NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
devemu_pci_device_msix_dpu_sample.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 <signal.h>
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <string.h>
30 
31 #include <doca_ctx.h>
32 #include <doca_devemu_pci.h>
33 #include <doca_dev.h>
34 #include <doca_error.h>
35 #include <doca_log.h>
36 #include <doca_dpa.h>
37 
38 #include <common.h>
39 #include <devemu_pci_common.h>
40 
41 #define MSIX_TABLE_REGION_INDEX 0
42 
43 DOCA_LOG_REGISTER(DEVEMU_PCI_DEVICE_MSIX_DPU);
44 
45 /*
46  * A struct that includes all needed info on registered kernels and is initialized during linkage by DPACC.
47  * Variable name should be the token passed to DPACC with --app-name parameter.
48  */
49 extern struct doca_dpa_app *devemu_pci_sample_app;
50 
55 
56 /*
57  * Create an MSI-X object for the given index
58  *
59  * @resources [in]: The sample resources
60  * @msix_idx [in]: MSI-X vector index
61  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
62  */
64 {
66 
67  const struct bar_region_config *msix_table_region = &msix_table_configs[MSIX_TABLE_REGION_INDEX];
68 
70  msix_table_region->bar_id,
71  msix_table_region->start_address,
72  msix_idx,
73  /*dpa_user_data=*/0x0,
74  &resources->data_path.msix);
75  if (result != DOCA_SUCCESS) {
76  DOCA_LOG_ERR("Failed to create MSI-X to be used in DPA");
77  return result;
78  }
79 
80  result = doca_devemu_pci_msix_get_dpa_handle(resources->data_path.msix, &resources->data_path.msix_handle);
81  if (result != DOCA_SUCCESS) {
82  DOCA_LOG_ERR("Failed to get MSI-X DPA handle");
83  return result;
84  }
85 
86  return result;
87 }
88 
89 /*
90  * Run DOCA Device Emulation MSI-X DPU sample
91  *
92  * @pci_address [in]: Device PCI address
93  * @emulated_dev_vuid [in]: VUID of the emulated device
94  * @msix_idx [in]: MSI-X vector index
95  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
96  */
97 doca_error_t devemu_pci_device_msix_dpu(const char *pci_address, const char *emulated_dev_vuid, uint16_t msix_idx)
98 {
100  struct devemu_resources resources = {0};
101  const char pci_type_name[DOCA_DEVEMU_PCI_TYPE_NAME_LEN] = PCI_TYPE_NAME;
102  bool destroy_rep = false;
103 
105  if (result != DOCA_SUCCESS) {
106  DOCA_LOG_ERR("Unable to create progress engine: %s", doca_error_get_descr(result));
107  return result;
108  }
109 
110  result = doca_devemu_pci_type_create(pci_type_name, &resources.pci_type);
111  if (result != DOCA_SUCCESS) {
112  DOCA_LOG_ERR("Unable to create PCI type: %s", doca_error_get_descr(result));
113  devemu_resources_cleanup(&resources, destroy_rep);
114  return result;
115  }
116 
117  result = find_supported_device(pci_address,
118  resources.pci_type,
120  &resources.dev);
121  if (result != DOCA_SUCCESS) {
122  devemu_resources_cleanup(&resources, destroy_rep);
123  return result;
124  }
125 
126  /* Set PCIe configuration space values */
128  if (result != DOCA_SUCCESS) {
129  devemu_resources_cleanup(&resources, destroy_rep);
130  return result;
131  }
132 
133  /* Initialize DPA context */
135  if (result != DOCA_SUCCESS) {
136  devemu_resources_cleanup(&resources, destroy_rep);
137  return result;
138  }
139 
140  /* Find existing emulated device */
141  result = find_emulated_device(resources.pci_type, emulated_dev_vuid, &resources.rep);
142  if (result != DOCA_SUCCESS) {
143  DOCA_LOG_ERR("Unable to find PCI emulated device representor: %s", doca_error_get_descr(result));
144  devemu_resources_cleanup(&resources, destroy_rep);
145  return result;
146  }
147 
148  /* Create emulated device context */
150  if (result != DOCA_SUCCESS) {
151  DOCA_LOG_ERR("Unable to create PCI emulated device context: %s", doca_error_get_descr(result));
152  devemu_resources_cleanup(&resources, destroy_rep);
153  return result;
154  }
155 
157  if (result != DOCA_SUCCESS) {
158  DOCA_LOG_ERR("Failed to set PCI emulated device context datapath on DPA: %s",
160  devemu_resources_cleanup(&resources, destroy_rep);
161  return result;
162  }
163 
165  if (result != DOCA_SUCCESS) {
166  DOCA_LOG_ERR("Unable to start PCI emulated device context: %s", doca_error_get_descr(result));
167  devemu_resources_cleanup(&resources, destroy_rep);
168  return result;
169  }
170 
171  /* Defer assignment so that cleanup does not stop the context in case it was not started */
173 
175  if (result != DOCA_SUCCESS) {
176  DOCA_LOG_ERR("Unable to get hotplug state: %s", doca_error_get_descr(result));
177  devemu_resources_cleanup(&resources, destroy_rep);
178  return result;
179  }
180 
181  if (resources.hotplug_state != DOCA_DEVEMU_PCI_HP_STATE_POWER_ON) {
182  DOCA_LOG_ERR(
183  "Expected hotplug state to be DOCA_DEVEMU_PCI_HP_STATE_POWER_ON instead current state is %s",
184  hotplug_state_to_string(resources.hotplug_state));
185  devemu_resources_cleanup(&resources, destroy_rep);
186  return DOCA_ERROR_BAD_STATE;
187  }
188 
189  result = create_msix_object(&resources, msix_idx);
190  if (result != DOCA_SUCCESS) {
191  devemu_resources_cleanup(&resources, destroy_rep);
192  return result;
193  }
194 
195  DOCA_LOG_INFO("Raising MSI-X at index %u", msix_idx);
196 
197  uint64_t rpc_ret;
198  result = doca_dpa_rpc(resources.dpa, &raise_msix_rpc, &rpc_ret, resources.data_path.msix_handle);
199  if (result != DOCA_SUCCESS) {
200  DOCA_LOG_ERR("Raise MSI-X RPC execution failed");
201  devemu_resources_cleanup(&resources, destroy_rep);
202  return result;
203  }
204 
205  DOCA_LOG_INFO("MSI-X raised successfully");
206 
207  /* Clean and destroy all relevant objects */
208  devemu_resources_cleanup(&resources, destroy_rep);
209 
210  return result;
211 }
int32_t result
doca_error_t init_dpa(struct devemu_resources *resources, struct doca_dpa_app *dpa_app)
void devemu_resources_cleanup(struct devemu_resources *resources, bool destroy_rep)
DOCA_LOG_REGISTER(DEVEMU_PCI_DEVICE_MSIX_DPU)
doca_error_t create_msix_object(struct devemu_resources *resources, uint16_t msix_idx)
#define MSIX_TABLE_REGION_INDEX
struct doca_dpa_app * devemu_pci_sample_app
doca_dpa_func_t raise_msix_rpc
doca_error_t devemu_pci_device_msix_dpu(const char *pci_address, const char *emulated_dev_vuid, uint16_t msix_idx)
#define PCI_TYPE_NAME
struct rdma_resources resources
DOCA_STABLE doca_error_t doca_ctx_start(struct doca_ctx *ctx)
Finalizes all configurations, and starts the DOCA CTX.
DOCA_EXPERIMENTAL doca_error_t doca_ctx_set_datapath_on_dpa(struct doca_ctx *ctx, struct doca_dpa *dpa_dev)
This function binds the DOCA context to a dpa device.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_type_create(const char *name, struct doca_devemu_pci_type **pci_type)
Create a stopped DOCA devemu PCI type.
#define DOCA_DEVEMU_PCI_TYPE_NAME_LEN
Maximal length for the NULL terminated string that describe the name of the emulated PCI device type.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_cap_type_is_hotplug_supported(const struct doca_devinfo *devinfo, const struct doca_devemu_pci_type *pci_type, uint8_t *supported)
Get the hotplug capability of the device for a given DOCA devemu PCI type.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_dev_get_hotplug_state(struct doca_devemu_pci_dev *pci_dev, enum doca_devemu_pci_hotplug_state *state)
Get the hotplug state of the DOCA devemu PCI device.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_msix_create_on_dpa(struct doca_devemu_pci_dev *pci_dev, uint8_t bar_id, uint64_t bar_start_addr, uint16_t msix_idx, uint64_t user_data_on_dpa, struct doca_devemu_pci_msix **msix)
Allocate DOCA devemu PCI device MSI-X context on DPA.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_dev_create(struct doca_devemu_pci_type *pci_type, struct doca_dev_rep *dev_rep, struct doca_pe *progress_engine, struct doca_devemu_pci_dev **pci_dev)
Allocate DOCA devemu PCI device.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_msix_get_dpa_handle(struct doca_devemu_pci_msix *msix, doca_dpa_dev_devemu_pci_msix_t *msix_handle)
Get the DPA handle for the DOCA devemu PCI device MSI-X.
DOCA_EXPERIMENTAL struct doca_ctx * doca_devemu_pci_dev_as_ctx(struct doca_devemu_pci_dev *pci_dev)
Convert DOCA devemu PCI device instance into DOCA context.
@ DOCA_DEVEMU_PCI_HP_STATE_POWER_ON
DOCA_EXPERIMENTAL doca_error_t doca_dpa_rpc(struct doca_dpa *dpa, doca_dpa_func_t *func, uint64_t *retval,...)
RPC to run DPA kernel.
void() doca_dpa_func_t(void)
Generic function pointer type.
Definition: doca_dpa.h:118
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_BAD_STATE
Definition: doca_error.h:56
@ DOCA_SUCCESS
Definition: doca_error.h:38
#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_STABLE doca_error_t doca_pe_create(struct doca_pe **pe)
Creates DOCA progress engine.
doca_error_t configure_and_start_pci_type(struct doca_devemu_pci_type *pci_type, struct doca_dev *dev)
const char * hotplug_state_to_string(enum doca_devemu_pci_hotplug_state hotplug_state)
doca_error_t find_emulated_device(struct doca_devemu_pci_type *pci_type, const char *vuid, struct doca_dev_rep **rep)
doca_error_t find_supported_device(const char *dev_name, const struct doca_devemu_pci_type *pci_type, emulation_supported_cb_t has_support, struct doca_dev **dev)
static const struct bar_region_config msix_table_configs[PCI_TYPE_NUM_BAR_MSIX_TABLE_REGIONS]
struct doca_pe * pe
Definition: rdma_common.h:86