LCOV - code coverage report
Current view: top level - spdk/lib/vfio_user/host - vfio_user_pci.c (source / functions) Hit Total Coverage
Test: Combined Lines: 151 224 67.4 %
Date: 2024-07-13 11:15:58 Functions: 14 16 87.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 89 164 54.3 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2020 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : /*
       7                 :            :  * vfio-user transport for PCI devices.
       8                 :            :  */
       9                 :            : 
      10                 :            : #include "spdk/stdinc.h"
      11                 :            : #include "spdk/log.h"
      12                 :            : #include "spdk/env.h"
      13                 :            : #include "spdk/queue.h"
      14                 :            : #include "spdk/util.h"
      15                 :            : #include "spdk/vfio_user_pci.h"
      16                 :            : 
      17                 :            : #include "vfio_user_internal.h"
      18                 :            : 
      19                 :            : static uint32_t g_vfio_dev_id;
      20                 :            : 
      21                 :            : int
      22                 :        662 : spdk_vfio_user_pci_bar_access(struct vfio_device *dev, uint32_t index, uint64_t offset,
      23                 :            :                               size_t len, void *buf, bool is_write)
      24                 :            : {
      25                 :        662 :         struct vfio_pci_region *region = &dev->regions[index];
      26                 :            :         uint32_t i;
      27                 :            : 
      28         [ -  + ]:        662 :         if (offset + len > region->size) {
      29                 :          0 :                 return -EINVAL;
      30                 :            :         }
      31                 :            : 
      32   [ +  +  +  - ]:        662 :         if (!region->nr_mmaps || (offset < region->mmaps[0].offset)) {
      33                 :        662 :                 return vfio_user_dev_mmio_access(dev, index, offset, len, buf, is_write);
      34                 :            :         }
      35                 :            : 
      36                 :            :         /* SPARSE MMAP */
      37         [ #  # ]:          0 :         for (i = 0; i < region->nr_mmaps; i++) {
      38         [ #  # ]:          0 :                 if ((offset >= region->mmaps[i].offset) &&
      39         [ #  # ]:          0 :                     (offset + len <= region->mmaps[i].offset + region->mmaps[i].size)) {
      40         [ #  # ]:          0 :                         assert(region->mmaps[i].mem != NULL);
      41                 :          0 :                         void *bar_addr = region->mmaps[i].mem + offset - region->mmaps[i].offset;
      42         [ #  # ]:          0 :                         if (is_write) {
      43   [ #  #  #  # ]:          0 :                                 memcpy(bar_addr, buf, len);
      44                 :            :                         } else {
      45   [ #  #  #  # ]:          0 :                                 memcpy(buf, bar_addr, len);
      46                 :            :                         }
      47                 :          0 :                         return 0;
      48                 :            :                 }
      49                 :            :         }
      50                 :            : 
      51                 :          0 :         return -EFAULT;
      52                 :            : }
      53                 :            : 
      54                 :            : static int
      55                 :         56 : vfio_add_mr(struct vfio_device *dev, struct vfio_memory_region *mr)
      56                 :            : {
      57         [ -  + ]:         56 :         if (dev->nr_mrs == VFIO_MAXIMUM_MEMORY_REGIONS) {
      58                 :          0 :                 SPDK_ERRLOG("Maximum supported memory regions %d\n", VFIO_MAXIMUM_MEMORY_REGIONS);
      59                 :          0 :                 return -EINVAL;
      60                 :            :         }
      61                 :            : 
      62                 :         56 :         TAILQ_INSERT_TAIL(&dev->mrs_head, mr, link);
      63                 :         56 :         dev->nr_mrs++;
      64                 :            : 
      65   [ -  +  +  + ]:         56 :         SPDK_DEBUGLOG(vfio_pci, "Add memory region: FD %d, VADDR 0x%lx, IOVA 0x%lx, Size 0x%lx\n",
      66                 :            :                       mr->fd, mr->vaddr, mr->iova, mr->size);
      67                 :            : 
      68                 :         56 :         return 0;
      69                 :            : }
      70                 :            : 
      71                 :            : static struct vfio_memory_region *
      72                 :        112 : vfio_get_mr(struct vfio_device *dev, uint64_t addr, size_t len)
      73                 :            : {
      74                 :            :         struct vfio_memory_region *mr, *tmp_mr;
      75                 :            : 
      76         [ +  + ]:        112 :         if (dev->nr_mrs == 0) {
      77                 :         37 :                 return false;
      78                 :            :         }
      79                 :            : 
      80         [ +  + ]:        175 :         TAILQ_FOREACH_SAFE(mr, &dev->mrs_head, link, tmp_mr) {
      81   [ +  +  -  + ]:        156 :                 if ((mr->vaddr == addr) || (mr->iova == addr)) {
      82                 :         56 :                         return mr;
      83                 :            :                 }
      84                 :            :         }
      85                 :            : 
      86                 :         19 :         return false;
      87                 :            : }
      88                 :            : 
      89                 :            : static void
      90                 :         56 : vfio_remove_mr(struct vfio_device *dev, uint64_t addr, size_t len)
      91                 :            : {
      92                 :            :         struct vfio_memory_region *mr, *tmp_mr;
      93                 :            : 
      94         [ +  - ]:         74 :         TAILQ_FOREACH_SAFE(mr, &dev->mrs_head, link, tmp_mr) {
      95   [ +  +  -  + ]:         74 :                 if ((mr->vaddr == addr) || (mr->iova == addr)) {
      96   [ -  +  +  + ]:         56 :                         SPDK_DEBUGLOG(vfio_pci, "Remove memory region: FD %d, VADDR 0x%lx, IOVA 0x%lx, Size 0x%lx\n",
      97                 :            :                                       mr->fd, mr->vaddr, mr->iova, mr->size);
      98         [ +  + ]:         56 :                         TAILQ_REMOVE(&dev->mrs_head, mr, link);
      99         [ -  + ]:         56 :                         assert(dev->nr_mrs > 0);
     100                 :         56 :                         dev->nr_mrs--;
     101                 :         56 :                         free(mr);
     102                 :         56 :                         return;
     103                 :            :                 }
     104                 :            :         }
     105                 :            : }
     106                 :            : 
     107                 :            : static int
     108                 :        112 : vfio_mr_map_notify(void *cb_ctx, struct spdk_mem_map *map,
     109                 :            :                    enum spdk_mem_map_notify_action action,
     110                 :            :                    void *vaddr, size_t size)
     111                 :            : {
     112                 :            :         int ret;
     113                 :        112 :         struct vfio_device *dev = cb_ctx;
     114                 :            :         struct vfio_memory_region *mr;
     115                 :          4 :         uint64_t offset;
     116                 :            : 
     117                 :        112 :         mr = vfio_get_mr(dev, (uint64_t)vaddr, size);
     118         [ +  + ]:        112 :         if (action == SPDK_MEM_MAP_NOTIFY_UNREGISTER) {
     119         [ -  + ]:         56 :                 if (!mr) {
     120                 :          0 :                         SPDK_ERRLOG("Memory region VADDR %p doesn't exist\n", vaddr);
     121                 :          0 :                         return -EEXIST;
     122                 :            :                 }
     123                 :            : 
     124                 :         56 :                 ret = vfio_user_dev_dma_map_unmap(dev, mr, false);
     125                 :            :                 /* remove the memory region */
     126                 :         56 :                 vfio_remove_mr(dev, (uint64_t)vaddr, size);
     127                 :         56 :                 return ret;
     128                 :            :         }
     129                 :            : 
     130                 :            :         /* SPDK_MEM_MAP_NOTIFY_REGISTER */
     131         [ -  + ]:         56 :         if (mr != NULL) {
     132                 :          0 :                 SPDK_ERRLOG("Memory region VADDR 0x%lx already exist\n", mr->vaddr);
     133                 :          0 :                 return -EEXIST;
     134                 :            :         }
     135                 :            : 
     136                 :         56 :         mr = calloc(1, sizeof(*mr));
     137         [ -  + ]:         56 :         if (mr == NULL) {
     138                 :          0 :                 return -ENOMEM;
     139                 :            :         }
     140                 :         56 :         mr->vaddr = (uint64_t)(uintptr_t)vaddr;
     141                 :         56 :         mr->iova = mr->vaddr;
     142                 :         56 :         mr->size = size;
     143                 :         56 :         mr->fd = spdk_mem_get_fd_and_offset(vaddr, &offset);
     144         [ -  + ]:         56 :         if (mr->fd < 0) {
     145                 :          0 :                 SPDK_ERRLOG("Error to get the memory map offset\n");
     146                 :          0 :                 free(mr);
     147                 :          0 :                 return -EFAULT;
     148                 :            :         }
     149                 :         56 :         mr->offset = offset;
     150                 :            : 
     151                 :         56 :         ret = vfio_add_mr(dev, mr);
     152         [ -  + ]:         56 :         if (ret) {
     153                 :          0 :                 free(mr);
     154                 :          0 :                 return ret;
     155                 :            :         }
     156                 :            : 
     157                 :         56 :         return vfio_user_dev_dma_map_unmap(dev, mr, true);
     158                 :            : }
     159                 :            : 
     160                 :            : static int
     161                 :         37 : vfio_device_dma_map(struct vfio_device *device)
     162                 :            : {
     163                 :         37 :         const struct spdk_mem_map_ops vfio_map_ops = {
     164                 :            :                 .notify_cb = vfio_mr_map_notify,
     165                 :            :                 .are_contiguous = NULL,
     166                 :            :         };
     167                 :            : 
     168                 :         37 :         device->map = spdk_mem_map_alloc((uint64_t)NULL, &vfio_map_ops, device);
     169         [ -  + ]:         37 :         if (device->map == NULL) {
     170                 :          0 :                 SPDK_ERRLOG("Failed to allocate memory map structure\n");
     171                 :          0 :                 return -EFAULT;
     172                 :            :         }
     173                 :            : 
     174                 :         37 :         return 0;
     175                 :            : }
     176                 :            : 
     177                 :            : static struct vfio_info_cap_header *
     178                 :         72 : vfio_device_get_info_cap(struct vfio_region_info *info, int cap)
     179                 :            : {
     180                 :            :         struct vfio_info_cap_header *h;
     181                 :            :         size_t offset;
     182                 :            : 
     183         [ -  + ]:         72 :         if ((info->flags & VFIO_REGION_INFO_FLAG_CAPS) == 0) {
     184                 :          0 :                 return NULL;
     185                 :            :         }
     186                 :            : 
     187                 :         72 :         offset = info->cap_offset;
     188         [ +  - ]:        107 :         while (offset != 0) {
     189                 :        107 :                 h = (struct vfio_info_cap_header *)((uintptr_t)info + offset);
     190         [ +  + ]:        107 :                 if (h->id == cap) {
     191                 :         72 :                         return h;
     192                 :            :                 }
     193                 :         35 :                 offset = h->next;
     194                 :            :         }
     195                 :            : 
     196                 :          0 :         return NULL;
     197                 :            : }
     198                 :            : 
     199                 :            : static int
     200                 :         72 : vfio_device_setup_sparse_mmaps(struct vfio_device *device, int index,
     201                 :            :                                struct vfio_region_info *info, int *fds)
     202                 :            : {
     203                 :            :         struct vfio_info_cap_header *hdr;
     204                 :            :         struct vfio_region_info_cap_sparse_mmap *sparse;
     205                 :         72 :         struct vfio_pci_region *region = &device->regions[index];
     206                 :         72 :         uint32_t i, j = 0;
     207                 :         72 :         int rc = 0, prot = 0;
     208                 :            : 
     209                 :         72 :         hdr = vfio_device_get_info_cap(info, VFIO_REGION_INFO_CAP_SPARSE_MMAP);
     210         [ -  + ]:         72 :         if (!hdr) {
     211                 :          0 :                 SPDK_NOTICELOG("Device doesn't have sparse mmap\n");
     212                 :          0 :                 return -EEXIST;
     213                 :            :         }
     214                 :            : 
     215                 :         72 :         sparse = SPDK_CONTAINEROF(hdr, struct vfio_region_info_cap_sparse_mmap, header);
     216         [ +  + ]:        144 :         for (i = 0; i < sparse->nr_areas; i++) {
     217         [ +  - ]:         72 :                 if (sparse->areas[i].size) {
     218                 :         72 :                         region->mmaps[j].offset = sparse->areas[i].offset;
     219                 :         72 :                         region->mmaps[j].size = sparse->areas[i].size;
     220                 :         72 :                         prot |= info->flags & VFIO_REGION_INFO_FLAG_READ ? PROT_READ : 0;
     221                 :         72 :                         prot |= info->flags & VFIO_REGION_INFO_FLAG_WRITE ? PROT_WRITE : 0;
     222         [ +  - ]:         72 :                         if (*fds) {
     223                 :         72 :                                 region->mmaps[j].mem = mmap(NULL, region->mmaps[j].size, prot, MAP_SHARED,
     224                 :         72 :                                                             fds[i], region->offset + region->mmaps[j].offset);
     225         [ -  + ]:         72 :                                 if (region->mmaps[j].mem == MAP_FAILED) {
     226                 :          0 :                                         SPDK_ERRLOG("Device SPARSE MMAP failed\n");
     227                 :          0 :                                         rc = -EIO;
     228                 :          0 :                                         goto out;
     229                 :            :                                 }
     230                 :            :                         } else {
     231   [ #  #  #  # ]:          0 :                                 SPDK_DEBUGLOG(vfio_pci, "No valid fd, skip mmap for bar %d region %u\n", index, i);
     232                 :            :                         }
     233   [ -  +  +  + ]:         72 :                         SPDK_DEBUGLOG(vfio_pci, "Sparse region %u, Size 0x%llx, Offset 0x%llx, Map addr %p\n",
     234                 :            :                                       i, sparse->areas[i].size, sparse->areas[i].offset,
     235                 :            :                                       region->mmaps[j].mem);
     236                 :         72 :                         j++;
     237                 :            :                 }
     238                 :            :         }
     239                 :         72 :         device->regions[index].nr_mmaps = j;
     240                 :         72 : out:
     241         [ +  + ]:        144 :         for (i = 0; i < sparse->nr_areas; i++) {
     242                 :         72 :                 close(fds[i]);
     243                 :            :         }
     244                 :            : 
     245                 :         72 :         return rc;
     246                 :            : }
     247                 :            : 
     248                 :            : static int
     249                 :          0 : vfio_device_map_region(struct vfio_device *device, struct vfio_pci_region *region, int fd)
     250                 :            : {
     251                 :          0 :         int prot = 0;
     252                 :            : 
     253                 :          0 :         prot |= region->flags & VFIO_REGION_INFO_FLAG_READ ? PROT_READ : 0;
     254                 :          0 :         prot |= region->flags & VFIO_REGION_INFO_FLAG_WRITE ? PROT_WRITE : 0;
     255                 :            : 
     256                 :          0 :         region->mmaps[0].offset = 0;
     257                 :          0 :         region->mmaps[0].size = region->size;
     258                 :            : 
     259                 :          0 :         region->mmaps[0].mem = mmap(NULL, region->size, prot, MAP_SHARED,
     260                 :          0 :                                     fd, region->offset);
     261                 :          0 :         close(fd);
     262         [ #  # ]:          0 :         if (region->mmaps[0].mem == MAP_FAILED) {
     263                 :          0 :                 SPDK_ERRLOG("Device Region MMAP failed\n");
     264                 :          0 :                 return -EFAULT;
     265                 :            :         }
     266   [ #  #  #  # ]:          0 :         SPDK_DEBUGLOG(vfio_pci, "Memory mapped to %p\n", region->mmaps[0].mem);
     267                 :          0 :         region->nr_mmaps = 1;
     268                 :            : 
     269                 :          0 :         return 0;
     270                 :            : }
     271                 :            : 
     272                 :            : static int
     273                 :         37 : vfio_device_map_bars_and_config_region(struct vfio_device *device)
     274                 :            : {
     275                 :            :         uint32_t i;
     276                 :            :         int ret;
     277                 :         37 :         size_t len = 4096;
     278                 :          2 :         int fds[VFIO_MAXIMUM_SPARSE_MMAP_REGIONS];
     279                 :            :         struct vfio_region_info *info;
     280                 :            :         uint8_t *buf;
     281                 :            : 
     282                 :         37 :         buf = calloc(1, len);
     283         [ -  + ]:         37 :         if (!buf) {
     284                 :          0 :                 return -ENOMEM;
     285                 :            :         }
     286                 :            : 
     287                 :         37 :         info = (struct vfio_region_info *)buf;
     288         [ +  + ]:        407 :         for (i = 0; i < device->pci_regions; i++) {
     289         [ -  + ]:        370 :                 memset(info, 0, len);
     290         [ -  + ]:        370 :                 memset(fds, 0, sizeof(fds));
     291                 :            : 
     292                 :        370 :                 info->index = i;
     293                 :        370 :                 ret = vfio_user_get_dev_region_info(device, info, len, fds, VFIO_MAXIMUM_SPARSE_MMAP_REGIONS);
     294         [ -  + ]:        370 :                 if (ret) {
     295                 :          0 :                         SPDK_ERRLOG("Device setup bar %d failed\n", ret);
     296                 :          0 :                         free(buf);
     297                 :          0 :                         return ret;
     298                 :            :                 }
     299                 :            : 
     300                 :        370 :                 device->regions[i].size = info->size;
     301                 :        370 :                 device->regions[i].offset = info->offset;
     302                 :        370 :                 device->regions[i].flags = info->flags;
     303                 :            : 
     304   [ -  +  +  + ]:        370 :                 SPDK_DEBUGLOG(vfio_pci, "Bar %d, Size 0x%llx, Offset 0x%llx, Flags 0x%x, Cap offset %u\n",
     305                 :            :                               i, info->size, info->offset, info->flags, info->cap_offset);
     306                 :            : 
     307                 :            :                 /* Setup MMAP if any */
     308   [ +  +  +  + ]:        370 :                 if (info->size && (info->flags & VFIO_REGION_INFO_FLAG_MMAP)) {
     309                 :            :                         /* try to map sparse memory region first */
     310                 :         72 :                         ret = vfio_device_setup_sparse_mmaps(device, i, info, fds);
     311         [ -  + ]:         72 :                         if (ret < 0) {
     312                 :          0 :                                 ret = vfio_device_map_region(device, &device->regions[i], fds[0]);
     313                 :            :                         }
     314                 :            : 
     315         [ -  + ]:         72 :                         if (ret != 0) {
     316                 :          0 :                                 SPDK_ERRLOG("Setup Device %s region %d failed\n", device->name, i);
     317                 :          0 :                                 free(buf);
     318                 :          0 :                                 return ret;
     319                 :            :                         }
     320                 :            :                 }
     321                 :            :         }
     322                 :            : 
     323                 :         37 :         free(buf);
     324                 :         37 :         return 0;
     325                 :            : }
     326                 :            : 
     327                 :            : static void
     328                 :         37 : vfio_device_unmap_bars(struct vfio_device *dev)
     329                 :            : {
     330                 :            :         uint32_t i, j;
     331                 :            :         struct vfio_pci_region *region;
     332                 :            : 
     333         [ +  + ]:        407 :         for (i = 0; i < dev->pci_regions; i++) {
     334                 :        370 :                 region = &dev->regions[i];
     335         [ +  + ]:        442 :                 for (j = 0; j < region->nr_mmaps; j++) {
     336         [ +  - ]:         72 :                         if (region->mmaps[j].mem) {
     337                 :         72 :                                 munmap(region->mmaps[j].mem, region->mmaps[j].size);
     338                 :            :                         }
     339                 :            :                 }
     340                 :            :         }
     341         [ -  + ]:         37 :         memset(dev->regions, 0, sizeof(dev->regions));
     342                 :         37 : }
     343                 :            : 
     344                 :            : struct vfio_device *
     345                 :         37 : spdk_vfio_user_setup(const char *path)
     346                 :            : {
     347                 :            :         int ret;
     348                 :         37 :         struct vfio_device *device = NULL;
     349                 :         37 :         struct vfio_user_device_info dev_info = {};
     350                 :            : 
     351                 :         37 :         device = calloc(1, sizeof(*device));
     352         [ -  + ]:         37 :         if (!device) {
     353                 :          0 :                 return NULL;
     354                 :            :         }
     355                 :         37 :         TAILQ_INIT(&device->mrs_head);
     356         [ -  + ]:         37 :         snprintf(device->path, PATH_MAX, "%s", path);
     357         [ -  + ]:         37 :         snprintf(device->name, sizeof(device->name), "vfio-user%u", g_vfio_dev_id++);
     358                 :            : 
     359                 :         37 :         ret = vfio_user_dev_setup(device);
     360         [ -  + ]:         37 :         if (ret) {
     361                 :          0 :                 free(device);
     362                 :          0 :                 SPDK_ERRLOG("Error to setup vfio-user via path %s\n", path);
     363                 :          0 :                 return NULL;
     364                 :            :         }
     365                 :            : 
     366                 :         37 :         ret = vfio_user_get_dev_info(device, &dev_info, sizeof(dev_info));
     367         [ -  + ]:         37 :         if (ret) {
     368                 :          0 :                 SPDK_ERRLOG("Device get info failed\n");
     369                 :          0 :                 goto cleanup;
     370                 :            :         }
     371                 :         37 :         device->pci_regions = dev_info.num_regions;
     372                 :         37 :         device->flags = dev_info.flags;
     373                 :            : 
     374                 :         37 :         ret = vfio_device_map_bars_and_config_region(device);
     375         [ -  + ]:         37 :         if (ret) {
     376                 :          0 :                 goto cleanup;
     377                 :            :         }
     378                 :            : 
     379                 :            :         /* Register DMA Region */
     380                 :         37 :         ret = vfio_device_dma_map(device);
     381         [ -  + ]:         37 :         if (ret) {
     382                 :          0 :                 SPDK_ERRLOG("Container DMA map failed\n");
     383                 :          0 :                 goto cleanup;
     384                 :            :         }
     385                 :            : 
     386   [ -  +  +  + ]:         37 :         SPDK_DEBUGLOG(vfio_pci, "Device %s, Path %s Setup Successfully\n", device->name, device->path);
     387                 :            : 
     388                 :         37 :         return device;
     389                 :            : 
     390                 :          0 : cleanup:
     391                 :          0 :         close(device->fd);
     392                 :          0 :         free(device);
     393                 :          0 :         return NULL;
     394                 :            : }
     395                 :            : 
     396                 :            : void
     397                 :         37 : spdk_vfio_user_release(struct vfio_device *dev)
     398                 :            : {
     399   [ -  +  +  + ]:         37 :         SPDK_DEBUGLOG(vfio_pci, "Release file %s\n", dev->path);
     400                 :            : 
     401                 :         37 :         vfio_device_unmap_bars(dev);
     402         [ +  - ]:         37 :         if (dev->map) {
     403                 :         37 :                 spdk_mem_map_free(&dev->map);
     404                 :            :         }
     405                 :         37 :         close(dev->fd);
     406                 :            : 
     407                 :         37 :         free(dev);
     408                 :         37 : }
     409                 :            : 
     410                 :            : void *
     411                 :         35 : spdk_vfio_user_get_bar_addr(struct vfio_device *dev, uint32_t index, uint64_t offset, uint32_t len)
     412                 :            : {
     413                 :         35 :         struct vfio_pci_region *region = &dev->regions[index];
     414                 :            :         uint32_t i;
     415                 :            : 
     416   [ +  -  -  + ]:         35 :         if (!region->size || !(region->flags & VFIO_REGION_INFO_FLAG_MMAP)) {
     417                 :          0 :                 return NULL;
     418                 :            :         }
     419                 :            : 
     420         [ +  - ]:         35 :         for (i = 0; i < region->nr_mmaps; i++) {
     421   [ +  -  +  - ]:         35 :                 if (region->mmaps[i].mem && (region->mmaps[i].offset <= offset) &&
     422         [ +  - ]:         35 :                     ((offset + len) <= (region->mmaps[i].offset + region->mmaps[i].size))) {
     423                 :         35 :                         return (void *)((uintptr_t)region->mmaps[i].mem + offset - region->mmaps[i].offset);
     424                 :            :                 }
     425                 :            :         }
     426                 :            : 
     427                 :          0 :         return NULL;
     428                 :            : }
     429                 :            : 
     430                 :            : /* For fuzzing only */
     431                 :            : int
     432                 :          0 : spdk_vfio_user_dev_send_request(struct vfio_device *dev, enum vfio_user_command command,
     433                 :            :                                 void *arg, size_t arg_len, size_t buf_len, int *fds,
     434                 :            :                                 int max_fds)
     435                 :            : {
     436                 :          0 :         return vfio_user_dev_send_request(dev, command, arg, arg_len, buf_len, fds, max_fds);
     437                 :            : }
     438                 :            : 
     439                 :       2459 : SPDK_LOG_REGISTER_COMPONENT(vfio_pci)

Generated by: LCOV version 1.14