NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
devemu_pci_device_dma_host_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 <devemu_pci_common.h>
27 
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <linux/vfio.h>
31 #include <sys/ioctl.h>
32 #include <sys/mman.h>
33 #include <stdbool.h>
34 #include <stdint.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 #include <common.h>
39 #include <doca_error.h>
40 #include <doca_log.h>
41 
42 #include <devemu_pci_host_common.h>
43 
44 #define MEM_BUF_LEN (4 * 1024) /* Mem buffer size. It's the same as DPU side */
45 
46 DOCA_LOG_REGISTER(DEVEMU_PCI_DEVICE_DMA_HOST);
47 
48 /*
49  * Allocate memory for DMA
50  *
51  * @resources [in]: The sample resources
52  * @len [in]: The length of memory to allocate
53  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
54  */
56 {
57  resources->dma_mem.size = len;
58  resources->dma_mem.mem =
59  mmap(0, resources->dma_mem.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
60  if (resources->dma_mem.mem == MAP_FAILED) {
61  DOCA_LOG_ERR("Failed to allocate(mmap) memory");
62  return DOCA_ERROR_NO_MEMORY;
63  }
64  return DOCA_SUCCESS;
65 }
66 
67 /*
68  * IOMMU DMA map memory
69  *
70  * @resources [in]: The sample resources
71  * @iova [in]: The IOVA DMA memory mapped to
72  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
73  */
75 {
76  struct vfio_iommu_type1_dma_map dma_map = {0};
77  dma_map.argsz = sizeof(dma_map);
78  dma_map.vaddr = (uint64_t)resources->dma_mem.mem;
79  dma_map.size = resources->dma_mem.size;
80  dma_map.iova = iova;
81  dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
82  int status = ioctl(resources->container_fd, VFIO_IOMMU_MAP_DMA, &dma_map);
83  if (status != 0) {
84  DOCA_LOG_ERR("Failed to VFIO_IOMMU_MAP_DMA. Status=%d, errno=%d", status, errno);
85  return DOCA_ERROR_DRIVER;
86  }
87  return DOCA_SUCCESS;
88 }
89 
90 /*
91  * IOMMU DMA unmap memory
92  *
93  * @resources [in]: The sample resources
94  * @iova [in]: The IOVA DMA memory mapped to
95  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
96  */
98 {
99  /* DMA unmap */
100  struct vfio_iommu_type1_dma_unmap dma_unmap = {0};
101  dma_unmap.argsz = sizeof(dma_unmap);
102  dma_unmap.iova = iova;
103  dma_unmap.size = resources->dma_mem.size;
104  int status = ioctl(resources->container_fd, VFIO_IOMMU_UNMAP_DMA, &dma_unmap);
105  if (status != 0) {
106  DOCA_LOG_ERR("Failed to VFIO_IOMMU_UNMAP_DMA. Status=%d, errno=%d", status, errno);
107  return DOCA_ERROR_DRIVER;
108  }
109  return DOCA_SUCCESS;
110 }
111 
112 /*
113  * Run DOCA Device Emulation DMA Host sample
114  *
115  * @pci_address [in]: Emulated device PCI address
116  * @vfio_group [in]: VFIO group ID
117  * @write_data [in]: The data to write
118  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
119  */
120 doca_error_t devemu_pci_device_dma_host(const char *pci_address, int vfio_group, const char *write_data)
121 {
123  uint64_t iova = 0x1000000;
124  struct devemu_host_resources resources = {0};
125 
126  resources.container_fd = -1;
127  resources.group_fd = -1;
128  resources.device_fd = -1;
129 
130  result = init_vfio_device(&resources, vfio_group, pci_address);
131  if (result != DOCA_SUCCESS) {
133  return result;
134  }
135 
137  if (result != DOCA_SUCCESS) {
138  DOCA_LOG_ERR("Failed to allocate DMA memory");
140  return result;
141  }
142 
143  result = map_dma_mem(&resources, iova);
144  if (result != DOCA_SUCCESS) {
145  DOCA_LOG_ERR("Failed to DMA map memory to container");
147  return DOCA_ERROR_DRIVER;
148  }
149  DOCA_LOG_INFO("Allocated DMA memory(IOVA): %#lx", iova);
150 
151  /* Write the data */
152  memcpy(resources.dma_mem.mem, write_data, MEM_BUF_LEN);
153  DOCA_LOG_INFO("Write to DMA memory: %s", write_data);
154 
155  /* Read the data, till having different content from DPU */
156  while (1) {
157  sleep(2);
158  DOCA_LOG_INFO("Wait for new DMA data from DPU--- ---");
159  if (memcmp(resources.dma_mem.mem, write_data, MEM_BUF_LEN) == 0)
160  continue;
161 
162  DOCA_LOG_INFO("Read new data from DPU: %s", (char *)(resources.dma_mem.mem));
163  break;
164  };
165 
166  /* DMA unmap the memory*/
167  result = unmap_dma_mem(&resources, iova);
168  if (result != DOCA_SUCCESS) {
169  DOCA_LOG_ERR("Failed to DMA unmap memory to container");
171  return DOCA_ERROR_DRIVER;
172  }
173 
175  return DOCA_SUCCESS;
176 }
int32_t result
doca_error_t devemu_pci_device_dma_host(const char *pci_address, int vfio_group, const char *write_data)
static doca_error_t allocate_dma_mem(struct devemu_host_resources *resources, int len)
DOCA_LOG_REGISTER(DEVEMU_PCI_DEVICE_DMA_HOST)
static doca_error_t unmap_dma_mem(struct devemu_host_resources *resources, uint64_t iova)
static doca_error_t map_dma_mem(struct devemu_host_resources *resources, uint64_t iova)
void devemu_host_resources_cleanup(struct devemu_host_resources *resources)
doca_error_t init_vfio_device(struct devemu_host_resources *resources, int vfio_group, const char *pci_address)
doca_dpa_dev_mmap_t mmap
uint64_t len
struct rdma_resources resources
enum doca_error doca_error_t
DOCA API return codes.
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
@ DOCA_ERROR_DRIVER
Definition: doca_error.h:59
#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