NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
devemu_pci_device_db_host_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 
29 #include <doca_argp.h>
30 #include <doca_error.h>
31 #include <doca_dev.h>
32 #include <doca_log.h>
33 
34 #include <devemu_pci_host_common.h>
35 
36 DOCA_LOG_REGISTER(DEVEMU_PCI_DEVICE_DB_HOST::MAIN);
37 
38 /* Sample's Logic */
39 doca_error_t devemu_pci_device_db_host(const char *pci_address,
40  int vfio_group,
41  int region_idx,
42  uint16_t db_idx,
43  uint32_t db_value);
44 
45 /* Configuration struct */
46 struct devemu_pci_cfg {
47  char pci_address[DOCA_DEVINFO_PCI_ADDR_SIZE]; /* Emulated device PCI address */
48  int vfio_group; /* The VFIO group ID of the emulated device */
49  int region_idx; /* The index of the Doorbell region */
50  uint16_t db_idx; /* The index of the Doorbell */
51  uint32_t db_value; /* The value to write to the Doorbell */
52 };
53 
54 #ifndef DOCA_ARCH_DPU
55 
56 /*
57  * ARGP Callback - Handle PCI device address parameter
58  *
59  * @param [in]: Input parameter
60  * @config [in/out]: Program configuration context
61  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
62  */
63 static doca_error_t pci_callback(void *param, void *config)
64 {
65  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
66  const char *addr = (char *)param;
67 
69 }
70 
71 /*
72  * ARGP Callback - Handle VFIO Group ID parameter
73  *
74  * @param [in]: Input parameter
75  * @config [in/out]: Program configuration context
76  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
77  */
78 static doca_error_t vfio_group_callback(void *param, void *config)
79 {
80  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
81  int group_id = *(int *)param;
82 
83  if (group_id < 0) {
84  DOCA_LOG_ERR("Entered VFIO group ID, is invalid. Must be positive integer. Received %d", group_id);
86  }
87 
88  conf->vfio_group = group_id;
89 
90  return DOCA_SUCCESS;
91 }
92 
93 /*
94  * ARGP Callback - Handle DoorBell Region Index parameter
95  *
96  * @param [in]: Input parameter
97  * @config [in/out]: Program configuration context
98  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
99  */
100 static doca_error_t region_index_callback(void *param, void *config)
101 {
102  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
103  int region_index = *(int *)param;
104 
105  if (region_index < 0 || region_index >= PCI_TYPE_NUM_BAR_DB_REGIONS) {
106  DOCA_LOG_ERR(
107  "Entered region index, is invalid. Must be in [0, %d (PCI_TYPE_NUM_BAR_DB_REGIONS)). Received %d",
109  region_index);
111  }
112 
113  conf->region_idx = region_index;
114 
115  return DOCA_SUCCESS;
116 }
117 
118 /*
119  * ARGP Callback - Handle DoorBell Index parameter
120  *
121  * @param [in]: Input parameter
122  * @config [in/out]: Program configuration context
123  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
124  */
125 static doca_error_t db_index_callback(void *param, void *config)
126 {
127  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
128  int db_index = *(int *)param;
129 
130  if (db_index < 0 || db_index >= UINT16_MAX) {
131  DOCA_LOG_ERR("Entered DB index, is invalid. Must be in [0, %u (UINT16_MAX)). Received %d",
132  UINT16_MAX,
133  db_index);
135  }
136 
137  conf->db_idx = (int)db_index;
138 
139  return DOCA_SUCCESS;
140 }
141 
142 /*
143  * Register DB index command line parameter
144  *
145  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
146  */
148 {
149  struct doca_argp_param *db_index_param;
151 
152  result = doca_argp_param_create(&db_index_param);
153  if (result != DOCA_SUCCESS) {
154  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
155  return result;
156  }
157  doca_argp_param_set_short_name(db_index_param, "d");
158  doca_argp_param_set_long_name(db_index_param, "db-index");
160  db_index_param,
161  "The index of the Doorbell to write to. The sample will write at byte offset (db-index * db-stride)");
164  result = doca_argp_register_param(db_index_param);
165  if (result != DOCA_SUCCESS) {
166  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
167  return result;
168  }
169 
170  return DOCA_SUCCESS;
171 }
172 
173 /*
174  * ARGP Callback - Handle DoorBell Value parameter
175  *
176  * @param [in]: Input parameter
177  * @config [in/out]: Program configuration context
178  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
179  */
180 static doca_error_t db_value_callback(void *param, void *config)
181 {
182  struct devemu_pci_cfg *conf = (struct devemu_pci_cfg *)config;
183 
184  conf->db_value = *(uint32_t *)param;
185 
186  return DOCA_SUCCESS;
187 }
188 
189 /*
190  * Register DB value command line parameter
191  *
192  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
193  */
195 {
196  struct doca_argp_param *db_value_param;
198 
199  result = doca_argp_param_create(&db_value_param);
200  if (result != DOCA_SUCCESS) {
201  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
202  return result;
203  }
204  doca_argp_param_set_short_name(db_value_param, "w");
205  doca_argp_param_set_long_name(db_value_param, "db-value");
206  doca_argp_param_set_description(db_value_param,
207  "A 4B value to write to the Doorbell. Will be written in Big Endian");
210  result = doca_argp_register_param(db_value_param);
211  if (result != DOCA_SUCCESS) {
212  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
213  return result;
214  }
215 
216  return DOCA_SUCCESS;
217 }
218 
219 /*
220  * Register the command line parameters for the sample
221  *
222  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
223  */
225 {
227 
229  if (result != DOCA_SUCCESS)
230  return result;
231 
233  if (result != DOCA_SUCCESS)
234  return result;
235 
237  "The index of the DB region as defined in devemu_pci_type_config.h. Integer",
239  if (result != DOCA_SUCCESS)
240  return result;
241 
243  if (result != DOCA_SUCCESS)
244  return result;
245 
247  if (result != DOCA_SUCCESS)
248  return result;
249 
250  return DOCA_SUCCESS;
251 }
252 
253 #endif // DOCA_ARCH_DPU
254 
255 /*
256  * Sample main function
257  *
258  * @argc [in]: command line arguments size
259  * @argv [in]: array of command line arguments
260  * @return: EXIT_SUCCESS on success and EXIT_FAILURE otherwise
261  */
262 int main(int argc, char **argv)
263 {
266  struct doca_log_backend *sdk_log;
267  int exit_status = EXIT_FAILURE;
268 
269  /* Set the default configuration values (Example values) */
273 
274  /* Register a logger backend */
276  if (result != DOCA_SUCCESS)
277  goto sample_exit;
278 
279  /* Register a logger backend for internal SDK errors and warnings */
280  result = doca_log_backend_create_with_file_sdk(stderr, &sdk_log);
281  if (result != DOCA_SUCCESS)
282  goto sample_exit;
284  if (result != DOCA_SUCCESS)
285  goto sample_exit;
286 
287  DOCA_LOG_INFO("Starting the sample");
288 
289 #ifndef DOCA_ARCH_DPU
290 
292  if (result != DOCA_SUCCESS) {
293  DOCA_LOG_ERR("Failed to init ARGP resources: %s", doca_error_get_descr(result));
294  goto sample_exit;
295  }
297  if (result != DOCA_SUCCESS) {
298  DOCA_LOG_ERR("Failed to register sample command line parameters: %s", doca_error_get_descr(result));
299  goto argp_cleanup;
300  }
301  result = doca_argp_start(argc, argv);
302  if (result != DOCA_SUCCESS) {
303  DOCA_LOG_ERR("Failed to parse sample input: %s", doca_error_get_descr(result));
304  goto argp_cleanup;
305  }
306 
312  if (result != DOCA_SUCCESS) {
313  DOCA_LOG_ERR("devemu_pci_device_db_host() encountered an error: %s", doca_error_get_descr(result));
314  goto argp_cleanup;
315  }
316 
317  exit_status = EXIT_SUCCESS;
318 
319 argp_cleanup:
321 
322 #else // DOCA_ARCH_DPU
323  (void)argc;
324  (void)argv;
325  (void)devemu_pci_cfg;
326 
327  DOCA_LOG_ERR("PCI Emulated Device DB Host can run only on the Host");
328  exit_status = EXIT_FAILURE;
329 
330 #endif // DOCA_ARCH_DPU
331 
332 sample_exit:
333  if (exit_status == EXIT_SUCCESS)
334  DOCA_LOG_INFO("Sample finished successfully");
335  else
336  DOCA_LOG_INFO("Sample finished with errors");
337  return exit_status;
338 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
static doca_error_t register_db_value_param(void)
static doca_error_t db_index_callback(void *param, void *config)
int main(int argc, char **argv)
static doca_error_t register_devemu_pci_params(void)
static doca_error_t region_index_callback(void *param, void *config)
DOCA_LOG_REGISTER(DEVEMU_PCI_DEVICE_DB_HOST::MAIN)
static doca_error_t pci_callback(void *param, void *config)
static doca_error_t vfio_group_callback(void *param, void *config)
doca_error_t devemu_pci_device_db_host(const char *pci_address, int vfio_group, int region_idx, uint16_t db_idx, uint32_t db_value)
static doca_error_t register_db_index_param(void)
static doca_error_t db_value_callback(void *param, void *config)
doca_error_t register_vfio_group_param(doca_argp_param_cb_t vfio_group_callback)
doca_error_t register_region_index_param(const char *description, doca_argp_param_cb_t region_callback)
doca_error_t register_emulated_pci_address_param(doca_argp_param_cb_t pci_callback)
doca_error_t parse_emulated_pci_address(const char *addr, char *parsed_addr)
uintptr_t addr
uint32_t db_value
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_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_INT
Definition: doca_argp.h:57
#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_INFO
Definition: doca_log.h:48
#define PCI_TYPE_NUM_BAR_DB_REGIONS
char pci_address[DOCA_DEVINFO_PCI_ADDR_SIZE]