LCOV - code coverage report
Current view: top level - lib/eal/linux - eal_vfio.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 67 818 8.2 %
Date: 2025-07-01 21:32:37 Functions: 4 51 7.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 32 628 5.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2018 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <inttypes.h>
       6                 :            : #include <string.h>
       7                 :            : #include <fcntl.h>
       8                 :            : #include <unistd.h>
       9                 :            : #include <sys/ioctl.h>
      10                 :            : #include <dirent.h>
      11                 :            : 
      12                 :            : #include <rte_errno.h>
      13                 :            : #include <rte_log.h>
      14                 :            : #include <rte_memory.h>
      15                 :            : #include <rte_eal_memconfig.h>
      16                 :            : #include <rte_vfio.h>
      17                 :            : 
      18                 :            : #include <eal_export.h>
      19                 :            : #include "eal_filesystem.h"
      20                 :            : #include "eal_memcfg.h"
      21                 :            : #include "eal_vfio.h"
      22                 :            : #include "eal_private.h"
      23                 :            : #include "eal_internal_cfg.h"
      24                 :            : 
      25                 :            : #define VFIO_MEM_EVENT_CLB_NAME "vfio_mem_event_clb"
      26                 :            : 
      27                 :            : /* hot plug/unplug of VFIO groups may cause all DMA maps to be dropped. we can
      28                 :            :  * recreate the mappings for DPDK segments, but we cannot do so for memory that
      29                 :            :  * was registered by the user themselves, so we need to store the user mappings
      30                 :            :  * somewhere, to recreate them later.
      31                 :            :  */
      32                 :            : #define VFIO_MAX_USER_MEM_MAPS 256
      33                 :            : struct user_mem_map {
      34                 :            :         uint64_t addr;  /**< start VA */
      35                 :            :         uint64_t iova;  /**< start IOVA */
      36                 :            :         uint64_t len;   /**< total length of the mapping */
      37                 :            :         uint64_t chunk; /**< this mapping can be split in chunks of this size */
      38                 :            : };
      39                 :            : 
      40                 :            : struct user_mem_maps {
      41                 :            :         rte_spinlock_recursive_t lock;
      42                 :            :         int n_maps;
      43                 :            :         struct user_mem_map maps[VFIO_MAX_USER_MEM_MAPS];
      44                 :            : };
      45                 :            : 
      46                 :            : struct vfio_config {
      47                 :            :         int vfio_enabled;
      48                 :            :         int vfio_container_fd;
      49                 :            :         int vfio_active_groups;
      50                 :            :         const struct vfio_iommu_type *vfio_iommu_type;
      51                 :            :         struct vfio_group vfio_groups[VFIO_MAX_GROUPS];
      52                 :            :         struct user_mem_maps mem_maps;
      53                 :            : };
      54                 :            : 
      55                 :            : /* per-process VFIO config */
      56                 :            : static struct vfio_config vfio_cfgs[VFIO_MAX_CONTAINERS];
      57                 :            : static struct vfio_config *default_vfio_cfg = &vfio_cfgs[0];
      58                 :            : 
      59                 :            : static int vfio_type1_dma_map(int);
      60                 :            : static int vfio_type1_dma_mem_map(int, uint64_t, uint64_t, uint64_t, int);
      61                 :            : static int vfio_spapr_dma_map(int);
      62                 :            : static int vfio_spapr_dma_mem_map(int, uint64_t, uint64_t, uint64_t, int);
      63                 :            : static int vfio_noiommu_dma_map(int);
      64                 :            : static int vfio_noiommu_dma_mem_map(int, uint64_t, uint64_t, uint64_t, int);
      65                 :            : static int vfio_dma_mem_map(struct vfio_config *vfio_cfg, uint64_t vaddr,
      66                 :            :                 uint64_t iova, uint64_t len, int do_map);
      67                 :            : 
      68                 :            : /* IOMMU types we support */
      69                 :            : static const struct vfio_iommu_type iommu_types[] = {
      70                 :            :         /* x86 IOMMU, otherwise known as type 1 */
      71                 :            :         {
      72                 :            :                 .type_id = RTE_VFIO_TYPE1,
      73                 :            :                 .name = "Type 1",
      74                 :            :                 .partial_unmap = false,
      75                 :            :                 .dma_map_func = &vfio_type1_dma_map,
      76                 :            :                 .dma_user_map_func = &vfio_type1_dma_mem_map
      77                 :            :         },
      78                 :            :         /* ppc64 IOMMU, otherwise known as spapr */
      79                 :            :         {
      80                 :            :                 .type_id = RTE_VFIO_SPAPR,
      81                 :            :                 .name = "sPAPR",
      82                 :            :                 .partial_unmap = true,
      83                 :            :                 .dma_map_func = &vfio_spapr_dma_map,
      84                 :            :                 .dma_user_map_func = &vfio_spapr_dma_mem_map
      85                 :            :         },
      86                 :            :         /* IOMMU-less mode */
      87                 :            :         {
      88                 :            :                 .type_id = RTE_VFIO_NOIOMMU,
      89                 :            :                 .name = "No-IOMMU",
      90                 :            :                 .partial_unmap = true,
      91                 :            :                 .dma_map_func = &vfio_noiommu_dma_map,
      92                 :            :                 .dma_user_map_func = &vfio_noiommu_dma_mem_map
      93                 :            :         },
      94                 :            : };
      95                 :            : 
      96                 :            : static int
      97                 :            : is_null_map(const struct user_mem_map *map)
      98                 :            : {
      99   [ #  #  #  #  :          0 :         return map->addr == 0 && map->iova == 0 &&
          #  #  #  #  #  
                      # ]
     100   [ #  #  #  #  :          0 :                         map->len == 0 && map->chunk == 0;
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     101                 :            : }
     102                 :            : 
     103                 :            : /* we may need to merge user mem maps together in case of user mapping/unmapping
     104                 :            :  * chunks of memory, so we'll need a comparator function to sort segments.
     105                 :            :  */
     106                 :            : static int
     107         [ #  # ]:          0 : user_mem_map_cmp(const void *a, const void *b)
     108                 :            : {
     109                 :            :         const struct user_mem_map *umm_a = a;
     110                 :            :         const struct user_mem_map *umm_b = b;
     111                 :            : 
     112                 :            :         /* move null entries to end */
     113                 :            :         if (is_null_map(umm_a))
     114                 :            :                 return 1;
     115                 :            :         if (is_null_map(umm_b))
     116                 :            :                 return -1;
     117                 :            : 
     118                 :            :         /* sort by iova first */
     119         [ #  # ]:          0 :         if (umm_a->iova < umm_b->iova)
     120                 :            :                 return -1;
     121         [ #  # ]:          0 :         if (umm_a->iova > umm_b->iova)
     122                 :            :                 return 1;
     123                 :            : 
     124         [ #  # ]:          0 :         if (umm_a->addr < umm_b->addr)
     125                 :            :                 return -1;
     126         [ #  # ]:          0 :         if (umm_a->addr > umm_b->addr)
     127                 :            :                 return 1;
     128                 :            : 
     129         [ #  # ]:          0 :         if (umm_a->len < umm_b->len)
     130                 :            :                 return -1;
     131         [ #  # ]:          0 :         if (umm_a->len > umm_b->len)
     132                 :            :                 return 1;
     133                 :            : 
     134         [ #  # ]:          0 :         if (umm_a->chunk < umm_b->chunk)
     135                 :            :                 return -1;
     136         [ #  # ]:          0 :         if (umm_a->chunk > umm_b->chunk)
     137                 :          0 :                 return 1;
     138                 :            : 
     139                 :            :         return 0;
     140                 :            : }
     141                 :            : 
     142                 :            : /*
     143                 :            :  * Take in an address range and list of current mappings, and produce a list of
     144                 :            :  * mappings that will be kept.
     145                 :            :  */
     146                 :            : static int
     147                 :          0 : process_maps(struct user_mem_map *src, size_t src_len,
     148                 :            :                 struct user_mem_map newmap[2], uint64_t vaddr, uint64_t len)
     149                 :            : {
     150                 :            :         struct user_mem_map *src_first = &src[0];
     151                 :          0 :         struct user_mem_map *src_last = &src[src_len - 1];
     152                 :            :         struct user_mem_map *dst_first = &newmap[0];
     153                 :            :         /* we can get at most two new segments */
     154                 :          0 :         struct user_mem_map *dst_last = &newmap[1];
     155                 :          0 :         uint64_t first_off = vaddr - src_first->addr;
     156                 :          0 :         uint64_t last_off = (src_last->addr + src_last->len) - (vaddr + len);
     157                 :            :         int newmap_len = 0;
     158                 :            : 
     159         [ #  # ]:          0 :         if (first_off != 0) {
     160                 :          0 :                 dst_first->addr = src_first->addr;
     161                 :          0 :                 dst_first->iova = src_first->iova;
     162                 :          0 :                 dst_first->len = first_off;
     163                 :          0 :                 dst_first->chunk = src_first->chunk;
     164                 :            : 
     165                 :            :                 newmap_len++;
     166                 :            :         }
     167         [ #  # ]:          0 :         if (last_off != 0) {
     168                 :            :                 /* if we had start offset, we have two segments */
     169                 :            :                 struct user_mem_map *last =
     170         [ #  # ]:          0 :                                 first_off == 0 ? dst_first : dst_last;
     171                 :          0 :                 last->addr = (src_last->addr + src_last->len) - last_off;
     172                 :          0 :                 last->iova = (src_last->iova + src_last->len) - last_off;
     173                 :          0 :                 last->len = last_off;
     174                 :          0 :                 last->chunk = src_last->chunk;
     175                 :            : 
     176                 :          0 :                 newmap_len++;
     177                 :            :         }
     178                 :          0 :         return newmap_len;
     179                 :            : }
     180                 :            : 
     181                 :            : /* erase certain maps from the list */
     182                 :            : static void
     183                 :          0 : delete_maps(struct user_mem_maps *user_mem_maps, struct user_mem_map *del_maps,
     184                 :            :                 size_t n_del)
     185                 :            : {
     186                 :            :         int i;
     187                 :            :         size_t j;
     188                 :            : 
     189         [ #  # ]:          0 :         for (i = 0, j = 0; i < VFIO_MAX_USER_MEM_MAPS && j < n_del; i++) {
     190                 :          0 :                 struct user_mem_map *left = &user_mem_maps->maps[i];
     191                 :          0 :                 struct user_mem_map *right = &del_maps[j];
     192                 :            : 
     193         [ #  # ]:          0 :                 if (user_mem_map_cmp(left, right) == 0) {
     194                 :            :                         memset(left, 0, sizeof(*left));
     195                 :          0 :                         j++;
     196                 :          0 :                         user_mem_maps->n_maps--;
     197                 :            :                 }
     198                 :            :         }
     199                 :          0 : }
     200                 :            : 
     201                 :            : static void
     202                 :          0 : copy_maps(struct user_mem_maps *user_mem_maps, struct user_mem_map *add_maps,
     203                 :            :                 size_t n_add)
     204                 :            : {
     205                 :            :         int i;
     206                 :            :         size_t j;
     207                 :            : 
     208         [ #  # ]:          0 :         for (i = 0, j = 0; i < VFIO_MAX_USER_MEM_MAPS && j < n_add; i++) {
     209                 :          0 :                 struct user_mem_map *left = &user_mem_maps->maps[i];
     210         [ #  # ]:          0 :                 struct user_mem_map *right = &add_maps[j];
     211                 :            : 
     212                 :            :                 /* insert into empty space */
     213                 :            :                 if (is_null_map(left)) {
     214                 :            :                         memcpy(left, right, sizeof(*left));
     215                 :          0 :                         j++;
     216                 :          0 :                         user_mem_maps->n_maps++;
     217                 :            :                 }
     218                 :            :         }
     219                 :          0 : }
     220                 :            : 
     221                 :            : /* try merging two maps into one, return 1 if succeeded */
     222                 :            : static int
     223                 :          0 : merge_map(struct user_mem_map *left, struct user_mem_map *right)
     224                 :            : {
     225                 :            :         /* merge the same maps into one */
     226         [ #  # ]:          0 :         if (memcmp(left, right, sizeof(struct user_mem_map)) == 0)
     227                 :          0 :                 goto out;
     228                 :            : 
     229         [ #  # ]:          0 :         if (left->addr + left->len != right->addr)
     230                 :            :                 return 0;
     231         [ #  # ]:          0 :         if (left->iova + left->len != right->iova)
     232                 :            :                 return 0;
     233         [ #  # ]:          0 :         if (left->chunk != right->chunk)
     234                 :            :                 return 0;
     235                 :          0 :         left->len += right->len;
     236                 :            : 
     237                 :          0 : out:
     238                 :            :         memset(right, 0, sizeof(*right));
     239                 :            : 
     240                 :          0 :         return 1;
     241                 :            : }
     242                 :            : 
     243                 :            : static bool
     244                 :          0 : addr_is_chunk_aligned(struct user_mem_map *maps, size_t n_maps,
     245                 :            :                 uint64_t vaddr, uint64_t iova)
     246                 :            : {
     247                 :            :         unsigned int i;
     248                 :            : 
     249         [ #  # ]:          0 :         for (i = 0; i < n_maps; i++) {
     250                 :          0 :                 struct user_mem_map *map = &maps[i];
     251                 :          0 :                 uint64_t map_va_end = map->addr + map->len;
     252                 :          0 :                 uint64_t map_iova_end = map->iova + map->len;
     253                 :          0 :                 uint64_t map_va_off = vaddr - map->addr;
     254                 :          0 :                 uint64_t map_iova_off = iova - map->iova;
     255                 :            : 
     256                 :            :                 /* we include end of the segment in comparison as well */
     257   [ #  #  #  # ]:          0 :                 bool addr_in_map = (vaddr >= map->addr) && (vaddr <= map_va_end);
     258   [ #  #  #  # ]:          0 :                 bool iova_in_map = (iova >= map->iova) && (iova <= map_iova_end);
     259                 :            :                 /* chunk may not be power of two, so use modulo */
     260                 :          0 :                 bool addr_is_aligned = (map_va_off % map->chunk) == 0;
     261                 :          0 :                 bool iova_is_aligned = (map_iova_off % map->chunk) == 0;
     262                 :            : 
     263         [ #  # ]:          0 :                 if (addr_in_map && iova_in_map &&
     264         [ #  # ]:          0 :                                 addr_is_aligned && iova_is_aligned)
     265                 :            :                         return true;
     266                 :            :         }
     267                 :            :         return false;
     268                 :            : }
     269                 :            : 
     270                 :            : static int
     271                 :          0 : find_user_mem_maps(struct user_mem_maps *user_mem_maps, uint64_t addr,
     272                 :            :                 uint64_t iova, uint64_t len, struct user_mem_map *dst,
     273                 :            :                 size_t dst_len)
     274                 :            : {
     275                 :          0 :         uint64_t va_end = addr + len;
     276                 :          0 :         uint64_t iova_end = iova + len;
     277                 :            :         bool found = false;
     278                 :            :         size_t j;
     279                 :            :         int i, ret;
     280                 :            : 
     281         [ #  # ]:          0 :         for (i = 0, j = 0; i < user_mem_maps->n_maps; i++) {
     282                 :          0 :                 struct user_mem_map *map = &user_mem_maps->maps[i];
     283                 :          0 :                 uint64_t map_va_end = map->addr + map->len;
     284                 :          0 :                 uint64_t map_iova_end = map->iova + map->len;
     285                 :            : 
     286   [ #  #  #  # ]:          0 :                 bool start_addr_in_map = (addr >= map->addr) &&
     287                 :            :                                 (addr < map_va_end);
     288   [ #  #  #  # ]:          0 :                 bool end_addr_in_map = (va_end > map->addr) &&
     289                 :            :                                 (va_end <= map_va_end);
     290   [ #  #  #  # ]:          0 :                 bool start_iova_in_map = (iova >= map->iova) &&
     291                 :            :                                 (iova < map_iova_end);
     292   [ #  #  #  # ]:          0 :                 bool end_iova_in_map = (iova_end > map->iova) &&
     293                 :            :                                 (iova_end <= map_iova_end);
     294                 :            : 
     295                 :            :                 /* do we have space in temporary map? */
     296         [ #  # ]:          0 :                 if (j == dst_len) {
     297                 :            :                         ret = -ENOSPC;
     298                 :          0 :                         goto err;
     299                 :            :                 }
     300                 :            :                 /* check if current map is start of our segment */
     301   [ #  #  #  # ]:          0 :                 if (!found && start_addr_in_map && start_iova_in_map)
     302                 :            :                         found = true;
     303                 :            :                 /* if we have previously found a segment, add it to the map */
     304         [ #  # ]:          0 :                 if (found) {
     305                 :            :                         /* copy the segment into our temporary map */
     306         [ #  # ]:          0 :                         memcpy(&dst[j++], map, sizeof(*map));
     307                 :            : 
     308                 :            :                         /* if we match end of segment, quit */
     309         [ #  # ]:          0 :                         if (end_addr_in_map && end_iova_in_map)
     310                 :          0 :                                 return j;
     311                 :            :                 }
     312                 :            :         }
     313                 :            :         /* we didn't find anything */
     314                 :            :         ret = -ENOENT;
     315                 :          0 : err:
     316                 :          0 :         memset(dst, 0, sizeof(*dst) * dst_len);
     317                 :          0 :         return ret;
     318                 :            : }
     319                 :            : 
     320                 :            : /* this will sort all user maps, and merge/compact any adjacent maps */
     321                 :            : static void
     322                 :          0 : compact_user_maps(struct user_mem_maps *user_mem_maps)
     323                 :            : {
     324                 :            :         int i;
     325                 :            : 
     326                 :          0 :         qsort(user_mem_maps->maps, VFIO_MAX_USER_MEM_MAPS,
     327                 :            :                         sizeof(user_mem_maps->maps[0]), user_mem_map_cmp);
     328                 :            : 
     329                 :            :         /* we'll go over the list backwards when merging */
     330         [ #  # ]:          0 :         for (i = VFIO_MAX_USER_MEM_MAPS - 2; i >= 0; i--) {
     331                 :            :                 struct user_mem_map *l, *r;
     332                 :            : 
     333                 :          0 :                 l = &user_mem_maps->maps[i];
     334         [ #  # ]:          0 :                 r = &user_mem_maps->maps[i + 1];
     335                 :            : 
     336                 :          0 :                 if (is_null_map(l) || is_null_map(r))
     337                 :          0 :                         continue;
     338                 :            : 
     339                 :            :                 /* try and merge the maps */
     340         [ #  # ]:          0 :                 if (merge_map(l, r))
     341                 :          0 :                         user_mem_maps->n_maps--;
     342                 :            :         }
     343                 :            : 
     344                 :            :         /* the entries are still sorted, but now they have holes in them, so
     345                 :            :          * sort the list again.
     346                 :            :          */
     347                 :          0 :         qsort(user_mem_maps->maps, VFIO_MAX_USER_MEM_MAPS,
     348                 :            :                         sizeof(user_mem_maps->maps[0]), user_mem_map_cmp);
     349                 :          0 : }
     350                 :            : 
     351                 :            : static int
     352                 :          0 : vfio_open_group_fd(int iommu_group_num)
     353                 :            : {
     354                 :            :         int vfio_group_fd;
     355                 :            :         char filename[PATH_MAX];
     356                 :            :         struct rte_mp_msg mp_req, *mp_rep;
     357                 :          0 :         struct rte_mp_reply mp_reply = {0};
     358                 :          0 :         struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
     359                 :            :         struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param;
     360                 :            :         const struct internal_config *internal_conf =
     361                 :          0 :                 eal_get_internal_configuration();
     362                 :            : 
     363                 :            :         /* if primary, try to open the group */
     364         [ #  # ]:          0 :         if (internal_conf->process_type == RTE_PROC_PRIMARY) {
     365                 :            :                 /* try regular group format */
     366                 :            :                 snprintf(filename, sizeof(filename),
     367                 :            :                                  VFIO_GROUP_FMT, iommu_group_num);
     368                 :            :                 vfio_group_fd = open(filename, O_RDWR);
     369         [ #  # ]:          0 :                 if (vfio_group_fd < 0) {
     370                 :            :                         /* if file not found, it's not an error */
     371         [ #  # ]:          0 :                         if (errno != ENOENT) {
     372                 :          0 :                                 EAL_LOG(ERR, "Cannot open %s: %s",
     373                 :            :                                                 filename, strerror(errno));
     374                 :          0 :                                 return -1;
     375                 :            :                         }
     376                 :            : 
     377                 :            :                         /* special case: try no-IOMMU path as well */
     378                 :            :                         snprintf(filename, sizeof(filename),
     379                 :            :                                         VFIO_NOIOMMU_GROUP_FMT,
     380                 :            :                                         iommu_group_num);
     381                 :            :                         vfio_group_fd = open(filename, O_RDWR);
     382         [ #  # ]:          0 :                         if (vfio_group_fd < 0) {
     383         [ #  # ]:          0 :                                 if (errno != ENOENT) {
     384                 :          0 :                                         EAL_LOG(ERR,
     385                 :            :                                                 "Cannot open %s: %s",
     386                 :            :                                                 filename, strerror(errno));
     387                 :          0 :                                         return -1;
     388                 :            :                                 }
     389                 :            :                                 return -ENOENT;
     390                 :            :                         }
     391                 :            :                         /* noiommu group found */
     392                 :            :                 }
     393                 :            : 
     394                 :          0 :                 return vfio_group_fd;
     395                 :            :         }
     396                 :            :         /* if we're in a secondary process, request group fd from the primary
     397                 :            :          * process via mp channel.
     398                 :            :          */
     399                 :          0 :         p->req = SOCKET_REQ_GROUP;
     400                 :          0 :         p->group_num = iommu_group_num;
     401                 :            :         strcpy(mp_req.name, EAL_VFIO_MP);
     402                 :          0 :         mp_req.len_param = sizeof(*p);
     403                 :          0 :         mp_req.num_fds = 0;
     404                 :            : 
     405                 :            :         vfio_group_fd = -1;
     406         [ #  # ]:          0 :         if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
     407         [ #  # ]:          0 :             mp_reply.nb_received == 1) {
     408                 :          0 :                 mp_rep = &mp_reply.msgs[0];
     409                 :            :                 p = (struct vfio_mp_param *)mp_rep->param;
     410   [ #  #  #  # ]:          0 :                 if (p->result == SOCKET_OK && mp_rep->num_fds == 1) {
     411                 :          0 :                         vfio_group_fd = mp_rep->fds[0];
     412         [ #  # ]:          0 :                 } else if (p->result == SOCKET_NO_FD) {
     413                 :          0 :                         EAL_LOG(ERR, "Bad VFIO group fd");
     414                 :            :                         vfio_group_fd = -ENOENT;
     415                 :            :                 }
     416                 :            :         }
     417                 :            : 
     418                 :          0 :         free(mp_reply.msgs);
     419         [ #  # ]:          0 :         if (vfio_group_fd < 0 && vfio_group_fd != -ENOENT)
     420                 :          0 :                 EAL_LOG(ERR, "Cannot request VFIO group fd");
     421                 :            :         return vfio_group_fd;
     422                 :            : }
     423                 :            : 
     424                 :            : static struct vfio_config *
     425                 :            : get_vfio_cfg_by_group_num(int iommu_group_num)
     426                 :            : {
     427                 :            :         struct vfio_config *vfio_cfg;
     428                 :            :         int i, j;
     429                 :            : 
     430   [ #  #  #  #  :          0 :         for (i = 0; i < VFIO_MAX_CONTAINERS; i++) {
                   #  # ]
     431                 :          0 :                 vfio_cfg = &vfio_cfgs[i];
     432   [ #  #  #  #  :          0 :                 for (j = 0; j < VFIO_MAX_GROUPS; j++) {
                   #  # ]
     433   [ #  #  #  #  :          0 :                         if (vfio_cfg->vfio_groups[j].group_num ==
                   #  # ]
     434                 :            :                                         iommu_group_num)
     435                 :            :                                 return vfio_cfg;
     436                 :            :                 }
     437                 :            :         }
     438                 :            : 
     439                 :            :         return NULL;
     440                 :            : }
     441                 :            : 
     442                 :            : static int
     443                 :          0 : vfio_get_group_fd(struct vfio_config *vfio_cfg,
     444                 :            :                 int iommu_group_num)
     445                 :            : {
     446                 :            :         int i;
     447                 :            :         int vfio_group_fd;
     448                 :            :         struct vfio_group *cur_grp;
     449                 :            : 
     450                 :            :         /* check if we already have the group descriptor open */
     451         [ #  # ]:          0 :         for (i = 0; i < VFIO_MAX_GROUPS; i++)
     452         [ #  # ]:          0 :                 if (vfio_cfg->vfio_groups[i].group_num == iommu_group_num)
     453                 :          0 :                         return vfio_cfg->vfio_groups[i].fd;
     454                 :            : 
     455                 :            :         /* Lets see first if there is room for a new group */
     456         [ #  # ]:          0 :         if (vfio_cfg->vfio_active_groups == VFIO_MAX_GROUPS) {
     457                 :          0 :                 EAL_LOG(ERR, "Maximum number of VFIO groups reached!");
     458                 :          0 :                 return -1;
     459                 :            :         }
     460                 :            : 
     461                 :            :         /* Now lets get an index for the new group */
     462         [ #  # ]:          0 :         for (i = 0; i < VFIO_MAX_GROUPS; i++)
     463         [ #  # ]:          0 :                 if (vfio_cfg->vfio_groups[i].group_num == -1) {
     464                 :          0 :                         cur_grp = &vfio_cfg->vfio_groups[i];
     465                 :          0 :                         break;
     466                 :            :                 }
     467                 :            : 
     468                 :            :         /* This should not happen */
     469         [ #  # ]:          0 :         if (i == VFIO_MAX_GROUPS) {
     470                 :          0 :                 EAL_LOG(ERR, "No VFIO group free slot found");
     471                 :          0 :                 return -1;
     472                 :            :         }
     473                 :            : 
     474                 :          0 :         vfio_group_fd = vfio_open_group_fd(iommu_group_num);
     475         [ #  # ]:          0 :         if (vfio_group_fd < 0) {
     476                 :          0 :                 EAL_LOG(ERR, "Failed to open VFIO group %d",
     477                 :            :                         iommu_group_num);
     478                 :          0 :                 return vfio_group_fd;
     479                 :            :         }
     480                 :            : 
     481                 :          0 :         cur_grp->group_num = iommu_group_num;
     482                 :          0 :         cur_grp->fd = vfio_group_fd;
     483                 :          0 :         vfio_cfg->vfio_active_groups++;
     484                 :            : 
     485                 :          0 :         return vfio_group_fd;
     486                 :            : }
     487                 :            : 
     488                 :            : static struct vfio_config *
     489                 :            : get_vfio_cfg_by_group_fd(int vfio_group_fd)
     490                 :            : {
     491                 :            :         struct vfio_config *vfio_cfg;
     492                 :            :         int i, j;
     493                 :            : 
     494   [ #  #  #  #  :          0 :         for (i = 0; i < VFIO_MAX_CONTAINERS; i++) {
             #  #  #  # ]
     495                 :          0 :                 vfio_cfg = &vfio_cfgs[i];
     496   [ #  #  #  #  :          0 :                 for (j = 0; j < VFIO_MAX_GROUPS; j++)
             #  #  #  # ]
     497   [ #  #  #  #  :          0 :                         if (vfio_cfg->vfio_groups[j].fd == vfio_group_fd)
             #  #  #  # ]
     498                 :            :                                 return vfio_cfg;
     499                 :            :         }
     500                 :            : 
     501                 :            :         return NULL;
     502                 :            : }
     503                 :            : 
     504                 :            : static struct vfio_config *
     505                 :            : get_vfio_cfg_by_container_fd(int container_fd)
     506                 :            : {
     507                 :            :         int i;
     508                 :            : 
     509   [ #  #  #  # ]:          0 :         if (container_fd == RTE_VFIO_DEFAULT_CONTAINER_FD)
     510                 :          0 :                 return default_vfio_cfg;
     511                 :            : 
     512   [ #  #  #  #  :          0 :         for (i = 0; i < VFIO_MAX_CONTAINERS; i++) {
          #  #  #  #  #  
                      # ]
     513   [ #  #  #  #  :          0 :                 if (vfio_cfgs[i].vfio_container_fd == container_fd)
          #  #  #  #  #  
                      # ]
     514                 :          0 :                         return &vfio_cfgs[i];
     515                 :            :         }
     516                 :            : 
     517                 :            :         return NULL;
     518                 :            : }
     519                 :            : 
     520                 :            : RTE_EXPORT_SYMBOL(rte_vfio_get_group_fd)
     521                 :            : int
     522                 :          0 : rte_vfio_get_group_fd(int iommu_group_num)
     523                 :            : {
     524                 :            :         struct vfio_config *vfio_cfg;
     525                 :            : 
     526                 :            :         /* get the vfio_config it belongs to */
     527                 :            :         vfio_cfg = get_vfio_cfg_by_group_num(iommu_group_num);
     528         [ #  # ]:          0 :         vfio_cfg = vfio_cfg ? vfio_cfg : default_vfio_cfg;
     529                 :            : 
     530                 :          0 :         return vfio_get_group_fd(vfio_cfg, iommu_group_num);
     531                 :            : }
     532                 :            : 
     533                 :            : static int
     534                 :            : get_vfio_group_idx(int vfio_group_fd)
     535                 :            : {
     536                 :            :         struct vfio_config *vfio_cfg;
     537                 :            :         int i, j;
     538                 :            : 
     539   [ #  #  #  #  :          0 :         for (i = 0; i < VFIO_MAX_CONTAINERS; i++) {
             #  #  #  # ]
     540                 :            :                 vfio_cfg = &vfio_cfgs[i];
     541   [ #  #  #  #  :          0 :                 for (j = 0; j < VFIO_MAX_GROUPS; j++)
             #  #  #  # ]
     542   [ #  #  #  #  :          0 :                         if (vfio_cfg->vfio_groups[j].fd == vfio_group_fd)
             #  #  #  # ]
     543                 :            :                                 return j;
     544                 :            :         }
     545                 :            : 
     546                 :            :         return -1;
     547                 :            : }
     548                 :            : 
     549                 :            : static void
     550                 :          0 : vfio_group_device_get(int vfio_group_fd)
     551                 :            : {
     552                 :            :         struct vfio_config *vfio_cfg;
     553                 :            :         int i;
     554                 :            : 
     555                 :            :         vfio_cfg = get_vfio_cfg_by_group_fd(vfio_group_fd);
     556         [ #  # ]:          0 :         if (vfio_cfg == NULL) {
     557                 :          0 :                 EAL_LOG(ERR, "Invalid VFIO group fd!");
     558                 :          0 :                 return;
     559                 :            :         }
     560                 :            : 
     561                 :            :         i = get_vfio_group_idx(vfio_group_fd);
     562         [ #  # ]:          0 :         if (i < 0 || i > (VFIO_MAX_GROUPS - 1))
     563                 :          0 :                 EAL_LOG(ERR, "Wrong VFIO group index (%d)", i);
     564                 :            :         else
     565                 :          0 :                 vfio_cfg->vfio_groups[i].devices++;
     566                 :            : }
     567                 :            : 
     568                 :            : static void
     569                 :          0 : vfio_group_device_put(int vfio_group_fd)
     570                 :            : {
     571                 :            :         struct vfio_config *vfio_cfg;
     572                 :            :         int i;
     573                 :            : 
     574                 :            :         vfio_cfg = get_vfio_cfg_by_group_fd(vfio_group_fd);
     575         [ #  # ]:          0 :         if (vfio_cfg == NULL) {
     576                 :          0 :                 EAL_LOG(ERR, "Invalid VFIO group fd!");
     577                 :          0 :                 return;
     578                 :            :         }
     579                 :            : 
     580                 :            :         i = get_vfio_group_idx(vfio_group_fd);
     581         [ #  # ]:          0 :         if (i < 0 || i > (VFIO_MAX_GROUPS - 1))
     582                 :          0 :                 EAL_LOG(ERR, "Wrong VFIO group index (%d)", i);
     583                 :            :         else
     584                 :          0 :                 vfio_cfg->vfio_groups[i].devices--;
     585                 :            : }
     586                 :            : 
     587                 :            : static int
     588                 :          0 : vfio_group_device_count(int vfio_group_fd)
     589                 :            : {
     590                 :            :         struct vfio_config *vfio_cfg;
     591                 :            :         int i;
     592                 :            : 
     593                 :            :         vfio_cfg = get_vfio_cfg_by_group_fd(vfio_group_fd);
     594         [ #  # ]:          0 :         if (vfio_cfg == NULL) {
     595                 :          0 :                 EAL_LOG(ERR, "Invalid VFIO group fd!");
     596                 :          0 :                 return -1;
     597                 :            :         }
     598                 :            : 
     599                 :            :         i = get_vfio_group_idx(vfio_group_fd);
     600         [ #  # ]:          0 :         if (i < 0 || i > (VFIO_MAX_GROUPS - 1)) {
     601                 :          0 :                 EAL_LOG(ERR, "Wrong VFIO group index (%d)", i);
     602                 :          0 :                 return -1;
     603                 :            :         }
     604                 :            : 
     605                 :          0 :         return vfio_cfg->vfio_groups[i].devices;
     606                 :            : }
     607                 :            : 
     608                 :            : static void
     609                 :          0 : vfio_mem_event_callback(enum rte_mem_event type, const void *addr, size_t len,
     610                 :            :                 void *arg __rte_unused)
     611                 :            : {
     612                 :            :         struct rte_memseg_list *msl;
     613                 :            :         struct rte_memseg *ms;
     614                 :            :         size_t cur_len = 0;
     615                 :            : 
     616                 :          0 :         msl = rte_mem_virt2memseg_list(addr);
     617                 :            : 
     618                 :            :         /* for IOVA as VA mode, no need to care for IOVA addresses */
     619   [ #  #  #  # ]:          0 :         if (rte_eal_iova_mode() == RTE_IOVA_VA && msl->external == 0) {
     620                 :          0 :                 uint64_t vfio_va = (uint64_t)(uintptr_t)addr;
     621                 :          0 :                 uint64_t page_sz = msl->page_sz;
     622                 :            : 
     623                 :            :                 /* Maintain granularity of DMA map/unmap to memseg size */
     624         [ #  # ]:          0 :                 for (; cur_len < len; cur_len += page_sz) {
     625         [ #  # ]:          0 :                         if (type == RTE_MEM_EVENT_ALLOC)
     626                 :          0 :                                 vfio_dma_mem_map(default_vfio_cfg, vfio_va,
     627                 :            :                                                  vfio_va, page_sz, 1);
     628                 :            :                         else
     629                 :          0 :                                 vfio_dma_mem_map(default_vfio_cfg, vfio_va,
     630                 :            :                                                  vfio_va, page_sz, 0);
     631                 :          0 :                         vfio_va += page_sz;
     632                 :            :                 }
     633                 :            : 
     634                 :            :                 return;
     635                 :            :         }
     636                 :            : 
     637                 :            :         /* memsegs are contiguous in memory */
     638                 :          0 :         ms = rte_mem_virt2memseg(addr, msl);
     639         [ #  # ]:          0 :         while (cur_len < len) {
     640                 :            :                 /* some memory segments may have invalid IOVA */
     641         [ #  # ]:          0 :                 if (ms->iova == RTE_BAD_IOVA) {
     642                 :          0 :                         EAL_LOG(DEBUG,
     643                 :            :                                 "Memory segment at %p has bad IOVA, skipping",
     644                 :            :                                 ms->addr);
     645                 :          0 :                         goto next;
     646                 :            :                 }
     647         [ #  # ]:          0 :                 if (type == RTE_MEM_EVENT_ALLOC)
     648                 :          0 :                         vfio_dma_mem_map(default_vfio_cfg, ms->addr_64,
     649                 :            :                                         ms->iova, ms->len, 1);
     650                 :            :                 else
     651                 :          0 :                         vfio_dma_mem_map(default_vfio_cfg, ms->addr_64,
     652                 :            :                                         ms->iova, ms->len, 0);
     653                 :          0 : next:
     654                 :          0 :                 cur_len += ms->len;
     655                 :          0 :                 ++ms;
     656                 :            :         }
     657                 :            : }
     658                 :            : 
     659                 :            : static int
     660                 :          0 : vfio_sync_default_container(void)
     661                 :            : {
     662                 :            :         struct rte_mp_msg mp_req, *mp_rep;
     663                 :          0 :         struct rte_mp_reply mp_reply = {0};
     664                 :          0 :         struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
     665                 :            :         struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param;
     666                 :            :         int iommu_type_id;
     667                 :            :         unsigned int i;
     668                 :            : 
     669                 :            :         /* cannot be called from primary */
     670         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_SECONDARY)
     671                 :            :                 return -1;
     672                 :            : 
     673                 :            :         /* default container fd should have been opened in rte_vfio_enable() */
     674         [ #  # ]:          0 :         if (!default_vfio_cfg->vfio_enabled ||
     675         [ #  # ]:          0 :                         default_vfio_cfg->vfio_container_fd < 0) {
     676                 :          0 :                 EAL_LOG(ERR, "VFIO support is not initialized");
     677                 :          0 :                 return -1;
     678                 :            :         }
     679                 :            : 
     680                 :            :         /* find default container's IOMMU type */
     681                 :          0 :         p->req = SOCKET_REQ_IOMMU_TYPE;
     682                 :            :         strcpy(mp_req.name, EAL_VFIO_MP);
     683                 :          0 :         mp_req.len_param = sizeof(*p);
     684                 :          0 :         mp_req.num_fds = 0;
     685                 :            : 
     686                 :            :         iommu_type_id = -1;
     687         [ #  # ]:          0 :         if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
     688         [ #  # ]:          0 :                         mp_reply.nb_received == 1) {
     689                 :          0 :                 mp_rep = &mp_reply.msgs[0];
     690                 :            :                 p = (struct vfio_mp_param *)mp_rep->param;
     691         [ #  # ]:          0 :                 if (p->result == SOCKET_OK)
     692                 :          0 :                         iommu_type_id = p->iommu_type_id;
     693                 :            :         }
     694                 :          0 :         free(mp_reply.msgs);
     695         [ #  # ]:          0 :         if (iommu_type_id < 0) {
     696                 :          0 :                 EAL_LOG(ERR,
     697                 :            :                         "Could not get IOMMU type for default container");
     698                 :          0 :                 return -1;
     699                 :            :         }
     700                 :            : 
     701                 :            :         /* we now have an fd for default container, as well as its IOMMU type.
     702                 :            :          * now, set up default VFIO container config to match.
     703                 :            :          */
     704         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(iommu_types); i++) {
     705                 :          0 :                 const struct vfio_iommu_type *t = &iommu_types[i];
     706         [ #  # ]:          0 :                 if (t->type_id != iommu_type_id)
     707                 :            :                         continue;
     708                 :            : 
     709                 :            :                 /* we found our IOMMU type */
     710                 :          0 :                 default_vfio_cfg->vfio_iommu_type = t;
     711                 :            : 
     712                 :          0 :                 return 0;
     713                 :            :         }
     714                 :          0 :         EAL_LOG(ERR, "Could not find IOMMU type id (%i)",
     715                 :            :                         iommu_type_id);
     716                 :          0 :         return -1;
     717                 :            : }
     718                 :            : 
     719                 :            : RTE_EXPORT_SYMBOL(rte_vfio_clear_group)
     720                 :            : int
     721                 :          0 : rte_vfio_clear_group(int vfio_group_fd)
     722                 :            : {
     723                 :            :         int i;
     724                 :            :         struct vfio_config *vfio_cfg;
     725                 :            : 
     726                 :            :         vfio_cfg = get_vfio_cfg_by_group_fd(vfio_group_fd);
     727         [ #  # ]:          0 :         if (vfio_cfg == NULL) {
     728                 :          0 :                 EAL_LOG(ERR, "Invalid VFIO group fd!");
     729                 :          0 :                 return -1;
     730                 :            :         }
     731                 :            : 
     732                 :            :         i = get_vfio_group_idx(vfio_group_fd);
     733         [ #  # ]:          0 :         if (i < 0)
     734                 :            :                 return -1;
     735                 :          0 :         vfio_cfg->vfio_groups[i].group_num = -1;
     736                 :          0 :         vfio_cfg->vfio_groups[i].fd = -1;
     737                 :          0 :         vfio_cfg->vfio_groups[i].devices = 0;
     738                 :          0 :         vfio_cfg->vfio_active_groups--;
     739                 :            : 
     740                 :          0 :         return 0;
     741                 :            : }
     742                 :            : 
     743                 :            : RTE_EXPORT_SYMBOL(rte_vfio_setup_device)
     744                 :            : int
     745                 :          0 : rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
     746                 :            :                 int *vfio_dev_fd, struct vfio_device_info *device_info)
     747                 :            : {
     748                 :          0 :         struct vfio_group_status group_status = {
     749                 :            :                         .argsz = sizeof(group_status)
     750                 :            :         };
     751                 :            :         struct vfio_config *vfio_cfg;
     752                 :            :         struct user_mem_maps *user_mem_maps;
     753                 :            :         int vfio_container_fd;
     754                 :            :         int vfio_group_fd;
     755                 :            :         int iommu_group_num;
     756                 :            :         rte_uuid_t vf_token;
     757                 :            :         int i, ret;
     758                 :            :         const struct internal_config *internal_conf =
     759                 :          0 :                 eal_get_internal_configuration();
     760                 :            : 
     761                 :            :         /* get group number */
     762                 :          0 :         ret = rte_vfio_get_group_num(sysfs_base, dev_addr, &iommu_group_num);
     763         [ #  # ]:          0 :         if (ret == 0) {
     764                 :          0 :                 EAL_LOG(NOTICE,
     765                 :            :                                 "%s not managed by VFIO driver, skipping",
     766                 :            :                                 dev_addr);
     767                 :          0 :                 return 1;
     768                 :            :         }
     769                 :            : 
     770                 :            :         /* if negative, something failed */
     771         [ #  # ]:          0 :         if (ret < 0)
     772                 :            :                 return -1;
     773                 :            : 
     774                 :            :         /* get the actual group fd */
     775                 :          0 :         vfio_group_fd = rte_vfio_get_group_fd(iommu_group_num);
     776         [ #  # ]:          0 :         if (vfio_group_fd < 0 && vfio_group_fd != -ENOENT)
     777                 :            :                 return -1;
     778                 :            : 
     779                 :            :         /*
     780                 :            :          * if vfio_group_fd == -ENOENT, that means the device
     781                 :            :          * isn't managed by VFIO
     782                 :            :          */
     783         [ #  # ]:          0 :         if (vfio_group_fd == -ENOENT) {
     784                 :          0 :                 EAL_LOG(NOTICE,
     785                 :            :                                 "%s not managed by VFIO driver, skipping",
     786                 :            :                                 dev_addr);
     787                 :          0 :                 return 1;
     788                 :            :         }
     789                 :            : 
     790                 :            :         /*
     791                 :            :          * at this point, we know that this group is viable (meaning, all devices
     792                 :            :          * are either bound to VFIO or not bound to anything)
     793                 :            :          */
     794                 :            : 
     795                 :            :         /* check if the group is viable */
     796                 :          0 :         ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_STATUS, &group_status);
     797         [ #  # ]:          0 :         if (ret) {
     798                 :          0 :                 EAL_LOG(ERR, "%s cannot get VFIO group status, "
     799                 :            :                         "error %i (%s)", dev_addr, errno, strerror(errno));
     800                 :          0 :                 close(vfio_group_fd);
     801                 :          0 :                 rte_vfio_clear_group(vfio_group_fd);
     802                 :          0 :                 return -1;
     803         [ #  # ]:          0 :         } else if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)) {
     804                 :          0 :                 EAL_LOG(ERR, "%s VFIO group is not viable! "
     805                 :            :                         "Not all devices in IOMMU group bound to VFIO or unbound",
     806                 :            :                         dev_addr);
     807                 :          0 :                 close(vfio_group_fd);
     808                 :          0 :                 rte_vfio_clear_group(vfio_group_fd);
     809                 :          0 :                 return -1;
     810                 :            :         }
     811                 :            : 
     812                 :            :         /* get the vfio_config it belongs to */
     813                 :          0 :         vfio_cfg = get_vfio_cfg_by_group_num(iommu_group_num);
     814         [ #  # ]:          0 :         vfio_cfg = vfio_cfg ? vfio_cfg : default_vfio_cfg;
     815                 :          0 :         vfio_container_fd = vfio_cfg->vfio_container_fd;
     816                 :            :         user_mem_maps = &vfio_cfg->mem_maps;
     817                 :            : 
     818                 :            :         /* check if group does not have a container yet */
     819         [ #  # ]:          0 :         if (!(group_status.flags & VFIO_GROUP_FLAGS_CONTAINER_SET)) {
     820                 :            : 
     821                 :            :                 /* add group to a container */
     822                 :          0 :                 ret = ioctl(vfio_group_fd, VFIO_GROUP_SET_CONTAINER,
     823                 :            :                                 &vfio_container_fd);
     824         [ #  # ]:          0 :                 if (ret) {
     825                 :          0 :                         EAL_LOG(ERR,
     826                 :            :                                 "%s cannot add VFIO group to container, error "
     827                 :            :                                 "%i (%s)", dev_addr, errno, strerror(errno));
     828                 :          0 :                         close(vfio_group_fd);
     829                 :          0 :                         rte_vfio_clear_group(vfio_group_fd);
     830                 :          0 :                         return -1;
     831                 :            :                 }
     832                 :            : 
     833                 :            :                 /*
     834                 :            :                  * pick an IOMMU type and set up DMA mappings for container
     835                 :            :                  *
     836                 :            :                  * needs to be done only once, only when first group is
     837                 :            :                  * assigned to a container and only in primary process.
     838                 :            :                  * Note this can happen several times with the hotplug
     839                 :            :                  * functionality.
     840                 :            :                  */
     841         [ #  # ]:          0 :                 if (internal_conf->process_type == RTE_PROC_PRIMARY &&
     842   [ #  #  #  # ]:          0 :                                 vfio_cfg->vfio_active_groups == 1 &&
     843                 :          0 :                                 vfio_group_device_count(vfio_group_fd) == 0) {
     844                 :            :                         const struct vfio_iommu_type *t;
     845                 :            : 
     846                 :            :                         /* select an IOMMU type which we will be using */
     847                 :          0 :                         t = vfio_set_iommu_type(vfio_container_fd);
     848         [ #  # ]:          0 :                         if (!t) {
     849                 :          0 :                                 EAL_LOG(ERR,
     850                 :            :                                         "%s failed to select IOMMU type",
     851                 :            :                                         dev_addr);
     852                 :          0 :                                 close(vfio_group_fd);
     853                 :          0 :                                 rte_vfio_clear_group(vfio_group_fd);
     854                 :          0 :                                 return -1;
     855                 :            :                         }
     856                 :            :                         /* lock memory hotplug before mapping and release it
     857                 :            :                          * after registering callback, to prevent races
     858                 :            :                          */
     859                 :          0 :                         rte_mcfg_mem_read_lock();
     860         [ #  # ]:          0 :                         if (vfio_cfg == default_vfio_cfg)
     861                 :          0 :                                 ret = t->dma_map_func(vfio_container_fd);
     862                 :            :                         else
     863                 :            :                                 ret = 0;
     864         [ #  # ]:          0 :                         if (ret) {
     865                 :          0 :                                 EAL_LOG(ERR,
     866                 :            :                                         "%s DMA remapping failed, error "
     867                 :            :                                         "%i (%s)",
     868                 :            :                                         dev_addr, errno, strerror(errno));
     869                 :          0 :                                 close(vfio_group_fd);
     870                 :          0 :                                 rte_vfio_clear_group(vfio_group_fd);
     871                 :          0 :                                 rte_mcfg_mem_read_unlock();
     872                 :          0 :                                 return -1;
     873                 :            :                         }
     874                 :            : 
     875                 :          0 :                         vfio_cfg->vfio_iommu_type = t;
     876                 :            : 
     877                 :            :                         /* re-map all user-mapped segments */
     878                 :          0 :                         rte_spinlock_recursive_lock(&user_mem_maps->lock);
     879                 :            : 
     880                 :            :                         /* this IOMMU type may not support DMA mapping, but
     881                 :            :                          * if we have mappings in the list - that means we have
     882                 :            :                          * previously mapped something successfully, so we can
     883                 :            :                          * be sure that DMA mapping is supported.
     884                 :            :                          */
     885         [ #  # ]:          0 :                         for (i = 0; i < user_mem_maps->n_maps; i++) {
     886                 :            :                                 struct user_mem_map *map;
     887                 :            :                                 map = &user_mem_maps->maps[i];
     888                 :            : 
     889                 :          0 :                                 ret = t->dma_user_map_func(
     890                 :            :                                                 vfio_container_fd,
     891                 :            :                                                 map->addr, map->iova, map->len,
     892                 :            :                                                 1);
     893         [ #  # ]:          0 :                                 if (ret) {
     894                 :          0 :                                         EAL_LOG(ERR, "Couldn't map user memory for DMA: "
     895                 :            :                                                         "va: 0x%" PRIx64 " "
     896                 :            :                                                         "iova: 0x%" PRIx64 " "
     897                 :            :                                                         "len: 0x%" PRIu64,
     898                 :            :                                                         map->addr, map->iova,
     899                 :            :                                                         map->len);
     900                 :            :                                         rte_spinlock_recursive_unlock(
     901                 :            :                                                         &user_mem_maps->lock);
     902                 :          0 :                                         rte_mcfg_mem_read_unlock();
     903                 :          0 :                                         return -1;
     904                 :            :                                 }
     905                 :            :                         }
     906                 :            :                         rte_spinlock_recursive_unlock(&user_mem_maps->lock);
     907                 :            : 
     908                 :            :                         /* register callback for mem events */
     909         [ #  # ]:          0 :                         if (vfio_cfg == default_vfio_cfg)
     910                 :          0 :                                 ret = rte_mem_event_callback_register(
     911                 :            :                                         VFIO_MEM_EVENT_CLB_NAME,
     912                 :            :                                         vfio_mem_event_callback, NULL);
     913                 :            :                         else
     914                 :            :                                 ret = 0;
     915                 :            :                         /* unlock memory hotplug */
     916                 :          0 :                         rte_mcfg_mem_read_unlock();
     917                 :            : 
     918   [ #  #  #  # ]:          0 :                         if (ret && rte_errno != ENOTSUP) {
     919                 :          0 :                                 EAL_LOG(ERR, "Could not install memory event callback for VFIO");
     920                 :          0 :                                 return -1;
     921                 :            :                         }
     922         [ #  # ]:          0 :                         if (ret)
     923                 :          0 :                                 EAL_LOG(DEBUG, "Memory event callbacks not supported");
     924                 :            :                         else
     925                 :          0 :                                 EAL_LOG(DEBUG, "Installed memory event callback for VFIO");
     926                 :            :                 }
     927         [ #  # ]:          0 :         } else if (rte_eal_process_type() != RTE_PROC_PRIMARY &&
     928         [ #  # ]:          0 :                         vfio_cfg == default_vfio_cfg &&
     929         [ #  # ]:          0 :                         vfio_cfg->vfio_iommu_type == NULL) {
     930                 :            :                 /* if we're not a primary process, we do not set up the VFIO
     931                 :            :                  * container because it's already been set up by the primary
     932                 :            :                  * process. instead, we simply ask the primary about VFIO type
     933                 :            :                  * we are using, and set the VFIO config up appropriately.
     934                 :            :                  */
     935                 :          0 :                 ret = vfio_sync_default_container();
     936         [ #  # ]:          0 :                 if (ret < 0) {
     937                 :          0 :                         EAL_LOG(ERR, "Could not sync default VFIO container");
     938                 :          0 :                         close(vfio_group_fd);
     939                 :          0 :                         rte_vfio_clear_group(vfio_group_fd);
     940                 :          0 :                         return -1;
     941                 :            :                 }
     942                 :            :                 /* we have successfully initialized VFIO, notify user */
     943                 :          0 :                 const struct vfio_iommu_type *t =
     944                 :          0 :                                 default_vfio_cfg->vfio_iommu_type;
     945                 :          0 :                 EAL_LOG(INFO, "Using IOMMU type %d (%s)",
     946                 :            :                                 t->type_id, t->name);
     947                 :            :         }
     948                 :            : 
     949                 :          0 :         rte_eal_vfio_get_vf_token(vf_token);
     950                 :            : 
     951                 :            :         /* get a file descriptor for the device with VF token firstly */
     952         [ #  # ]:          0 :         if (!rte_uuid_is_null(vf_token)) {
     953                 :            :                 char vf_token_str[RTE_UUID_STRLEN];
     954                 :            :                 char dev[PATH_MAX];
     955                 :            : 
     956                 :          0 :                 rte_uuid_unparse(vf_token, vf_token_str, sizeof(vf_token_str));
     957                 :            :                 snprintf(dev, sizeof(dev),
     958                 :            :                          "%s vf_token=%s", dev_addr, vf_token_str);
     959                 :            : 
     960                 :          0 :                 *vfio_dev_fd = ioctl(vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD,
     961                 :            :                                      dev);
     962         [ #  # ]:          0 :                 if (*vfio_dev_fd >= 0)
     963                 :          0 :                         goto dev_get_info;
     964                 :            :         }
     965                 :            : 
     966                 :            :         /* get a file descriptor for the device */
     967                 :          0 :         *vfio_dev_fd = ioctl(vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD, dev_addr);
     968         [ #  # ]:          0 :         if (*vfio_dev_fd < 0) {
     969                 :            :                 /* if we cannot get a device fd, this implies a problem with
     970                 :            :                  * the VFIO group or the container not having IOMMU configured.
     971                 :            :                  */
     972                 :            : 
     973                 :          0 :                 EAL_LOG(WARNING, "Getting a vfio_dev_fd for %s failed",
     974                 :            :                                 dev_addr);
     975                 :          0 :                 close(vfio_group_fd);
     976                 :          0 :                 rte_vfio_clear_group(vfio_group_fd);
     977                 :          0 :                 return -1;
     978                 :            :         }
     979                 :            : 
     980                 :            :         /* test and setup the device */
     981                 :          0 : dev_get_info:
     982                 :          0 :         ret = ioctl(*vfio_dev_fd, VFIO_DEVICE_GET_INFO, device_info);
     983         [ #  # ]:          0 :         if (ret) {
     984                 :          0 :                 EAL_LOG(ERR, "%s cannot get device info, "
     985                 :            :                                 "error %i (%s)", dev_addr, errno,
     986                 :            :                                 strerror(errno));
     987                 :          0 :                 close(*vfio_dev_fd);
     988                 :          0 :                 close(vfio_group_fd);
     989                 :          0 :                 rte_vfio_clear_group(vfio_group_fd);
     990                 :          0 :                 return -1;
     991                 :            :         }
     992                 :          0 :         vfio_group_device_get(vfio_group_fd);
     993                 :            : 
     994                 :          0 :         return 0;
     995                 :            : }
     996                 :            : 
     997                 :            : RTE_EXPORT_SYMBOL(rte_vfio_release_device)
     998                 :            : int
     999                 :          0 : rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
    1000                 :            :                     int vfio_dev_fd)
    1001                 :            : {
    1002                 :            :         struct vfio_config *vfio_cfg;
    1003                 :            :         int vfio_group_fd;
    1004                 :            :         int iommu_group_num;
    1005                 :            :         int ret;
    1006                 :            : 
    1007                 :            :         /* we don't want any DMA mapping messages to come while we're detaching
    1008                 :            :          * VFIO device, because this might be the last device and we might need
    1009                 :            :          * to unregister the callback.
    1010                 :            :          */
    1011                 :          0 :         rte_mcfg_mem_read_lock();
    1012                 :            : 
    1013                 :            :         /* get group number */
    1014                 :          0 :         ret = rte_vfio_get_group_num(sysfs_base, dev_addr, &iommu_group_num);
    1015         [ #  # ]:          0 :         if (ret <= 0) {
    1016                 :          0 :                 EAL_LOG(WARNING, "%s not managed by VFIO driver",
    1017                 :            :                         dev_addr);
    1018                 :            :                 /* This is an error at this point. */
    1019                 :            :                 ret = -1;
    1020                 :          0 :                 goto out;
    1021                 :            :         }
    1022                 :            : 
    1023                 :            :         /* get the actual group fd */
    1024                 :          0 :         vfio_group_fd = rte_vfio_get_group_fd(iommu_group_num);
    1025         [ #  # ]:          0 :         if (vfio_group_fd < 0) {
    1026                 :          0 :                 EAL_LOG(INFO, "rte_vfio_get_group_fd failed for %s",
    1027                 :            :                                    dev_addr);
    1028                 :            :                 ret = vfio_group_fd;
    1029                 :          0 :                 goto out;
    1030                 :            :         }
    1031                 :            : 
    1032                 :            :         /* get the vfio_config it belongs to */
    1033                 :          0 :         vfio_cfg = get_vfio_cfg_by_group_num(iommu_group_num);
    1034         [ #  # ]:          0 :         vfio_cfg = vfio_cfg ? vfio_cfg : default_vfio_cfg;
    1035                 :            : 
    1036                 :            :         /* At this point we got an active group. Closing it will make the
    1037                 :            :          * container detachment. If this is the last active group, VFIO kernel
    1038                 :            :          * code will unset the container and the IOMMU mappings.
    1039                 :            :          */
    1040                 :            : 
    1041                 :            :         /* Closing a device */
    1042         [ #  # ]:          0 :         if (close(vfio_dev_fd) < 0) {
    1043                 :          0 :                 EAL_LOG(INFO, "Error when closing vfio_dev_fd for %s",
    1044                 :            :                                    dev_addr);
    1045                 :            :                 ret = -1;
    1046                 :          0 :                 goto out;
    1047                 :            :         }
    1048                 :            : 
    1049                 :            :         /* An VFIO group can have several devices attached. Just when there is
    1050                 :            :          * no devices remaining should the group be closed.
    1051                 :            :          */
    1052                 :          0 :         vfio_group_device_put(vfio_group_fd);
    1053         [ #  # ]:          0 :         if (!vfio_group_device_count(vfio_group_fd)) {
    1054                 :            : 
    1055         [ #  # ]:          0 :                 if (close(vfio_group_fd) < 0) {
    1056                 :          0 :                         EAL_LOG(INFO, "Error when closing vfio_group_fd for %s",
    1057                 :            :                                 dev_addr);
    1058                 :            :                         ret = -1;
    1059                 :          0 :                         goto out;
    1060                 :            :                 }
    1061                 :            : 
    1062         [ #  # ]:          0 :                 if (rte_vfio_clear_group(vfio_group_fd) < 0) {
    1063                 :          0 :                         EAL_LOG(INFO, "Error when clearing group for %s",
    1064                 :            :                                            dev_addr);
    1065                 :            :                         ret = -1;
    1066                 :          0 :                         goto out;
    1067                 :            :                 }
    1068                 :            :         }
    1069                 :            : 
    1070                 :            :         /* if there are no active device groups, unregister the callback to
    1071                 :            :          * avoid spurious attempts to map/unmap memory from VFIO.
    1072                 :            :          */
    1073   [ #  #  #  #  :          0 :         if (vfio_cfg == default_vfio_cfg && vfio_cfg->vfio_active_groups == 0 &&
                   #  # ]
    1074                 :          0 :                         rte_eal_process_type() != RTE_PROC_SECONDARY)
    1075                 :          0 :                 rte_mem_event_callback_unregister(VFIO_MEM_EVENT_CLB_NAME,
    1076                 :            :                                 NULL);
    1077                 :            : 
    1078                 :            :         /* success */
    1079                 :            :         ret = 0;
    1080                 :            : 
    1081                 :          0 : out:
    1082                 :          0 :         rte_mcfg_mem_read_unlock();
    1083                 :          0 :         return ret;
    1084                 :            : }
    1085                 :            : 
    1086                 :            : RTE_EXPORT_SYMBOL(rte_vfio_enable)
    1087                 :            : int
    1088                 :        185 : rte_vfio_enable(const char *modname)
    1089                 :            : {
    1090                 :            :         /* initialize group list */
    1091                 :            :         int i, j;
    1092                 :            :         int vfio_available;
    1093                 :            :         DIR *dir;
    1094                 :            :         const struct internal_config *internal_conf =
    1095                 :        185 :                 eal_get_internal_configuration();
    1096                 :            : 
    1097                 :        185 :         rte_spinlock_recursive_t lock = RTE_SPINLOCK_RECURSIVE_INITIALIZER;
    1098                 :            : 
    1099         [ +  + ]:      12025 :         for (i = 0; i < VFIO_MAX_CONTAINERS; i++) {
    1100                 :      11840 :                 vfio_cfgs[i].vfio_container_fd = -1;
    1101                 :      11840 :                 vfio_cfgs[i].vfio_active_groups = 0;
    1102                 :      11840 :                 vfio_cfgs[i].vfio_iommu_type = NULL;
    1103                 :      11840 :                 vfio_cfgs[i].mem_maps.lock = lock;
    1104                 :            : 
    1105         [ +  + ]:     769600 :                 for (j = 0; j < VFIO_MAX_GROUPS; j++) {
    1106                 :     757760 :                         vfio_cfgs[i].vfio_groups[j].fd = -1;
    1107                 :     757760 :                         vfio_cfgs[i].vfio_groups[j].group_num = -1;
    1108                 :     757760 :                         vfio_cfgs[i].vfio_groups[j].devices = 0;
    1109                 :            :                 }
    1110                 :            :         }
    1111                 :            : 
    1112                 :        185 :         EAL_LOG(DEBUG, "Probing VFIO support...");
    1113                 :            : 
    1114                 :            :         /* check if vfio module is loaded */
    1115                 :        185 :         vfio_available = rte_eal_check_module(modname);
    1116                 :            : 
    1117                 :            :         /* return error directly */
    1118         [ -  + ]:        185 :         if (vfio_available == -1) {
    1119                 :          0 :                 EAL_LOG(INFO, "Could not get loaded module details!");
    1120                 :          0 :                 return -1;
    1121                 :            :         }
    1122                 :            : 
    1123                 :            :         /* return 0 if VFIO modules not loaded */
    1124         [ -  + ]:        185 :         if (vfio_available == 0) {
    1125                 :          0 :                 EAL_LOG(DEBUG,
    1126                 :            :                         "VFIO modules not loaded, skipping VFIO support...");
    1127                 :          0 :                 return 0;
    1128                 :            :         }
    1129                 :            : 
    1130                 :            :         /* VFIO directory might not exist (e.g., unprivileged containers) */
    1131                 :        185 :         dir = opendir(VFIO_DIR);
    1132         [ -  + ]:        185 :         if (dir == NULL) {
    1133                 :          0 :                 EAL_LOG(DEBUG,
    1134                 :            :                         "VFIO directory does not exist, skipping VFIO support...");
    1135                 :          0 :                 return 0;
    1136                 :            :         }
    1137                 :        185 :         closedir(dir);
    1138                 :            : 
    1139         [ +  + ]:        185 :         if (internal_conf->process_type == RTE_PROC_PRIMARY) {
    1140         [ -  + ]:        158 :                 if (vfio_mp_sync_setup() == -1) {
    1141                 :          0 :                         default_vfio_cfg->vfio_container_fd = -1;
    1142                 :            :                 } else {
    1143                 :            :                         /* open a new container */
    1144                 :        158 :                         default_vfio_cfg->vfio_container_fd = rte_vfio_get_container_fd();
    1145                 :            :                 }
    1146                 :            :         } else {
    1147                 :            :                 /* get the default container from the primary process */
    1148                 :         27 :                 default_vfio_cfg->vfio_container_fd =
    1149                 :         27 :                                 vfio_get_default_container_fd();
    1150                 :            :         }
    1151                 :            : 
    1152                 :            :         /* check if we have VFIO driver enabled */
    1153         [ +  + ]:        185 :         if (default_vfio_cfg->vfio_container_fd != -1) {
    1154                 :        184 :                 EAL_LOG(INFO, "VFIO support initialized");
    1155                 :        184 :                 default_vfio_cfg->vfio_enabled = 1;
    1156                 :            :         } else {
    1157                 :          1 :                 EAL_LOG(NOTICE, "VFIO support could not be initialized");
    1158                 :            :         }
    1159                 :            : 
    1160                 :            :         return 0;
    1161                 :            : }
    1162                 :            : 
    1163                 :            : RTE_EXPORT_SYMBOL(rte_vfio_is_enabled)
    1164                 :            : int
    1165                 :          0 : rte_vfio_is_enabled(const char *modname)
    1166                 :            : {
    1167                 :          0 :         const int mod_available = rte_eal_check_module(modname) > 0;
    1168   [ #  #  #  # ]:          0 :         return default_vfio_cfg->vfio_enabled && mod_available;
    1169                 :            : }
    1170                 :            : 
    1171                 :            : int
    1172                 :         53 : vfio_get_default_container_fd(void)
    1173                 :            : {
    1174                 :            :         struct rte_mp_msg mp_req, *mp_rep;
    1175                 :         53 :         struct rte_mp_reply mp_reply = {0};
    1176                 :         53 :         struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
    1177                 :            :         struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param;
    1178                 :            :         int container_fd;
    1179                 :            :         const struct internal_config *internal_conf =
    1180                 :         53 :                 eal_get_internal_configuration();
    1181                 :            : 
    1182         [ +  + ]:         53 :         if (default_vfio_cfg->vfio_enabled)
    1183                 :         26 :                 return default_vfio_cfg->vfio_container_fd;
    1184                 :            : 
    1185         [ +  - ]:         27 :         if (internal_conf->process_type == RTE_PROC_PRIMARY) {
    1186                 :            :                 /* if we were secondary process we would try requesting
    1187                 :            :                  * container fd from the primary, but we're the primary
    1188                 :            :                  * process so just exit here
    1189                 :            :                  */
    1190                 :            :                 return -1;
    1191                 :            :         }
    1192                 :            : 
    1193                 :         27 :         p->req = SOCKET_REQ_DEFAULT_CONTAINER;
    1194                 :            :         strcpy(mp_req.name, EAL_VFIO_MP);
    1195                 :         27 :         mp_req.len_param = sizeof(*p);
    1196                 :         27 :         mp_req.num_fds = 0;
    1197                 :            : 
    1198         [ +  + ]:         27 :         if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
    1199         [ +  - ]:         26 :             mp_reply.nb_received == 1) {
    1200                 :         26 :                 mp_rep = &mp_reply.msgs[0];
    1201                 :            :                 p = (struct vfio_mp_param *)mp_rep->param;
    1202   [ +  -  +  - ]:         26 :                 if (p->result == SOCKET_OK && mp_rep->num_fds == 1) {
    1203                 :         26 :                         container_fd = mp_rep->fds[0];
    1204                 :         26 :                         free(mp_reply.msgs);
    1205                 :         26 :                         return container_fd;
    1206                 :            :                 }
    1207                 :            :         }
    1208                 :            : 
    1209                 :          1 :         free(mp_reply.msgs);
    1210                 :          1 :         EAL_LOG(ERR, "Cannot request default VFIO container fd");
    1211                 :          1 :         return -1;
    1212                 :            : }
    1213                 :            : 
    1214                 :            : int
    1215                 :          0 : vfio_get_iommu_type(void)
    1216                 :            : {
    1217         [ #  # ]:          0 :         if (default_vfio_cfg->vfio_iommu_type == NULL)
    1218                 :            :                 return -1;
    1219                 :            : 
    1220                 :          0 :         return default_vfio_cfg->vfio_iommu_type->type_id;
    1221                 :            : }
    1222                 :            : 
    1223                 :            : const struct vfio_iommu_type *
    1224                 :          0 : vfio_set_iommu_type(int vfio_container_fd)
    1225                 :            : {
    1226                 :            :         unsigned idx;
    1227         [ #  # ]:          0 :         for (idx = 0; idx < RTE_DIM(iommu_types); idx++) {
    1228                 :          0 :                 const struct vfio_iommu_type *t = &iommu_types[idx];
    1229                 :            : 
    1230                 :          0 :                 int ret = ioctl(vfio_container_fd, VFIO_SET_IOMMU,
    1231                 :          0 :                                 t->type_id);
    1232         [ #  # ]:          0 :                 if (!ret) {
    1233                 :          0 :                         EAL_LOG(INFO, "Using IOMMU type %d (%s)",
    1234                 :            :                                         t->type_id, t->name);
    1235                 :          0 :                         return t;
    1236                 :            :                 }
    1237                 :            :                 /* not an error, there may be more supported IOMMU types */
    1238                 :          0 :                 EAL_LOG(DEBUG, "Set IOMMU type %d (%s) failed, error "
    1239                 :            :                                 "%i (%s)", t->type_id, t->name, errno,
    1240                 :            :                                 strerror(errno));
    1241                 :            :         }
    1242                 :            :         /* if we didn't find a suitable IOMMU type, fail */
    1243                 :            :         return NULL;
    1244                 :            : }
    1245                 :            : 
    1246                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_vfio_get_device_info, 24.03)
    1247                 :            : int
    1248                 :          0 : rte_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
    1249                 :            :                 int *vfio_dev_fd, struct vfio_device_info *device_info)
    1250                 :            : {
    1251                 :            :         int ret;
    1252                 :            : 
    1253   [ #  #  #  # ]:          0 :         if (device_info == NULL || *vfio_dev_fd < 0)
    1254                 :            :                 return -1;
    1255                 :            : 
    1256         [ #  # ]:          0 :         if (*vfio_dev_fd == 0) {
    1257                 :          0 :                 ret = rte_vfio_setup_device(sysfs_base, dev_addr,
    1258                 :            :                                 vfio_dev_fd, device_info);
    1259         [ #  # ]:          0 :                 if (ret)
    1260                 :          0 :                         return -1;
    1261                 :            :         } else {
    1262                 :          0 :                 ret = ioctl(*vfio_dev_fd, VFIO_DEVICE_GET_INFO, device_info);
    1263         [ #  # ]:          0 :                 if (ret) {
    1264                 :          0 :                         EAL_LOG(ERR, "%s cannot get device info, error %i (%s)",
    1265                 :            :                                         dev_addr, errno, strerror(errno));
    1266                 :          0 :                         return -1;
    1267                 :            :                 }
    1268                 :            :         }
    1269                 :            : 
    1270                 :            :         return 0;
    1271                 :            : }
    1272                 :            : 
    1273                 :            : int
    1274                 :        158 : vfio_has_supported_extensions(int vfio_container_fd)
    1275                 :            : {
    1276                 :            :         int ret;
    1277                 :            :         unsigned idx, n_extensions = 0;
    1278         [ +  + ]:        632 :         for (idx = 0; idx < RTE_DIM(iommu_types); idx++) {
    1279                 :            :                 const struct vfio_iommu_type *t = &iommu_types[idx];
    1280                 :            : 
    1281                 :        474 :                 ret = ioctl(vfio_container_fd, VFIO_CHECK_EXTENSION,
    1282                 :        474 :                                 t->type_id);
    1283         [ -  + ]:        474 :                 if (ret < 0) {
    1284                 :          0 :                         EAL_LOG(ERR, "Could not get IOMMU type, error "
    1285                 :            :                                         "%i (%s)", errno, strerror(errno));
    1286                 :          0 :                         close(vfio_container_fd);
    1287                 :          0 :                         return -1;
    1288         [ +  + ]:        474 :                 } else if (ret == 1) {
    1289                 :            :                         /* we found a supported extension */
    1290                 :        158 :                         n_extensions++;
    1291                 :            :                 }
    1292         [ +  + ]:        790 :                 EAL_LOG(DEBUG, "IOMMU type %d (%s) is %s",
    1293                 :            :                                 t->type_id, t->name,
    1294                 :            :                                 ret ? "supported" : "not supported");
    1295                 :            :         }
    1296                 :            : 
    1297                 :            :         /* if we didn't find any supported IOMMU types, fail */
    1298         [ -  + ]:        158 :         if (!n_extensions) {
    1299                 :          0 :                 close(vfio_container_fd);
    1300                 :          0 :                 return -1;
    1301                 :            :         }
    1302                 :            : 
    1303                 :            :         return 0;
    1304                 :            : }
    1305                 :            : 
    1306                 :            : RTE_EXPORT_SYMBOL(rte_vfio_get_container_fd)
    1307                 :            : int
    1308                 :        158 : rte_vfio_get_container_fd(void)
    1309                 :            : {
    1310                 :            :         int ret, vfio_container_fd;
    1311                 :            :         struct rte_mp_msg mp_req, *mp_rep;
    1312                 :        158 :         struct rte_mp_reply mp_reply = {0};
    1313                 :        158 :         struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
    1314                 :            :         struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param;
    1315                 :            :         const struct internal_config *internal_conf =
    1316                 :        158 :                 eal_get_internal_configuration();
    1317                 :            : 
    1318                 :            : 
    1319                 :            :         /* if we're in a primary process, try to open the container */
    1320         [ +  - ]:        158 :         if (internal_conf->process_type == RTE_PROC_PRIMARY) {
    1321                 :            :                 vfio_container_fd = open(VFIO_CONTAINER_PATH, O_RDWR);
    1322         [ -  + ]:        158 :                 if (vfio_container_fd < 0) {
    1323                 :          0 :                         EAL_LOG(ERR,
    1324                 :            :                                         "Cannot open VFIO container %s, error "
    1325                 :            :                                         "%i (%s)", VFIO_CONTAINER_PATH,
    1326                 :            :                                         errno, strerror(errno));
    1327                 :          0 :                         return -1;
    1328                 :            :                 }
    1329                 :            : 
    1330                 :            :                 /* check VFIO API version */
    1331                 :        158 :                 ret = ioctl(vfio_container_fd, VFIO_GET_API_VERSION);
    1332         [ -  + ]:        158 :                 if (ret != VFIO_API_VERSION) {
    1333         [ #  # ]:          0 :                         if (ret < 0)
    1334                 :          0 :                                 EAL_LOG(ERR,
    1335                 :            :                                         "Could not get VFIO API version, error "
    1336                 :            :                                         "%i (%s)", errno, strerror(errno));
    1337                 :            :                         else
    1338                 :          0 :                                 EAL_LOG(ERR, "Unsupported VFIO API version!");
    1339                 :          0 :                         close(vfio_container_fd);
    1340                 :          0 :                         return -1;
    1341                 :            :                 }
    1342                 :            : 
    1343                 :        158 :                 ret = vfio_has_supported_extensions(vfio_container_fd);
    1344         [ -  + ]:        158 :                 if (ret) {
    1345                 :          0 :                         EAL_LOG(ERR,
    1346                 :            :                                 "No supported IOMMU extensions found!");
    1347                 :          0 :                         return -1;
    1348                 :            :                 }
    1349                 :            : 
    1350                 :            :                 return vfio_container_fd;
    1351                 :            :         }
    1352                 :            :         /*
    1353                 :            :          * if we're in a secondary process, request container fd from the
    1354                 :            :          * primary process via mp channel
    1355                 :            :          */
    1356                 :          0 :         p->req = SOCKET_REQ_CONTAINER;
    1357                 :            :         strcpy(mp_req.name, EAL_VFIO_MP);
    1358                 :          0 :         mp_req.len_param = sizeof(*p);
    1359                 :          0 :         mp_req.num_fds = 0;
    1360                 :            : 
    1361                 :            :         vfio_container_fd = -1;
    1362         [ #  # ]:          0 :         if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
    1363         [ #  # ]:          0 :             mp_reply.nb_received == 1) {
    1364                 :          0 :                 mp_rep = &mp_reply.msgs[0];
    1365                 :            :                 p = (struct vfio_mp_param *)mp_rep->param;
    1366   [ #  #  #  # ]:          0 :                 if (p->result == SOCKET_OK && mp_rep->num_fds == 1) {
    1367                 :          0 :                         vfio_container_fd = mp_rep->fds[0];
    1368                 :          0 :                         free(mp_reply.msgs);
    1369                 :          0 :                         return vfio_container_fd;
    1370                 :            :                 }
    1371                 :            :         }
    1372                 :            : 
    1373                 :          0 :         free(mp_reply.msgs);
    1374                 :          0 :         EAL_LOG(ERR, "Cannot request VFIO container fd");
    1375                 :          0 :         return -1;
    1376                 :            : }
    1377                 :            : 
    1378                 :            : RTE_EXPORT_SYMBOL(rte_vfio_get_group_num)
    1379                 :            : int
    1380                 :          0 : rte_vfio_get_group_num(const char *sysfs_base,
    1381                 :            :                 const char *dev_addr, int *iommu_group_num)
    1382                 :            : {
    1383                 :            :         char linkname[PATH_MAX];
    1384                 :            :         char filename[PATH_MAX];
    1385                 :            :         char *tok[16], *group_tok, *end;
    1386                 :            :         int ret;
    1387                 :            : 
    1388                 :            :         memset(linkname, 0, sizeof(linkname));
    1389                 :            :         memset(filename, 0, sizeof(filename));
    1390                 :            : 
    1391                 :            :         /* try to find out IOMMU group for this device */
    1392                 :            :         snprintf(linkname, sizeof(linkname),
    1393                 :            :                          "%s/%s/iommu_group", sysfs_base, dev_addr);
    1394                 :            : 
    1395                 :          0 :         ret = readlink(linkname, filename, sizeof(filename));
    1396                 :            : 
    1397                 :            :         /* if the link doesn't exist, no VFIO for us */
    1398         [ #  # ]:          0 :         if (ret < 0)
    1399                 :            :                 return 0;
    1400                 :            : 
    1401                 :          0 :         ret = rte_strsplit(filename, sizeof(filename),
    1402                 :            :                         tok, RTE_DIM(tok), '/');
    1403                 :            : 
    1404         [ #  # ]:          0 :         if (ret <= 0) {
    1405                 :          0 :                 EAL_LOG(ERR, "%s cannot get IOMMU group", dev_addr);
    1406                 :          0 :                 return -1;
    1407                 :            :         }
    1408                 :            : 
    1409                 :            :         /* IOMMU group is always the last token */
    1410                 :          0 :         errno = 0;
    1411                 :          0 :         group_tok = tok[ret - 1];
    1412                 :          0 :         end = group_tok;
    1413                 :          0 :         *iommu_group_num = strtol(group_tok, &end, 10);
    1414   [ #  #  #  #  :          0 :         if ((end != group_tok && *end != '\0') || errno != 0) {
                   #  # ]
    1415                 :          0 :                 EAL_LOG(ERR, "%s error parsing IOMMU number!", dev_addr);
    1416                 :          0 :                 return -1;
    1417                 :            :         }
    1418                 :            : 
    1419                 :            :         return 1;
    1420                 :            : }
    1421                 :            : 
    1422                 :            : static int
    1423                 :          0 : type1_map(const struct rte_memseg_list *msl, const struct rte_memseg *ms,
    1424                 :            :                 void *arg)
    1425                 :            : {
    1426                 :            :         int *vfio_container_fd = arg;
    1427                 :            : 
    1428                 :            :         /* skip external memory that isn't a heap */
    1429   [ #  #  #  # ]:          0 :         if (msl->external && !msl->heap)
    1430                 :            :                 return 0;
    1431                 :            : 
    1432                 :            :         /* skip any segments with invalid IOVA addresses */
    1433         [ #  # ]:          0 :         if (ms->iova == RTE_BAD_IOVA)
    1434                 :            :                 return 0;
    1435                 :            : 
    1436                 :          0 :         return vfio_type1_dma_mem_map(*vfio_container_fd, ms->addr_64, ms->iova,
    1437                 :          0 :                         ms->len, 1);
    1438                 :            : }
    1439                 :            : 
    1440                 :            : static int
    1441                 :          0 : vfio_type1_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,
    1442                 :            :                 uint64_t len, int do_map)
    1443                 :            : {
    1444                 :            :         struct vfio_iommu_type1_dma_map dma_map;
    1445                 :            :         struct vfio_iommu_type1_dma_unmap dma_unmap;
    1446                 :            :         int ret;
    1447                 :            : 
    1448         [ #  # ]:          0 :         if (do_map != 0) {
    1449                 :            :                 memset(&dma_map, 0, sizeof(dma_map));
    1450                 :          0 :                 dma_map.argsz = sizeof(struct vfio_iommu_type1_dma_map);
    1451                 :          0 :                 dma_map.vaddr = vaddr;
    1452                 :          0 :                 dma_map.size = len;
    1453                 :          0 :                 dma_map.iova = iova;
    1454                 :          0 :                 dma_map.flags = VFIO_DMA_MAP_FLAG_READ |
    1455                 :            :                                 VFIO_DMA_MAP_FLAG_WRITE;
    1456                 :            : 
    1457                 :          0 :                 ret = ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map);
    1458         [ #  # ]:          0 :                 if (ret) {
    1459                 :            :                         /**
    1460                 :            :                          * In case the mapping was already done EEXIST will be
    1461                 :            :                          * returned from kernel.
    1462                 :            :                          */
    1463         [ #  # ]:          0 :                         if (errno == EEXIST) {
    1464                 :          0 :                                 EAL_LOG(DEBUG,
    1465                 :            :                                         "Memory segment is already mapped, skipping");
    1466                 :            :                         } else {
    1467                 :          0 :                                 EAL_LOG(ERR,
    1468                 :            :                                         "Cannot set up DMA remapping, error "
    1469                 :            :                                         "%i (%s)", errno, strerror(errno));
    1470                 :          0 :                                 return -1;
    1471                 :            :                         }
    1472                 :            :                 }
    1473                 :            :         } else {
    1474                 :            :                 memset(&dma_unmap, 0, sizeof(dma_unmap));
    1475                 :          0 :                 dma_unmap.argsz = sizeof(struct vfio_iommu_type1_dma_unmap);
    1476                 :          0 :                 dma_unmap.size = len;
    1477                 :          0 :                 dma_unmap.iova = iova;
    1478                 :            : 
    1479                 :          0 :                 ret = ioctl(vfio_container_fd, VFIO_IOMMU_UNMAP_DMA,
    1480                 :            :                                 &dma_unmap);
    1481         [ #  # ]:          0 :                 if (ret) {
    1482                 :          0 :                         EAL_LOG(ERR, "Cannot clear DMA remapping, error "
    1483                 :            :                                         "%i (%s)", errno, strerror(errno));
    1484                 :          0 :                         return -1;
    1485         [ #  # ]:          0 :                 } else if (dma_unmap.size != len) {
    1486                 :          0 :                         EAL_LOG(ERR, "Unexpected size %"PRIu64
    1487                 :            :                                 " of DMA remapping cleared instead of %"PRIu64,
    1488                 :            :                                 (uint64_t)dma_unmap.size, len);
    1489                 :          0 :                         rte_errno = EIO;
    1490                 :          0 :                         return -1;
    1491                 :            :                 }
    1492                 :            :         }
    1493                 :            : 
    1494                 :            :         return 0;
    1495                 :            : }
    1496                 :            : 
    1497                 :            : static int
    1498                 :          0 : vfio_type1_dma_map(int vfio_container_fd)
    1499                 :            : {
    1500                 :          0 :         return rte_memseg_walk(type1_map, &vfio_container_fd);
    1501                 :            : }
    1502                 :            : 
    1503                 :            : /* Track the size of the statically allocated DMA window for SPAPR */
    1504                 :            : uint64_t spapr_dma_win_len;
    1505                 :            : uint64_t spapr_dma_win_page_sz;
    1506                 :            : 
    1507                 :            : static int
    1508                 :          0 : vfio_spapr_dma_do_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,
    1509                 :            :                 uint64_t len, int do_map)
    1510                 :            : {
    1511                 :          0 :         struct vfio_iommu_spapr_register_memory reg = {
    1512                 :            :                 .argsz = sizeof(reg),
    1513                 :            :                 .vaddr = (uintptr_t) vaddr,
    1514                 :            :                 .size = len,
    1515                 :            :                 .flags = 0
    1516                 :            :         };
    1517                 :            :         int ret;
    1518                 :            : 
    1519         [ #  # ]:          0 :         if (do_map != 0) {
    1520                 :            :                 struct vfio_iommu_type1_dma_map dma_map;
    1521                 :            : 
    1522         [ #  # ]:          0 :                 if (iova + len > spapr_dma_win_len) {
    1523                 :          0 :                         EAL_LOG(ERR, "DMA map attempt outside DMA window");
    1524                 :          0 :                         return -1;
    1525                 :            :                 }
    1526                 :            : 
    1527                 :          0 :                 ret = ioctl(vfio_container_fd,
    1528                 :            :                                 VFIO_IOMMU_SPAPR_REGISTER_MEMORY, &reg);
    1529         [ #  # ]:          0 :                 if (ret) {
    1530                 :          0 :                         EAL_LOG(ERR,
    1531                 :            :                                 "Cannot register vaddr for IOMMU, error "
    1532                 :            :                                 "%i (%s)", errno, strerror(errno));
    1533                 :          0 :                         return -1;
    1534                 :            :                 }
    1535                 :            : 
    1536                 :            :                 memset(&dma_map, 0, sizeof(dma_map));
    1537                 :          0 :                 dma_map.argsz = sizeof(struct vfio_iommu_type1_dma_map);
    1538                 :          0 :                 dma_map.vaddr = vaddr;
    1539                 :          0 :                 dma_map.size = len;
    1540                 :          0 :                 dma_map.iova = iova;
    1541                 :          0 :                 dma_map.flags = VFIO_DMA_MAP_FLAG_READ |
    1542                 :            :                                 VFIO_DMA_MAP_FLAG_WRITE;
    1543                 :            : 
    1544                 :          0 :                 ret = ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map);
    1545         [ #  # ]:          0 :                 if (ret) {
    1546                 :          0 :                         EAL_LOG(ERR, "Cannot map vaddr for IOMMU, error "
    1547                 :            :                                         "%i (%s)", errno, strerror(errno));
    1548                 :          0 :                         return -1;
    1549                 :            :                 }
    1550                 :            : 
    1551                 :            :         } else {
    1552                 :            :                 struct vfio_iommu_type1_dma_map dma_unmap;
    1553                 :            : 
    1554                 :            :                 memset(&dma_unmap, 0, sizeof(dma_unmap));
    1555                 :          0 :                 dma_unmap.argsz = sizeof(struct vfio_iommu_type1_dma_unmap);
    1556                 :          0 :                 dma_unmap.size = len;
    1557                 :          0 :                 dma_unmap.iova = iova;
    1558                 :            : 
    1559                 :          0 :                 ret = ioctl(vfio_container_fd, VFIO_IOMMU_UNMAP_DMA,
    1560                 :            :                                 &dma_unmap);
    1561         [ #  # ]:          0 :                 if (ret) {
    1562                 :          0 :                         EAL_LOG(ERR, "Cannot unmap vaddr for IOMMU, error "
    1563                 :            :                                         "%i (%s)", errno, strerror(errno));
    1564                 :          0 :                         return -1;
    1565                 :            :                 }
    1566                 :            : 
    1567                 :          0 :                 ret = ioctl(vfio_container_fd,
    1568                 :            :                                 VFIO_IOMMU_SPAPR_UNREGISTER_MEMORY, &reg);
    1569         [ #  # ]:          0 :                 if (ret) {
    1570                 :          0 :                         EAL_LOG(ERR,
    1571                 :            :                                 "Cannot unregister vaddr for IOMMU, error "
    1572                 :            :                                 "%i (%s)", errno, strerror(errno));
    1573                 :          0 :                         return -1;
    1574                 :            :                 }
    1575                 :            :         }
    1576                 :            : 
    1577                 :            :         return ret;
    1578                 :            : }
    1579                 :            : 
    1580                 :            : static int
    1581                 :          0 : vfio_spapr_map_walk(const struct rte_memseg_list *msl,
    1582                 :            :                 const struct rte_memseg *ms, void *arg)
    1583                 :            : {
    1584                 :            :         int *vfio_container_fd = arg;
    1585                 :            : 
    1586                 :            :         /* skip external memory that isn't a heap */
    1587   [ #  #  #  # ]:          0 :         if (msl->external && !msl->heap)
    1588                 :            :                 return 0;
    1589                 :            : 
    1590                 :            :         /* skip any segments with invalid IOVA addresses */
    1591         [ #  # ]:          0 :         if (ms->iova == RTE_BAD_IOVA)
    1592                 :            :                 return 0;
    1593                 :            : 
    1594                 :          0 :         return vfio_spapr_dma_do_map(*vfio_container_fd,
    1595                 :          0 :                 ms->addr_64, ms->iova, ms->len, 1);
    1596                 :            : }
    1597                 :            : 
    1598                 :            : struct spapr_size_walk_param {
    1599                 :            :         uint64_t max_va;
    1600                 :            :         uint64_t page_sz;
    1601                 :            :         bool is_user_managed;
    1602                 :            : };
    1603                 :            : 
    1604                 :            : /*
    1605                 :            :  * In order to set the DMA window size required for the SPAPR IOMMU
    1606                 :            :  * we need to walk the existing virtual memory allocations as well as
    1607                 :            :  * find the hugepage size used.
    1608                 :            :  */
    1609                 :            : static int
    1610                 :          0 : vfio_spapr_size_walk(const struct rte_memseg_list *msl, void *arg)
    1611                 :            : {
    1612                 :            :         struct spapr_size_walk_param *param = arg;
    1613                 :          0 :         uint64_t max = (uint64_t) msl->base_va + (uint64_t) msl->len;
    1614                 :            : 
    1615   [ #  #  #  # ]:          0 :         if (msl->external && !msl->heap) {
    1616                 :            :                 /* ignore user managed external memory */
    1617                 :          0 :                 param->is_user_managed = true;
    1618                 :          0 :                 return 0;
    1619                 :            :         }
    1620                 :            : 
    1621         [ #  # ]:          0 :         if (max > param->max_va) {
    1622                 :          0 :                 param->page_sz = msl->page_sz;
    1623                 :          0 :                 param->max_va = max;
    1624                 :            :         }
    1625                 :            : 
    1626                 :            :         return 0;
    1627                 :            : }
    1628                 :            : 
    1629                 :            : /*
    1630                 :            :  * Find the highest memory address used in physical or virtual address
    1631                 :            :  * space and use that as the top of the DMA window.
    1632                 :            :  */
    1633                 :            : static int
    1634                 :          0 : find_highest_mem_addr(struct spapr_size_walk_param *param)
    1635                 :            : {
    1636                 :            :         /* find the maximum IOVA address for setting the DMA window size */
    1637         [ #  # ]:          0 :         if (rte_eal_iova_mode() == RTE_IOVA_PA) {
    1638                 :            :                 static const char proc_iomem[] = "/proc/iomem";
    1639                 :            :                 static const char str_sysram[] = "System RAM";
    1640                 :            :                 uint64_t start, end, max = 0;
    1641                 :          0 :                 char *line = NULL;
    1642                 :            :                 char *dash, *space;
    1643                 :            :                 size_t line_len;
    1644                 :            : 
    1645                 :            :                 /*
    1646                 :            :                  * Example "System RAM" in /proc/iomem:
    1647                 :            :                  * 00000000-1fffffffff : System RAM
    1648                 :            :                  * 200000000000-201fffffffff : System RAM
    1649                 :            :                  */
    1650                 :          0 :                 FILE *fd = fopen(proc_iomem, "r");
    1651         [ #  # ]:          0 :                 if (fd == NULL) {
    1652                 :          0 :                         EAL_LOG(ERR, "Cannot open %s", proc_iomem);
    1653                 :          0 :                         return -1;
    1654                 :            :                 }
    1655                 :            :                 /* Scan /proc/iomem for the highest PA in the system */
    1656         [ #  # ]:          0 :                 while (getline(&line, &line_len, fd) != -1) {
    1657         [ #  # ]:          0 :                         if (strstr(line, str_sysram) == NULL)
    1658                 :          0 :                                 continue;
    1659                 :            : 
    1660                 :          0 :                         space = strstr(line, " ");
    1661                 :          0 :                         dash = strstr(line, "-");
    1662                 :            : 
    1663                 :            :                         /* Validate the format of the memory string */
    1664   [ #  #  #  # ]:          0 :                         if (space == NULL || dash == NULL || space < dash) {
    1665                 :          0 :                                 EAL_LOG(ERR, "Can't parse line \"%s\" in file %s",
    1666                 :            :                                         line, proc_iomem);
    1667                 :          0 :                                 continue;
    1668                 :            :                         }
    1669                 :            : 
    1670                 :          0 :                         start = strtoull(line, NULL, 16);
    1671                 :          0 :                         end   = strtoull(dash + 1, NULL, 16);
    1672                 :          0 :                         EAL_LOG(DEBUG, "Found system RAM from 0x%" PRIx64
    1673                 :            :                                 " to 0x%" PRIx64, start, end);
    1674                 :            :                         if (end > max)
    1675                 :            :                                 max = end;
    1676                 :            :                 }
    1677                 :          0 :                 free(line);
    1678                 :          0 :                 fclose(fd);
    1679                 :            : 
    1680         [ #  # ]:          0 :                 if (max == 0) {
    1681                 :          0 :                         EAL_LOG(ERR, "Failed to find valid \"System RAM\" "
    1682                 :            :                                 "entry in file %s", proc_iomem);
    1683                 :          0 :                         return -1;
    1684                 :            :                 }
    1685                 :            : 
    1686                 :          0 :                 spapr_dma_win_len = rte_align64pow2(max + 1);
    1687                 :          0 :                 return 0;
    1688         [ #  # ]:          0 :         } else if (rte_eal_iova_mode() == RTE_IOVA_VA) {
    1689                 :          0 :                 EAL_LOG(DEBUG, "Highest VA address in memseg list is 0x%"
    1690                 :            :                         PRIx64, param->max_va);
    1691                 :          0 :                 spapr_dma_win_len = rte_align64pow2(param->max_va);
    1692                 :          0 :                 return 0;
    1693                 :            :         }
    1694                 :            : 
    1695                 :          0 :         spapr_dma_win_len = 0;
    1696                 :          0 :         EAL_LOG(ERR, "Unsupported IOVA mode");
    1697                 :          0 :         return -1;
    1698                 :            : }
    1699                 :            : 
    1700                 :            : 
    1701                 :            : /*
    1702                 :            :  * The SPAPRv2 IOMMU supports 2 DMA windows with starting
    1703                 :            :  * address at 0 or 1<<59.  By default, a DMA window is set
    1704                 :            :  * at address 0, 2GB long, with a 4KB page.  For DPDK we
    1705                 :            :  * must remove the default window and setup a new DMA window
    1706                 :            :  * based on the hugepage size and memory requirements of
    1707                 :            :  * the application before we can map memory for DMA.
    1708                 :            :  */
    1709                 :            : static int
    1710                 :          0 : spapr_dma_win_size(void)
    1711                 :            : {
    1712                 :            :         struct spapr_size_walk_param param;
    1713                 :            : 
    1714                 :            :         /* only create DMA window once */
    1715         [ #  # ]:          0 :         if (spapr_dma_win_len > 0)
    1716                 :            :                 return 0;
    1717                 :            : 
    1718                 :            :         /* walk the memseg list to find the page size/max VA address */
    1719                 :            :         memset(&param, 0, sizeof(param));
    1720         [ #  # ]:          0 :         if (rte_memseg_list_walk(vfio_spapr_size_walk, &param) < 0) {
    1721                 :          0 :                 EAL_LOG(ERR, "Failed to walk memseg list for DMA window size");
    1722                 :          0 :                 return -1;
    1723                 :            :         }
    1724                 :            : 
    1725                 :            :         /* we can't be sure if DMA window covers external memory */
    1726         [ #  # ]:          0 :         if (param.is_user_managed)
    1727                 :          0 :                 EAL_LOG(WARNING, "Detected user managed external memory which may not be managed by the IOMMU");
    1728                 :            : 
    1729                 :            :         /* check physical/virtual memory size */
    1730         [ #  # ]:          0 :         if (find_highest_mem_addr(&param) < 0)
    1731                 :            :                 return -1;
    1732                 :          0 :         EAL_LOG(DEBUG, "Setting DMA window size to 0x%" PRIx64,
    1733                 :            :                 spapr_dma_win_len);
    1734                 :          0 :         spapr_dma_win_page_sz = param.page_sz;
    1735                 :          0 :         rte_mem_set_dma_mask(rte_ctz64(spapr_dma_win_len));
    1736                 :          0 :         return 0;
    1737                 :            : }
    1738                 :            : 
    1739                 :            : static int
    1740                 :          0 : vfio_spapr_create_dma_window(int vfio_container_fd)
    1741                 :            : {
    1742                 :          0 :         struct vfio_iommu_spapr_tce_create create = {
    1743                 :            :                 .argsz = sizeof(create), };
    1744                 :          0 :         struct vfio_iommu_spapr_tce_remove remove = {
    1745                 :            :                 .argsz = sizeof(remove), };
    1746                 :          0 :         struct vfio_iommu_spapr_tce_info info = {
    1747                 :            :                 .argsz = sizeof(info), };
    1748                 :            :         int ret;
    1749                 :            : 
    1750                 :          0 :         ret = spapr_dma_win_size();
    1751         [ #  # ]:          0 :         if (ret < 0)
    1752                 :            :                 return ret;
    1753                 :            : 
    1754                 :          0 :         ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_GET_INFO, &info);
    1755         [ #  # ]:          0 :         if (ret) {
    1756                 :          0 :                 EAL_LOG(ERR, "Cannot get IOMMU info, error %i (%s)",
    1757                 :            :                         errno, strerror(errno));
    1758                 :          0 :                 return -1;
    1759                 :            :         }
    1760                 :            : 
    1761                 :            :         /*
    1762                 :            :          * sPAPR v1/v2 IOMMU always has a default 1G DMA window set.  The window
    1763                 :            :          * can't be changed for v1 but it can be changed for v2. Since DPDK only
    1764                 :            :          * supports v2, remove the default DMA window so it can be resized.
    1765                 :            :          */
    1766                 :          0 :         remove.start_addr = info.dma32_window_start;
    1767                 :          0 :         ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove);
    1768         [ #  # ]:          0 :         if (ret)
    1769                 :            :                 return -1;
    1770                 :            : 
    1771                 :            :         /* create a new DMA window (start address is not selectable) */
    1772                 :          0 :         create.window_size = spapr_dma_win_len;
    1773                 :          0 :         create.page_shift  = rte_ctz64(spapr_dma_win_page_sz);
    1774                 :          0 :         create.levels = 1;
    1775                 :          0 :         ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_CREATE, &create);
    1776                 :            : #ifdef VFIO_IOMMU_SPAPR_INFO_DDW
    1777                 :            :         /*
    1778                 :            :          * The vfio_iommu_spapr_tce_info structure was modified in
    1779                 :            :          * Linux kernel 4.2.0 to add support for the
    1780                 :            :          * vfio_iommu_spapr_tce_ddw_info structure needed to try
    1781                 :            :          * multiple table levels.  Skip the attempt if running with
    1782                 :            :          * an older kernel.
    1783                 :            :          */
    1784         [ #  # ]:          0 :         if (ret) {
    1785                 :            :                 /* if at first we don't succeed, try more levels */
    1786                 :            :                 uint32_t levels;
    1787                 :            : 
    1788                 :          0 :                 for (levels = create.levels + 1;
    1789   [ #  #  #  # ]:          0 :                         ret && levels <= info.ddw.levels; levels++) {
    1790                 :          0 :                         create.levels = levels;
    1791                 :          0 :                         ret = ioctl(vfio_container_fd,
    1792                 :            :                                 VFIO_IOMMU_SPAPR_TCE_CREATE, &create);
    1793                 :            :                 }
    1794                 :            :         }
    1795                 :            : #endif /* VFIO_IOMMU_SPAPR_INFO_DDW */
    1796         [ #  # ]:          0 :         if (ret) {
    1797                 :          0 :                 EAL_LOG(ERR, "Cannot create new DMA window, error "
    1798                 :            :                                 "%i (%s)", errno, strerror(errno));
    1799                 :          0 :                 EAL_LOG(ERR,
    1800                 :            :                         "Consider using a larger hugepage size if supported by the system");
    1801                 :          0 :                 return -1;
    1802                 :            :         }
    1803                 :            : 
    1804                 :            :         /* verify the start address  */
    1805         [ #  # ]:          0 :         if (create.start_addr != 0) {
    1806                 :          0 :                 EAL_LOG(ERR, "Received unsupported start address 0x%"
    1807                 :            :                         PRIx64, (uint64_t)create.start_addr);
    1808                 :          0 :                 return -1;
    1809                 :            :         }
    1810                 :            :         return ret;
    1811                 :            : }
    1812                 :            : 
    1813                 :            : static int
    1814                 :          0 : vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr,
    1815                 :            :                 uint64_t iova, uint64_t len, int do_map)
    1816                 :            : {
    1817                 :            :         int ret = 0;
    1818                 :            : 
    1819         [ #  # ]:          0 :         if (do_map) {
    1820         [ #  # ]:          0 :                 if (vfio_spapr_dma_do_map(vfio_container_fd,
    1821                 :            :                         vaddr, iova, len, 1)) {
    1822                 :          0 :                         EAL_LOG(ERR, "Failed to map DMA");
    1823                 :            :                         ret = -1;
    1824                 :            :                 }
    1825                 :            :         } else {
    1826         [ #  # ]:          0 :                 if (vfio_spapr_dma_do_map(vfio_container_fd,
    1827                 :            :                         vaddr, iova, len, 0)) {
    1828                 :          0 :                         EAL_LOG(ERR, "Failed to unmap DMA");
    1829                 :            :                         ret = -1;
    1830                 :            :                 }
    1831                 :            :         }
    1832                 :            : 
    1833                 :          0 :         return ret;
    1834                 :            : }
    1835                 :            : 
    1836                 :            : static int
    1837                 :          0 : vfio_spapr_dma_map(int vfio_container_fd)
    1838                 :            : {
    1839         [ #  # ]:          0 :         if (vfio_spapr_create_dma_window(vfio_container_fd) < 0) {
    1840                 :          0 :                 EAL_LOG(ERR, "Could not create new DMA window!");
    1841                 :          0 :                 return -1;
    1842                 :            :         }
    1843                 :            : 
    1844                 :            :         /* map all existing DPDK segments for DMA */
    1845         [ #  # ]:          0 :         if (rte_memseg_walk(vfio_spapr_map_walk, &vfio_container_fd) < 0)
    1846                 :          0 :                 return -1;
    1847                 :            : 
    1848                 :            :         return 0;
    1849                 :            : }
    1850                 :            : 
    1851                 :            : static int
    1852                 :          0 : vfio_noiommu_dma_map(int __rte_unused vfio_container_fd)
    1853                 :            : {
    1854                 :            :         /* No-IOMMU mode does not need DMA mapping */
    1855                 :          0 :         return 0;
    1856                 :            : }
    1857                 :            : 
    1858                 :            : static int
    1859                 :          0 : vfio_noiommu_dma_mem_map(int __rte_unused vfio_container_fd,
    1860                 :            :                          uint64_t __rte_unused vaddr,
    1861                 :            :                          uint64_t __rte_unused iova, uint64_t __rte_unused len,
    1862                 :            :                          int __rte_unused do_map)
    1863                 :            : {
    1864                 :            :         /* No-IOMMU mode does not need DMA mapping */
    1865                 :          0 :         return 0;
    1866                 :            : }
    1867                 :            : 
    1868                 :            : static int
    1869                 :          0 : vfio_dma_mem_map(struct vfio_config *vfio_cfg, uint64_t vaddr, uint64_t iova,
    1870                 :            :                 uint64_t len, int do_map)
    1871                 :            : {
    1872                 :          0 :         const struct vfio_iommu_type *t = vfio_cfg->vfio_iommu_type;
    1873                 :            : 
    1874         [ #  # ]:          0 :         if (!t) {
    1875                 :          0 :                 EAL_LOG(ERR, "VFIO support not initialized");
    1876                 :          0 :                 rte_errno = ENODEV;
    1877                 :          0 :                 return -1;
    1878                 :            :         }
    1879                 :            : 
    1880         [ #  # ]:          0 :         if (!t->dma_user_map_func) {
    1881                 :          0 :                 EAL_LOG(ERR,
    1882                 :            :                         "VFIO custom DMA region mapping not supported by IOMMU %s",
    1883                 :            :                         t->name);
    1884                 :          0 :                 rte_errno = ENOTSUP;
    1885                 :          0 :                 return -1;
    1886                 :            :         }
    1887                 :            : 
    1888                 :          0 :         return t->dma_user_map_func(vfio_cfg->vfio_container_fd, vaddr, iova,
    1889                 :            :                         len, do_map);
    1890                 :            : }
    1891                 :            : 
    1892                 :            : static int
    1893                 :          0 : container_dma_map(struct vfio_config *vfio_cfg, uint64_t vaddr, uint64_t iova,
    1894                 :            :                 uint64_t len)
    1895                 :            : {
    1896                 :            :         struct user_mem_map *new_map;
    1897                 :            :         struct user_mem_maps *user_mem_maps;
    1898                 :            :         bool has_partial_unmap;
    1899                 :            :         int ret = 0;
    1900                 :            : 
    1901                 :          0 :         user_mem_maps = &vfio_cfg->mem_maps;
    1902                 :          0 :         rte_spinlock_recursive_lock(&user_mem_maps->lock);
    1903         [ #  # ]:          0 :         if (user_mem_maps->n_maps == VFIO_MAX_USER_MEM_MAPS) {
    1904                 :          0 :                 EAL_LOG(ERR, "No more space for user mem maps");
    1905                 :          0 :                 rte_errno = ENOMEM;
    1906                 :            :                 ret = -1;
    1907                 :          0 :                 goto out;
    1908                 :            :         }
    1909                 :            :         /* map the entry */
    1910         [ #  # ]:          0 :         if (vfio_dma_mem_map(vfio_cfg, vaddr, iova, len, 1)) {
    1911                 :            :                 /* technically, this will fail if there are currently no devices
    1912                 :            :                  * plugged in, even if a device were added later, this mapping
    1913                 :            :                  * might have succeeded. however, since we cannot verify if this
    1914                 :            :                  * is a valid mapping without having a device attached, consider
    1915                 :            :                  * this to be unsupported, because we can't just store any old
    1916                 :            :                  * mapping and pollute list of active mappings willy-nilly.
    1917                 :            :                  */
    1918                 :          0 :                 EAL_LOG(ERR, "Couldn't map new region for DMA");
    1919                 :            :                 ret = -1;
    1920                 :          0 :                 goto out;
    1921                 :            :         }
    1922                 :            :         /* do we have partial unmap support? */
    1923                 :          0 :         has_partial_unmap = vfio_cfg->vfio_iommu_type->partial_unmap;
    1924                 :            : 
    1925                 :            :         /* create new user mem map entry */
    1926                 :          0 :         new_map = &user_mem_maps->maps[user_mem_maps->n_maps++];
    1927                 :          0 :         new_map->addr = vaddr;
    1928                 :          0 :         new_map->iova = iova;
    1929                 :          0 :         new_map->len = len;
    1930                 :            :         /* for IOMMU types supporting partial unmap, we don't need chunking */
    1931         [ #  # ]:          0 :         new_map->chunk = has_partial_unmap ? 0 : len;
    1932                 :            : 
    1933                 :          0 :         compact_user_maps(user_mem_maps);
    1934         [ #  # ]:          0 : out:
    1935                 :            :         rte_spinlock_recursive_unlock(&user_mem_maps->lock);
    1936                 :          0 :         return ret;
    1937                 :            : }
    1938                 :            : 
    1939                 :            : static int
    1940                 :          0 : container_dma_unmap(struct vfio_config *vfio_cfg, uint64_t vaddr, uint64_t iova,
    1941                 :            :                 uint64_t len)
    1942                 :            : {
    1943                 :            :         struct user_mem_map orig_maps[VFIO_MAX_USER_MEM_MAPS];
    1944                 :            :         struct user_mem_map new_maps[2]; /* can be at most 2 */
    1945                 :            :         struct user_mem_maps *user_mem_maps;
    1946                 :            :         int n_orig, n_new, newlen, ret = 0;
    1947                 :            :         bool has_partial_unmap;
    1948                 :            : 
    1949                 :          0 :         user_mem_maps = &vfio_cfg->mem_maps;
    1950                 :          0 :         rte_spinlock_recursive_lock(&user_mem_maps->lock);
    1951                 :            : 
    1952                 :            :         /*
    1953                 :            :          * Previously, we had adjacent mappings entirely contained within one
    1954                 :            :          * mapping entry. Since we now store original mapping length in some
    1955                 :            :          * cases, this is no longer the case, so unmapping can potentially go
    1956                 :            :          * over multiple segments and split them in any number of ways.
    1957                 :            :          *
    1958                 :            :          * To complicate things further, some IOMMU types support arbitrary
    1959                 :            :          * partial unmapping, while others will only support unmapping along the
    1960                 :            :          * chunk size, so there are a lot of cases we need to handle. To make
    1961                 :            :          * things easier code wise, instead of trying to adjust existing
    1962                 :            :          * mappings, let's just rebuild them using information we have.
    1963                 :            :          */
    1964                 :            : 
    1965                 :            :         /*
    1966                 :            :          * first thing to do is check if there exists a mapping that includes
    1967                 :            :          * the start and the end of our requested unmap. We need to collect all
    1968                 :            :          * maps that include our unmapped region.
    1969                 :            :          */
    1970                 :          0 :         n_orig = find_user_mem_maps(user_mem_maps, vaddr, iova, len,
    1971                 :            :                         orig_maps, RTE_DIM(orig_maps));
    1972                 :            :         /* did we find anything? */
    1973         [ #  # ]:          0 :         if (n_orig < 0) {
    1974                 :          0 :                 EAL_LOG(ERR, "Couldn't find previously mapped region");
    1975                 :          0 :                 rte_errno = EINVAL;
    1976                 :            :                 ret = -1;
    1977                 :          0 :                 goto out;
    1978                 :            :         }
    1979                 :            : 
    1980                 :            :         /* do we have partial unmap capability? */
    1981                 :          0 :         has_partial_unmap = vfio_cfg->vfio_iommu_type->partial_unmap;
    1982                 :            : 
    1983                 :            :         /*
    1984                 :            :          * if we don't support partial unmap, we must check if start and end of
    1985                 :            :          * current unmap region are chunk-aligned.
    1986                 :            :          */
    1987         [ #  # ]:          0 :         if (!has_partial_unmap) {
    1988                 :            :                 bool start_aligned, end_aligned;
    1989                 :            : 
    1990                 :          0 :                 start_aligned = addr_is_chunk_aligned(orig_maps, n_orig,
    1991                 :            :                                 vaddr, iova);
    1992                 :          0 :                 end_aligned = addr_is_chunk_aligned(orig_maps, n_orig,
    1993                 :            :                                 vaddr + len, iova + len);
    1994                 :            : 
    1995         [ #  # ]:          0 :                 if (!start_aligned || !end_aligned) {
    1996                 :          0 :                         EAL_LOG(DEBUG, "DMA partial unmap unsupported");
    1997                 :          0 :                         rte_errno = ENOTSUP;
    1998                 :            :                         ret = -1;
    1999                 :          0 :                         goto out;
    2000                 :            :                 }
    2001                 :            :         }
    2002                 :            : 
    2003                 :            :         /*
    2004                 :            :          * now we know we can potentially unmap the region, but we still have to
    2005                 :            :          * figure out if there is enough space in our list to store remaining
    2006                 :            :          * maps. for this, we will figure out how many segments we are going to
    2007                 :            :          * remove, and how many new segments we are going to create.
    2008                 :            :          */
    2009                 :          0 :         n_new = process_maps(orig_maps, n_orig, new_maps, vaddr, len);
    2010                 :            : 
    2011                 :            :         /* can we store the new maps in our list? */
    2012                 :          0 :         newlen = (user_mem_maps->n_maps - n_orig) + n_new;
    2013         [ #  # ]:          0 :         if (newlen >= VFIO_MAX_USER_MEM_MAPS) {
    2014                 :          0 :                 EAL_LOG(ERR, "Not enough space to store partial mapping");
    2015                 :          0 :                 rte_errno = ENOMEM;
    2016                 :            :                 ret = -1;
    2017                 :          0 :                 goto out;
    2018                 :            :         }
    2019                 :            : 
    2020                 :            :         /* unmap the entry */
    2021         [ #  # ]:          0 :         if (vfio_dma_mem_map(vfio_cfg, vaddr, iova, len, 0)) {
    2022                 :            :                 /* there may not be any devices plugged in, so unmapping will
    2023                 :            :                  * fail with ENODEV/ENOTSUP rte_errno values, but that doesn't
    2024                 :            :                  * stop us from removing the mapping, as the assumption is we
    2025                 :            :                  * won't be needing this memory any more and thus will want to
    2026                 :            :                  * prevent it from being remapped again on hotplug. so, only
    2027                 :            :                  * fail if we indeed failed to unmap (e.g. if the mapping was
    2028                 :            :                  * within our mapped range but had invalid alignment).
    2029                 :            :                  */
    2030         [ #  # ]:          0 :                 if (rte_errno != ENODEV && rte_errno != ENOTSUP) {
    2031                 :          0 :                         EAL_LOG(ERR, "Couldn't unmap region for DMA");
    2032                 :            :                         ret = -1;
    2033                 :          0 :                         goto out;
    2034                 :            :                 } else {
    2035                 :          0 :                         EAL_LOG(DEBUG, "DMA unmapping failed, but removing mappings anyway");
    2036                 :            :                 }
    2037                 :            :         }
    2038                 :            : 
    2039                 :            :         /* we have unmapped the region, so now update the maps */
    2040                 :          0 :         delete_maps(user_mem_maps, orig_maps, n_orig);
    2041                 :          0 :         copy_maps(user_mem_maps, new_maps, n_new);
    2042                 :          0 :         compact_user_maps(user_mem_maps);
    2043         [ #  # ]:          0 : out:
    2044                 :            :         rte_spinlock_recursive_unlock(&user_mem_maps->lock);
    2045                 :          0 :         return ret;
    2046                 :            : }
    2047                 :            : 
    2048                 :            : RTE_EXPORT_SYMBOL(rte_vfio_noiommu_is_enabled)
    2049                 :            : int
    2050                 :          0 : rte_vfio_noiommu_is_enabled(void)
    2051                 :            : {
    2052                 :            :         int fd;
    2053                 :            :         ssize_t cnt;
    2054                 :            :         char c;
    2055                 :            : 
    2056                 :            :         fd = open(VFIO_NOIOMMU_MODE, O_RDONLY);
    2057         [ #  # ]:          0 :         if (fd < 0) {
    2058         [ #  # ]:          0 :                 if (errno != ENOENT) {
    2059                 :          0 :                         EAL_LOG(ERR, "Cannot open VFIO noiommu file "
    2060                 :            :                                         "%i (%s)", errno, strerror(errno));
    2061                 :          0 :                         return -1;
    2062                 :            :                 }
    2063                 :            :                 /*
    2064                 :            :                  * else the file does not exists
    2065                 :            :                  * i.e. noiommu is not enabled
    2066                 :            :                  */
    2067                 :            :                 return 0;
    2068                 :            :         }
    2069                 :            : 
    2070                 :            :         cnt = read(fd, &c, 1);
    2071                 :          0 :         close(fd);
    2072         [ #  # ]:          0 :         if (cnt != 1) {
    2073                 :          0 :                 EAL_LOG(ERR, "Unable to read from VFIO noiommu file "
    2074                 :            :                                 "%i (%s)", errno, strerror(errno));
    2075                 :          0 :                 return -1;
    2076                 :            :         }
    2077                 :            : 
    2078                 :          0 :         return c == 'Y';
    2079                 :            : }
    2080                 :            : 
    2081                 :            : RTE_EXPORT_SYMBOL(rte_vfio_container_create)
    2082                 :            : int
    2083                 :          0 : rte_vfio_container_create(void)
    2084                 :            : {
    2085                 :            :         int i;
    2086                 :            : 
    2087                 :            :         /* Find an empty slot to store new vfio config */
    2088         [ #  # ]:          0 :         for (i = 1; i < VFIO_MAX_CONTAINERS; i++) {
    2089         [ #  # ]:          0 :                 if (vfio_cfgs[i].vfio_container_fd == -1)
    2090                 :            :                         break;
    2091                 :            :         }
    2092                 :            : 
    2093         [ #  # ]:          0 :         if (i == VFIO_MAX_CONTAINERS) {
    2094                 :          0 :                 EAL_LOG(ERR, "Exceed max VFIO container limit");
    2095                 :          0 :                 return -1;
    2096                 :            :         }
    2097                 :            : 
    2098                 :          0 :         vfio_cfgs[i].vfio_container_fd = rte_vfio_get_container_fd();
    2099         [ #  # ]:          0 :         if (vfio_cfgs[i].vfio_container_fd < 0) {
    2100                 :          0 :                 EAL_LOG(NOTICE, "Fail to create a new VFIO container");
    2101                 :          0 :                 return -1;
    2102                 :            :         }
    2103                 :            : 
    2104                 :            :         return vfio_cfgs[i].vfio_container_fd;
    2105                 :            : }
    2106                 :            : 
    2107                 :            : RTE_EXPORT_SYMBOL(rte_vfio_container_destroy)
    2108                 :            : int
    2109         [ #  # ]:          0 : rte_vfio_container_destroy(int container_fd)
    2110                 :            : {
    2111                 :            :         struct vfio_config *vfio_cfg;
    2112                 :            :         int i;
    2113                 :            : 
    2114                 :            :         vfio_cfg = get_vfio_cfg_by_container_fd(container_fd);
    2115         [ #  # ]:          0 :         if (vfio_cfg == NULL) {
    2116                 :          0 :                 EAL_LOG(ERR, "Invalid VFIO container fd");
    2117                 :          0 :                 return -1;
    2118                 :            :         }
    2119                 :            : 
    2120         [ #  # ]:          0 :         for (i = 0; i < VFIO_MAX_GROUPS; i++)
    2121         [ #  # ]:          0 :                 if (vfio_cfg->vfio_groups[i].group_num != -1)
    2122                 :          0 :                         rte_vfio_container_group_unbind(container_fd,
    2123                 :            :                                 vfio_cfg->vfio_groups[i].group_num);
    2124                 :            : 
    2125                 :          0 :         close(container_fd);
    2126                 :          0 :         vfio_cfg->vfio_container_fd = -1;
    2127                 :          0 :         vfio_cfg->vfio_active_groups = 0;
    2128                 :          0 :         vfio_cfg->vfio_iommu_type = NULL;
    2129                 :            : 
    2130                 :          0 :         return 0;
    2131                 :            : }
    2132                 :            : 
    2133                 :            : RTE_EXPORT_SYMBOL(rte_vfio_container_group_bind)
    2134                 :            : int
    2135         [ #  # ]:          0 : rte_vfio_container_group_bind(int container_fd, int iommu_group_num)
    2136                 :            : {
    2137                 :            :         struct vfio_config *vfio_cfg;
    2138                 :            : 
    2139                 :            :         vfio_cfg = get_vfio_cfg_by_container_fd(container_fd);
    2140         [ #  # ]:          0 :         if (vfio_cfg == NULL) {
    2141                 :          0 :                 EAL_LOG(ERR, "Invalid VFIO container fd");
    2142                 :          0 :                 return -1;
    2143                 :            :         }
    2144                 :            : 
    2145                 :          0 :         return vfio_get_group_fd(vfio_cfg, iommu_group_num);
    2146                 :            : }
    2147                 :            : 
    2148                 :            : RTE_EXPORT_SYMBOL(rte_vfio_container_group_unbind)
    2149                 :            : int
    2150         [ #  # ]:          0 : rte_vfio_container_group_unbind(int container_fd, int iommu_group_num)
    2151                 :            : {
    2152                 :            :         struct vfio_config *vfio_cfg;
    2153                 :            :         struct vfio_group *cur_grp = NULL;
    2154                 :            :         int i;
    2155                 :            : 
    2156                 :            :         vfio_cfg = get_vfio_cfg_by_container_fd(container_fd);
    2157         [ #  # ]:          0 :         if (vfio_cfg == NULL) {
    2158                 :          0 :                 EAL_LOG(ERR, "Invalid VFIO container fd");
    2159                 :          0 :                 return -1;
    2160                 :            :         }
    2161                 :            : 
    2162         [ #  # ]:          0 :         for (i = 0; i < VFIO_MAX_GROUPS; i++) {
    2163         [ #  # ]:          0 :                 if (vfio_cfg->vfio_groups[i].group_num == iommu_group_num) {
    2164                 :          0 :                         cur_grp = &vfio_cfg->vfio_groups[i];
    2165                 :          0 :                         break;
    2166                 :            :                 }
    2167                 :            :         }
    2168                 :            : 
    2169                 :            :         /* This should not happen */
    2170         [ #  # ]:          0 :         if (i == VFIO_MAX_GROUPS || cur_grp == NULL) {
    2171                 :          0 :                 EAL_LOG(ERR, "Specified VFIO group number not found");
    2172                 :          0 :                 return -1;
    2173                 :            :         }
    2174                 :            : 
    2175   [ #  #  #  # ]:          0 :         if (cur_grp->fd >= 0 && close(cur_grp->fd) < 0) {
    2176                 :          0 :                 EAL_LOG(ERR,
    2177                 :            :                         "Error when closing vfio_group_fd for iommu_group_num "
    2178                 :            :                         "%d", iommu_group_num);
    2179                 :          0 :                 return -1;
    2180                 :            :         }
    2181                 :          0 :         cur_grp->group_num = -1;
    2182                 :          0 :         cur_grp->fd = -1;
    2183                 :          0 :         cur_grp->devices = 0;
    2184                 :          0 :         vfio_cfg->vfio_active_groups--;
    2185                 :            : 
    2186                 :          0 :         return 0;
    2187                 :            : }
    2188                 :            : 
    2189                 :            : RTE_EXPORT_SYMBOL(rte_vfio_container_dma_map)
    2190                 :            : int
    2191                 :          0 : rte_vfio_container_dma_map(int container_fd, uint64_t vaddr, uint64_t iova,
    2192                 :            :                 uint64_t len)
    2193                 :            : {
    2194                 :            :         struct vfio_config *vfio_cfg;
    2195                 :            : 
    2196         [ #  # ]:          0 :         if (len == 0) {
    2197                 :          0 :                 rte_errno = EINVAL;
    2198                 :          0 :                 return -1;
    2199                 :            :         }
    2200                 :            : 
    2201                 :            :         vfio_cfg = get_vfio_cfg_by_container_fd(container_fd);
    2202         [ #  # ]:          0 :         if (vfio_cfg == NULL) {
    2203                 :          0 :                 EAL_LOG(ERR, "Invalid VFIO container fd");
    2204                 :          0 :                 return -1;
    2205                 :            :         }
    2206                 :            : 
    2207                 :          0 :         return container_dma_map(vfio_cfg, vaddr, iova, len);
    2208                 :            : }
    2209                 :            : 
    2210                 :            : RTE_EXPORT_SYMBOL(rte_vfio_container_dma_unmap)
    2211                 :            : int
    2212                 :          0 : rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova,
    2213                 :            :                 uint64_t len)
    2214                 :            : {
    2215                 :            :         struct vfio_config *vfio_cfg;
    2216                 :            : 
    2217         [ #  # ]:          0 :         if (len == 0) {
    2218                 :          0 :                 rte_errno = EINVAL;
    2219                 :          0 :                 return -1;
    2220                 :            :         }
    2221                 :            : 
    2222                 :            :         vfio_cfg = get_vfio_cfg_by_container_fd(container_fd);
    2223         [ #  # ]:          0 :         if (vfio_cfg == NULL) {
    2224                 :          0 :                 EAL_LOG(ERR, "Invalid VFIO container fd");
    2225                 :          0 :                 return -1;
    2226                 :            :         }
    2227                 :            : 
    2228                 :          0 :         return container_dma_unmap(vfio_cfg, vaddr, iova, len);
    2229                 :            : }

Generated by: LCOV version 1.14