NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
devemu_pci_device_dma_dpu_main.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29 
30 #include <doca_argp.h>
31 #include <doca_error.h>
32 #include <doca_dev.h>
33 #include <doca_log.h>
34 
35 #include <devemu_pci_common.h>
36 
37 #define MEM_BUF_LEN (4 * 1024) /* Mem buffer size. It's the same as Host side */
38 
39 DOCA_LOG_REGISTER(DEVEMU_PCI_DEVICE_DMA_DPU::MAIN);
40 
41 /* Sample's Logic */
42 doca_error_t devemu_pci_device_dma_dpu(const char *pci_address,
43  const char *devemu_name,
44  const char *emulated_dev_vuid,
45  uint64_t host_dma_mem_iova,
46  const char *write_data);
47 
48 /* Configuration struct */
49 struct devemu_pci_cfg {
50  char devemu_manager_pci_address[DOCA_DEVINFO_PCI_ADDR_SIZE]; /* Emulated device manager PCI address */
51  char dma_dev_name[DOCA_DEVINFO_IBDEV_NAME_SIZE]; /* DMA device name */
52  char vuid[DOCA_DEVINFO_REP_VUID_SIZE]; /* VUID of emulated device */
53  uint64_t host_dma_mem_iova; /* IOVA of host DMA memory */
54  char write_data[MEM_BUF_LEN]; /* Data to write to host memory */
55 };
56 
57 #ifdef DOCA_ARCH_DPU
58 
59 /*
60  * ARGP Callback - Handle IB device name parameter
61  *
62  * @param [in]: Input parameter
63  * @config [in/out]: Program configuration context
64  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
65  */
66 static doca_error_t device_name_callback(void *param, void *config)
67 {
68  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
69  char *device_name = (char *)param;
70 
71  int len = strnlen(device_name, DOCA_DEVINFO_IBDEV_NAME_SIZE);
73  DOCA_LOG_ERR("Entered IB device name exceeding the maximum size of %d",
76  }
77 
78  strncpy(conf->dma_dev_name, device_name, len + 1);
79 
80  return DOCA_SUCCESS;
81 }
82 
83 /*
84  * ARGP Callback - Handle PCI device address parameter
85  *
86  * @param [in]: Input parameter
87  * @config [in/out]: Program configuration context
88  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
89  */
90 static doca_error_t pci_callback(void *param, void *config)
91 {
92  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
93  const char *addr = (char *)param;
94 
96 }
97 
98 /*
99  * ARGP Callback - Handle VUID parameter
100  *
101  * @param [in]: Input parameter
102  * @config [in/out]: Program configuration context
103  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
104  */
105 static doca_error_t vuid_callback(void *param, void *config)
106 {
107  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
108  const char *vuid = (char *)param;
109 
110  return parse_vuid(vuid, conf->vuid);
111 }
112 
113 /*
114  * ARGP Callback - Handle mem address parameter
115  *
116  * @param [in]: Input parameter
117  * @config [in/out]: Program configuration context
118  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
119  */
120 static doca_error_t mem_address_callback(void *param, void *config)
121 {
122  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
123  const char *mem_addr = (char *)param;
124  int len = strlen(mem_addr);
125 
126  if (len <= 2 || mem_addr[0] != '0' || tolower(mem_addr[1]) != 'x' ||
127  sscanf(mem_addr + 2, "%lx", &conf->host_dma_mem_iova) != 1) {
128  DOCA_LOG_ERR(
129  "Entered host DMA memory address does not match supported formats: 0x12345678 or 0X12345678");
131  }
132  return DOCA_SUCCESS;
133 }
134 
135 /*
136  * ARGP Callback - Handle Stateful Region Index parameter
137  *
138  * @param [in]: Input parameter
139  * @config [in/out]: Program configuration context
140  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
141  */
142 static doca_error_t write_data_callback(void *param, void *config)
143 {
144  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
145  const char *write_data = (char *)param;
146  int data_len = strnlen(write_data, MEM_BUF_LEN) + 1;
147 
148  /* Check using > to make static code analysis satisfied */
149  if (data_len > MEM_BUF_LEN) {
150  DOCA_LOG_ERR("Entered write data exceeds max stateful region size of %d", MEM_BUF_LEN - 1);
152  }
153 
154  strncpy(conf->write_data, write_data, data_len - 1);
155  conf->write_data[data_len - 1] = 0;
156 
157  return DOCA_SUCCESS;
158 }
159 
160 /*
161  * Register device emulation manager PCI address command line parameter
162  *
163  * @pci_callback [in]: Callback called for parsing the device emulation manager PCI address command line param
164  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
165  */
166 doca_error_t register_devemu_manager_pci_address_param(doca_argp_param_cb_t pci_callback)
167 {
168  struct doca_argp_param *param;
170 
171  /* Create and register device emulation manager PCI address param */
172  result = doca_argp_param_create(&param);
173  if (result != DOCA_SUCCESS) {
174  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
175  return result;
176  }
177  doca_argp_param_set_short_name(param, "p");
178  doca_argp_param_set_long_name(param, "pci-addr");
180  param,
181  "The DOCA device emulation manager PCI address. Format: XXXX:XX:XX.X or XX:XX.X");
185  if (result != DOCA_SUCCESS) {
186  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
187  return result;
188  }
189 
190  return DOCA_SUCCESS;
191 }
192 
193 /*
194  * Register DMA IB device name command line parameter
195  *
196  * @device_name_callback [in]: Callback called for parsing the DMA IB device name command line param
197  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
198  */
199 static doca_error_t register_dma_device_name_param(doca_argp_param_cb_t device_name_callback)
200 {
201  struct doca_argp_param *param;
203 
204  /* Create and register DMA IB device name param */
205  result = doca_argp_param_create(&param);
206  if (result != DOCA_SUCCESS) {
207  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
208  return result;
209  }
210  doca_argp_param_set_short_name(param, "d");
211  doca_argp_param_set_long_name(param, "device-name");
212  doca_argp_param_set_description(param, "The IB device name to be used for DMA operations");
216  if (result != DOCA_SUCCESS) {
217  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
218  return result;
219  }
220 
221  return DOCA_SUCCESS;
222 }
223 
224 /*
225  * Register write data command line parameter
226  *
227  * @write_data_callback [in]: Callback called for parsing the write data command line param
228  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
229  */
231 {
232  struct doca_argp_param *write_data_param;
234 
235  result = doca_argp_param_create(&write_data_param);
236  if (result != DOCA_SUCCESS) {
237  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
238  return result;
239  }
240  doca_argp_param_set_short_name(write_data_param, "w");
241  doca_argp_param_set_long_name(write_data_param, "write-data");
243  write_data_param,
244  "Data to write to the host memory, if not provided then the sample will do a read instead. ASCII string");
247  result = doca_argp_register_param(write_data_param);
248  if (result != DOCA_SUCCESS) {
249  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
250  return result;
251  }
252 
253  return DOCA_SUCCESS;
254 }
255 
256 /*
257  * Register host memory address command line parameter
258  *
259  * @mem_address_callback [in]: Callback called for parsing the memory address command line param
260  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
261  */
262 doca_error_t register_mem_address_param(doca_argp_param_cb_t mem_address_callback)
263 {
264  struct doca_argp_param *param;
266 
267  result = doca_argp_param_create(&param);
268  if (result != DOCA_SUCCESS) {
269  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
270  return result;
271  }
272  doca_argp_param_set_short_name(param, "a");
273  doca_argp_param_set_long_name(param, "addr");
274  doca_argp_param_set_description(param, "Host DMA memory IOVA address. Format: 0x12345678 or 0X12345678");
275  doca_argp_param_set_callback(param, mem_address_callback);
278  if (result != DOCA_SUCCESS) {
279  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
280  return result;
281  }
282 
283  return DOCA_SUCCESS;
284 }
285 
286 /*
287  * Register the command line parameters for the sample
288  *
289  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
290  */
292 {
294 
295  result = register_devemu_manager_pci_address_param(pci_callback);
296  if (result != DOCA_SUCCESS)
297  return result;
298 
299  result = register_dma_device_name_param(device_name_callback);
300  if (result != DOCA_SUCCESS)
301  return result;
302 
303  result = register_vuid_param("DOCA Devemu emulated device VUID.", vuid_callback);
304  if (result != DOCA_SUCCESS)
305  return result;
306 
307  result = register_mem_address_param(mem_address_callback);
308  if (result != DOCA_SUCCESS)
309  return result;
310 
312  if (result != DOCA_SUCCESS)
313  return result;
314 
315  return DOCA_SUCCESS;
316 }
317 
318 #endif // DOCA_ARCH_DPU
319 
320 /*
321  * Sample main function
322  *
323  * @argc [in]: command line arguments size
324  * @argv [in]: array of command line arguments
325  * @return: EXIT_SUCCESS on success and EXIT_FAILURE otherwise
326  */
327 int main(int argc, char **argv)
328 {
331  struct doca_log_backend *sdk_log;
332  int exit_status = EXIT_FAILURE;
333 
334  /* Set the default configuration values (Example values) */
335  strcpy(devemu_pci_cfg.devemu_manager_pci_address, "0000:03:00.0");
336  strcpy(devemu_pci_cfg.dma_dev_name, "");
337  strcpy(devemu_pci_cfg.vuid, "");
338  strcpy(devemu_pci_cfg.write_data, "This is a sample piece of data from DPU!");
339  devemu_pci_cfg.host_dma_mem_iova = 0x1000000;
340 
341  /* Register a logger backend */
343  if (result != DOCA_SUCCESS)
344  goto sample_exit;
345  /* Register a logger backend for internal SDK errors and warnings */
346  result = doca_log_backend_create_with_file_sdk(stderr, &sdk_log);
347  if (result != DOCA_SUCCESS)
348  goto sample_exit;
350  if (result != DOCA_SUCCESS)
351  goto sample_exit;
352 
353  DOCA_LOG_INFO("Starting the sample");
354 
355 #ifdef DOCA_ARCH_DPU
357  if (result != DOCA_SUCCESS) {
358  DOCA_LOG_ERR("Failed to init ARGP resources: %s", doca_error_get_descr(result));
359  goto sample_exit;
360  }
362  if (result != DOCA_SUCCESS) {
363  DOCA_LOG_ERR("Failed to register sample command line parameters: %s", doca_error_get_descr(result));
364  goto argp_cleanup;
365  }
366  result = doca_argp_start(argc, argv);
367  if (result != DOCA_SUCCESS) {
368  DOCA_LOG_ERR("Failed to parse sample input: %s", doca_error_get_descr(result));
369  goto argp_cleanup;
370  }
371 
372  if (*devemu_pci_cfg.vuid == 0) {
373  DOCA_LOG_ERR("The VUID parameter is missing");
374  goto argp_cleanup;
375  }
376 
382  if (result != DOCA_SUCCESS) {
383  DOCA_LOG_ERR("devemu_pci_device_dma_dpu() encountered an error: %s", doca_error_get_descr(result));
384  goto argp_cleanup;
385  }
386 
387  exit_status = EXIT_SUCCESS;
388 
389 argp_cleanup:
391 
392 #else // DOCA_ARCH_DPU
393  (void)argc;
394  (void)argv;
395 
396  DOCA_LOG_ERR("PCI Emulated Device DMA DPU can run only on the DPU");
397  exit_status = EXIT_FAILURE;
398 
399 #endif // DOCA_ARCH_DPU
400 
401 sample_exit:
402  if (exit_status == EXIT_SUCCESS)
403  DOCA_LOG_INFO("Sample finished successfully");
404  else
405  DOCA_LOG_INFO("Sample finished with errors");
406  return exit_status;
407 }
#define NULL
Definition: __stddef_null.h:26
static doca_error_t vuid_callback(void *param, void *config)
int32_t result
doca_error_t parse_pci_address(const char *addr, char *parsed_addr)
doca_error_t register_vuid_param(const char *description, doca_argp_param_cb_t vuid_callback)
doca_error_t parse_vuid(const char *vuid, char *parsed_vuid)
static doca_error_t register_devemu_pci_params(void)
static doca_error_t pci_callback(void *param, void *config)
int main(int argc, char **argv)
DOCA_LOG_REGISTER(DEVEMU_PCI_DEVICE_DMA_DPU::MAIN)
doca_error_t devemu_pci_device_dma_dpu(const char *pci_address, const char *devemu_name, const char *emulated_dev_vuid, uint64_t host_dma_mem_iova, const char *write_data)
#define MEM_BUF_LEN
static doca_error_t write_data_callback(void *param, void *config)
static doca_error_t register_write_data_param(doca_argp_param_cb_t write_data_callback)
uintptr_t addr
uint64_t len
DOCA_EXPERIMENTAL void doca_argp_param_set_description(struct doca_argp_param *param, const char *description)
Set the description of the program param, used during program usage.
DOCA_EXPERIMENTAL void doca_argp_param_set_long_name(struct doca_argp_param *param, const char *name)
Set the long name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_start(int argc, char **argv)
Parse incoming arguments (cmd line/json).
DOCA_EXPERIMENTAL doca_error_t doca_argp_init(const char *program_name, void *program_config)
Initialize the parser interface.
doca_error_t(* doca_argp_param_cb_t)(void *, void *)
Flag callback function type.
Definition: doca_argp.h:37
DOCA_EXPERIMENTAL void doca_argp_param_set_callback(struct doca_argp_param *param, doca_argp_param_cb_t callback)
Set the callback function of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_param_create(struct doca_argp_param **param)
Create new program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_type(struct doca_argp_param *param, enum doca_argp_type type)
Set the type of the param arguments.
DOCA_EXPERIMENTAL void doca_argp_param_set_short_name(struct doca_argp_param *param, const char *name)
Set the short name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_destroy(void)
ARG Parser destroy.
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_param(struct doca_argp_param *input_param)
Register a program flag.
@ DOCA_ARGP_TYPE_STRING
Definition: doca_argp.h:56
#define DOCA_DEVINFO_IBDEV_NAME_SIZE
Buffer size to hold Infiniband/RoCE device name. Including a null terminator.
Definition: doca_dev.h:309
#define DOCA_DEVINFO_REP_VUID_SIZE
Buffer size to hold VUID. Including a null terminator.
Definition: doca_dev.h:661
#define DOCA_DEVINFO_PCI_ADDR_SIZE
Buffer size to hold PCI BDF format: "XXXX:XX:XX.X". Including a null terminator.
Definition: doca_dev.h:313
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_SUCCESS
Definition: doca_error.h:38
DOCA_EXPERIMENTAL doca_error_t doca_log_backend_create_standard(void)
Create default, non configurable backend for application messages.
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
DOCA_EXPERIMENTAL doca_error_t doca_log_backend_create_with_file_sdk(FILE *fptr, struct doca_log_backend **backend)
Create a logging backend with a FILE* stream for SDK messages.
DOCA_EXPERIMENTAL doca_error_t doca_log_backend_set_sdk_level(struct doca_log_backend *backend, uint32_t level)
Set the log level limit for SDK logging backends.
@ DOCA_LOG_LEVEL_WARNING
Definition: doca_log.h:47
static doca_error_t device_name_callback(void *param, void *config)
Definition: pcc_core.c:549
char vuid[DOCA_DEVINFO_REP_VUID_SIZE]
char devemu_manager_pci_address[DOCA_DEVINFO_PCI_ADDR_SIZE]
char dma_dev_name[DOCA_DEVINFO_IBDEV_NAME_SIZE]