Skip to contentSkip to conversation

Support VFIO cdev API in DPDK

PATCH Superseded Anatoly Burakov 3 participants 386 messages Nov 18, 2025 – Oct 10 1 message not in the archive Page 5 of 7

Subsystems (5)
lore
Share & tools
lore
#262 lore raw

PATCH v17 3/26 vfio: make all functions internal

In reply to Anatoly Burakov

The VFIO API is an externally exported API because the original intent was to offer DMA mapping facilities to applications. However, practical usage of this API seems to be centered around drivers, so keeping this API exported to applications only creates needless API/ABI stability surface that has no added value.

Make the entire VFIO API internal-only and visible only to drivers.

---
 doc/api/doxy-api-index.md              |  3 +-
 doc/guides/rel_notes/deprecation.rst   |  6 ----
 doc/guides/rel_notes/release_26_11.rst |  8 +++++
 lib/eal/freebsd/eal.c                  | 30 ++++++++--------
 lib/eal/include/meson.build            |  2 +-
 lib/eal/include/rte_vfio.h             | 47 ++++++++++++++++++++++----
 lib/eal/linux/eal_vfio.c               | 32 +++++++++---------
 lib/eal/windows/eal.c                  |  4 +--
 8 files changed, 84 insertions(+), 48 deletions(-)
doc/api/doxy-api-index.md +1 -2
index 9296042119..4216b1b9e4 100644
@@ -37,8 +37,7 @@ The public API headers are grouped by topics:
   [latency](@ref rte_latencystats.h),
   [devargs](@ref rte_devargs.h),
   [PCI](@ref rte_pci.h),
-  [vdev](@ref rte_bus_vdev.h),
-  [vfio](@ref rte_vfio.h)
+  [vdev](@ref rte_bus_vdev.h)
 
 - **device specific**:
   [softnic](@ref rte_eth_softnic.h),
doc/guides/rel_notes/deprecation.rst +0 -6
index 6ad7698c6b..8a82c815e3 100644
@@ -29,12 +29,6 @@ Deprecation Notices
   Use the ``-S <service-corelist>`` parameter instead
   to specify the cores to be used for background services in DPDK.
 
-* eal: The entire VFIO API (``rte_vfio_*``) will be made internal only,
-  and will only be available to EAL and drivers.
-  Group-based API (``rte_vfio_*_group_*``) will be removed
-  and replaced with unified container device assignment API.
-  This change will be made in 26.11 release.
-
 * vdpa: The vDPA driver API will no longer offer ``get_vfio_group_fd``
   as part of its internal API. All drivers will be adjusted
   to use the new unified VFIO container device assignment API.
doc/guides/rel_notes/release_26_11.rst +8 -0
index c8cc86295d..b5793b5c94 100644
@@ -93,6 +93,10 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =======================================================
 
+* vfio: The entire VFIO API (``rte_vfio_*``) was made internal.
+  These functions are now available only to EAL and drivers,
+  and are no longer part of the public API.
+
 
 ABI Changes
 -----------
@@ -109,6 +113,10 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =======================================================
 
+* vfio: The entire VFIO API (``rte_vfio_*``) was made internal.
+  These functions are now available only to EAL and drivers,
+  and are no longer part of the public ABI.
+
 
 Known Issues
 ------------
lib/eal/freebsd/eal.c +15 -15
index 8b1ba5b99b..0fe54a9dd7 100644
@@ -819,7 +819,7 @@ rte_eal_vfio_get_vf_token(__rte_unused rte_uuid_t vf_token)
 {
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_setup_device)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_setup_device)
 int rte_vfio_setup_device(__rte_unused const char *sysfs_base,
 		      __rte_unused const char *dev_addr,
 		      __rte_unused int *vfio_dev_fd,
@@ -829,7 +829,7 @@ int rte_vfio_setup_device(__rte_unused const char *sysfs_base,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_release_device)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_release_device)
 int rte_vfio_release_device(__rte_unused const char *sysfs_base,
 			__rte_unused const char *dev_addr,
 			__rte_unused int fd)
@@ -838,33 +838,33 @@ int rte_vfio_release_device(__rte_unused const char *sysfs_base,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_enable)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_enable)
 int rte_vfio_enable(__rte_unused const char *modname)
 {
 	rte_errno = ENOTSUP;
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_is_enabled)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_is_enabled)
 int rte_vfio_is_enabled(__rte_unused const char *modname)
 {
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_noiommu_is_enabled)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_noiommu_is_enabled)
 int rte_vfio_noiommu_is_enabled(void)
 {
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_clear_group)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_clear_group)
 int rte_vfio_clear_group(__rte_unused int vfio_group_fd)
 {
 	rte_errno = ENOTSUP;
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_num)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_group_num)
 int
 rte_vfio_get_group_num(__rte_unused const char *sysfs_base,
 		       __rte_unused const char *dev_addr,
@@ -874,7 +874,7 @@ rte_vfio_get_group_num(__rte_unused const char *sysfs_base,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_container_fd)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_container_fd)
 int
 rte_vfio_get_container_fd(void)
 {
@@ -882,7 +882,7 @@ rte_vfio_get_container_fd(void)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_fd)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_group_fd)
 int
 rte_vfio_get_group_fd(__rte_unused int iommu_group_num)
 {
@@ -890,7 +890,7 @@ rte_vfio_get_group_fd(__rte_unused int iommu_group_num)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_create)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_create)
 int
 rte_vfio_container_create(void)
 {
@@ -898,7 +898,7 @@ rte_vfio_container_create(void)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_destroy)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_destroy)
 int
 rte_vfio_container_destroy(__rte_unused int container_fd)
 {
@@ -906,7 +906,7 @@ rte_vfio_container_destroy(__rte_unused int container_fd)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_bind)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_group_bind)
 int
 rte_vfio_container_group_bind(__rte_unused int container_fd,
 		__rte_unused int iommu_group_num)
@@ -915,7 +915,7 @@ rte_vfio_container_group_bind(__rte_unused int container_fd,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_unbind)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_group_unbind)
 int
 rte_vfio_container_group_unbind(__rte_unused int container_fd,
 		__rte_unused int iommu_group_num)
@@ -924,7 +924,7 @@ rte_vfio_container_group_unbind(__rte_unused int container_fd,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_map)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_map)
 int
 rte_vfio_container_dma_map(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
@@ -935,7 +935,7 @@ rte_vfio_container_dma_map(__rte_unused int container_fd,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_unmap)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_unmap)
 int
 rte_vfio_container_dma_unmap(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
lib/eal/include/meson.build +1 -1
index aef5824e5f..9282143918 100644
@@ -55,12 +55,12 @@ headers += files(
         'rte_trace_point_register.h',
         'rte_uuid.h',
         'rte_version.h',
-        'rte_vfio.h',
 )
 
 driver_sdk_headers = files(
         'bus_driver.h',
         'dev_driver.h',
+        'rte_vfio.h',
 )
 
 # special case install the generic headers, since they go in a subdir
lib/eal/include/rte_vfio.h +41 -6

214 lines not on this page · raw message

lib/eal/linux/eal_vfio.c +16 -16
index f1050ffa60..33fa04feaf 100644
@@ -532,7 +532,7 @@ get_vfio_cfg_by_container_fd(int container_fd)
 	return NULL;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_fd)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_group_fd)
 int
 rte_vfio_get_group_fd(int iommu_group_num)
 {
@@ -731,7 +731,7 @@ vfio_sync_default_container(void)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_clear_group)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_clear_group)
 int
 rte_vfio_clear_group(int vfio_group_fd)
 {
@@ -755,7 +755,7 @@ rte_vfio_clear_group(int vfio_group_fd)
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_setup_device)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_setup_device)
 int
 rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 		int *vfio_dev_fd, struct vfio_device_info *device_info)
@@ -1009,7 +1009,7 @@ rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_release_device)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_release_device)
 int
 rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
 		    int vfio_dev_fd)
@@ -1098,7 +1098,7 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
 	return ret;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_enable)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_enable)
 int
 rte_vfio_enable(const char *modname)
 {
@@ -1175,7 +1175,7 @@ rte_vfio_enable(const char *modname)
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_is_enabled)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_is_enabled)
 int
 rte_vfio_is_enabled(const char *modname)
 {
@@ -1215,7 +1215,7 @@ vfio_set_iommu_type(int vfio_container_fd)
 	return NULL;
 }
 
-RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_vfio_get_device_info, 24.03)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_device_info)
 int
 rte_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
 		int *vfio_dev_fd, struct vfio_device_info *device_info)
@@ -1349,7 +1349,7 @@ vfio_open_container_fd(bool mp_request)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_container_fd)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_container_fd)
 int
 rte_vfio_get_container_fd(void)
 {
@@ -1363,7 +1363,7 @@ rte_vfio_get_container_fd(void)
 	return default_vfio_cfg->vfio_container_fd;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_num)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_group_num)
 int
 rte_vfio_get_group_num(const char *sysfs_base,
 		const char *dev_addr, int *iommu_group_num)
@@ -2034,7 +2034,7 @@ container_dma_unmap(struct vfio_config *vfio_cfg, uint64_t vaddr, uint64_t iova,
 	return ret;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_noiommu_is_enabled)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_noiommu_is_enabled)
 int
 rte_vfio_noiommu_is_enabled(void)
 {
@@ -2067,7 +2067,7 @@ rte_vfio_noiommu_is_enabled(void)
 	return c == 'Y';
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_create)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_create)
 int
 rte_vfio_container_create(void)
 {
@@ -2094,7 +2094,7 @@ rte_vfio_container_create(void)
 	return vfio_cfgs[i].vfio_container_fd;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_destroy)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_destroy)
 int
 rte_vfio_container_destroy(int container_fd)
 {
@@ -2120,7 +2120,7 @@ rte_vfio_container_destroy(int container_fd)
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_bind)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_group_bind)
 int
 rte_vfio_container_group_bind(int container_fd, int iommu_group_num)
 {
@@ -2135,7 +2135,7 @@ rte_vfio_container_group_bind(int container_fd, int iommu_group_num)
 	return vfio_get_group_fd(vfio_cfg, iommu_group_num);
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_unbind)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_group_unbind)
 int
 rte_vfio_container_group_unbind(int container_fd, int iommu_group_num)
 {
@@ -2176,7 +2176,7 @@ rte_vfio_container_group_unbind(int container_fd, int iommu_group_num)
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_map)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_map)
 int
 rte_vfio_container_dma_map(int container_fd, uint64_t vaddr, uint64_t iova,
 		uint64_t len)
@@ -2197,7 +2197,7 @@ rte_vfio_container_dma_map(int container_fd, uint64_t vaddr, uint64_t iova,
 	return container_dma_map(vfio_cfg, vaddr, iova, len);
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_unmap)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_unmap)
 int
 rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova,
 		uint64_t len)
lib/eal/windows/eal.c +2 -2
index 6dacae7235..de7a89a829 100644
@@ -453,7 +453,7 @@ eal_asprintf(char **buffer, const char *format, ...)
 	return ret;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_map)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_map)
 int
 rte_vfio_container_dma_map(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
@@ -464,7 +464,7 @@ rte_vfio_container_dma_map(__rte_unused int container_fd,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_unmap)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_unmap)
 int
 rte_vfio_container_dma_unmap(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
Signature · 1 line
2.52.0
#263 lore raw

PATCH v17 4/26 bus/fslmc: decouple from EAL VFIO

In reply to Anatoly Burakov

FSLMC bus has its own VFIO implementation which is completely separate from one in EAL or rte_vfio. Yet, it references a couple of macros and uses a struct definition. Fully decoupling them is not a huge lift, so do that.

---
 drivers/bus/fslmc/fslmc_vfio.c | 50 +++++++++++++++++++++-------------
 drivers/bus/fslmc/meson.build  |  1 -
 2 files changed, 31 insertions(+), 20 deletions(-)
drivers/bus/fslmc/fslmc_vfio.c +31 -19
index 412b70e5ae..8d39895bac 100644
@@ -35,7 +35,6 @@
 #include <dev_driver.h>
 #include <rte_eal_memconfig.h>
 #include <rte_vfio.h>
-#include <eal_vfio.h>
 
 #include "private.h"
 #include "fslmc_vfio.h"
@@ -73,8 +72,21 @@ struct fslmc_dmaseg_list fslmc_iosegs =
 static uint64_t fslmc_mem_va2iova = RTE_BAD_IOVA;
 static int fslmc_mem_map_num;
 
+#define FSLMC_VFIO_SOCKET_OK 0x0
+#define FSLMC_VFIO_SOCKET_NO_FD 0x1
+#define FSLMC_VFIO_SOCKET_ERR 0xFF
+
+struct fslmc_vfio_mp_param {
+	int req;
+	int result;
+	union {
+		int group_num;
+		int iommu_type_id;
+	};
+};
+
 struct fslmc_mem_param {
-	struct vfio_mp_param mp_param;
+	struct fslmc_vfio_mp_param mp_param;
 	struct fslmc_dmaseg_list memsegs;
 	struct fslmc_dmaseg_list iosegs;
 	uint64_t mem_va2iova;
@@ -386,7 +398,7 @@ fslmc_vfio_open_group_fd(const char *group_name)
 	struct rte_mp_msg mp_req, *mp_rep;
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
-	struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param;
+	struct fslmc_vfio_mp_param *p = (struct fslmc_vfio_mp_param *)mp_req.param;
 	int iommu_group_num, ret;
 
 	vfio_group_fd = fslmc_vfio_group_fd_by_name(group_name);
@@ -417,10 +429,10 @@ fslmc_vfio_open_group_fd(const char *group_name)
 	if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
 	    mp_reply.nb_received == 1) {
 		mp_rep = &mp_reply.msgs[0];
-		p = (struct vfio_mp_param *)mp_rep->param;
-		if (p->result == SOCKET_OK && mp_rep->num_fds == 1)
+		p = (struct fslmc_vfio_mp_param *)mp_rep->param;
+		if (p->result == FSLMC_VFIO_SOCKET_OK && mp_rep->num_fds == 1)
 			vfio_group_fd = mp_rep->fds[0];
-		else if (p->result == SOCKET_NO_FD)
+		else if (p->result == FSLMC_VFIO_SOCKET_NO_FD)
 			DPAA2_BUS_ERR("Bad VFIO group fd");
 	}
 
@@ -490,7 +502,7 @@ fslmc_vfio_open_container_fd(void)
 	struct rte_mp_msg mp_req, *mp_rep;
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
-	struct vfio_mp_param *p = (void *)mp_req.param;
+	struct fslmc_vfio_mp_param *p = (void *)mp_req.param;
 
 	if (fslmc_vfio_container_fd() > 0)
 		return fslmc_vfio_container_fd();
@@ -551,7 +563,7 @@ fslmc_vfio_open_container_fd(void)
 
 	mp_rep = &mp_reply.msgs[0];
 	p = (void *)mp_rep->param;
-	if (p->result == SOCKET_OK && mp_rep->num_fds == 1) {
+	if (p->result == FSLMC_VFIO_SOCKET_OK && mp_rep->num_fds == 1) {
 		vfio_container_fd = mp_rep->fds[0];
 		free(mp_reply.msgs);
 	}
@@ -594,8 +606,8 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 	int fd = -1;
 	int ret;
 	struct rte_mp_msg reply;
-	struct vfio_mp_param *r = (void *)reply.param;
-	const struct vfio_mp_param *m = (const void *)msg->param;
+	struct fslmc_vfio_mp_param *r = (void *)reply.param;
+	const struct fslmc_vfio_mp_param *m = (const void *)msg->param;
 	struct fslmc_mem_param *map;
 
 	if (msg->len_param != sizeof(*m)) {
@@ -612,13 +624,13 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 		r->group_num = m->group_num;
 		fd = fslmc_vfio_group_fd_by_id(m->group_num);
 		if (fd < 0) {
-			r->result = SOCKET_ERR;
+			r->result = FSLMC_VFIO_SOCKET_ERR;
 		} else if (!fd) {
 			/* if group exists but isn't bound to VFIO driver */
-			r->result = SOCKET_NO_FD;
+			r->result = FSLMC_VFIO_SOCKET_NO_FD;
 		} else {
 			/* if group exists and is bound to VFIO driver */
-			r->result = SOCKET_OK;
+			r->result = FSLMC_VFIO_SOCKET_OK;
 			reply.num_fds = 1;
 			reply.fds[0] = fd;
 		}
@@ -628,9 +640,9 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 		r->req = FSLMC_VFIO_SOCKET_REQ_CONTAINER;
 		fd = fslmc_vfio_container_fd();
 		if (fd <= 0) {
-			r->result = SOCKET_ERR;
+			r->result = FSLMC_VFIO_SOCKET_ERR;
 		} else {
-			r->result = SOCKET_OK;
+			r->result = FSLMC_VFIO_SOCKET_OK;
 			reply.num_fds = 1;
 			reply.fds[0] = fd;
 		}
@@ -640,7 +652,7 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 		map = (void *)reply.param;
 		r = &map->mp_param;
 		r->req = FSLMC_VFIO_SOCKET_REQ_MEM;
-		r->result = SOCKET_OK;
+		r->result = FSLMC_VFIO_SOCKET_OK;
 		map->memsegs = fslmc_memsegs;
 		map->iosegs = fslmc_iosegs;
 		map->mem_va2iova = fslmc_mem_va2iova;
@@ -666,19 +678,19 @@ fslmc_vfio_mp_sync_mem_req(void)
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
 	int ret = 0;
-	struct vfio_mp_param *mp_param;
+	struct fslmc_vfio_mp_param *mp_param;
 	struct fslmc_mem_param *mem_rsp;
 
 	mp_param = (void *)mp_req.param;
 	memset(&mp_req, 0, sizeof(struct rte_mp_msg));
 	mp_param->req = FSLMC_VFIO_SOCKET_REQ_MEM;
 	rte_strscpy(mp_req.name, FSLMC_VFIO_MP, sizeof(mp_req.name));
-	mp_req.len_param = sizeof(struct vfio_mp_param);
+	mp_req.len_param = sizeof(struct fslmc_vfio_mp_param);
 	if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
 		mp_reply.nb_received == 1) {
 		mp_rep = &mp_reply.msgs[0];
 		mem_rsp = (struct fslmc_mem_param *)mp_rep->param;
-		if (mem_rsp->mp_param.result == SOCKET_OK) {
+		if (mem_rsp->mp_param.result == FSLMC_VFIO_SOCKET_OK) {
 			fslmc_memsegs = mem_rsp->memsegs;
 			fslmc_mem_va2iova = mem_rsp->mem_va2iova;
 			fslmc_mem_map_num = mem_rsp->mem_map_num;
drivers/bus/fslmc/meson.build +0 -1
index 50d9e91a37..55f9d2e808 100644
@@ -30,4 +30,3 @@ sources = files(
 )
 
 includes += include_directories('mc', 'qbman/include', 'portal')
-includes += include_directories('../../../lib/eal/linux')
Signature · 1 line
2.52.0
#264 lore raw

PATCH v17 5/26 vfio: decouple EAL from VFIO internals

In reply to Anatoly Burakov

Currently, the multiprocess cleanup for VFIO is called via an internal-only API, and this is the only thing eal_vfio.h is used for in EAL. In order to make eal_vfio.h truly VFIO-internal, export a cleanup function from rte_vfio API instead, and call that. This allows us to remove all EAL references to eal_vfio.h in non-VFIO related files.

---
 lib/eal/freebsd/eal.c      | 6 ++++++
 lib/eal/include/rte_vfio.h | 9 +++++++++
 lib/eal/linux/eal.c        | 3 +--
 lib/eal/linux/eal_vfio.c   | 7 +++++++
 lib/eal/windows/eal.c      | 6 ++++++
 5 files changed, 29 insertions(+), 2 deletions(-)
lib/eal/freebsd/eal.c +6 -0
index 0fe54a9dd7..991ca45064 100644
@@ -845,6 +845,12 @@ int rte_vfio_enable(__rte_unused const char *modname)
 	return -1;
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
+void
+rte_vfio_cleanup(void)
+{
+}
+
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_is_enabled)
 int rte_vfio_is_enabled(__rte_unused const char *modname)
 {
lib/eal/include/rte_vfio.h +9 -0
index 0ddeb08f94..e76181c83c 100644
@@ -109,6 +109,15 @@ int rte_vfio_release_device(const char *sysfs_base, const char *dev_addr, int fd
 __rte_internal
 int rte_vfio_enable(const char *modname);
 
+/**
+ * @internal
+ * Cleanup VFIO resources.
+ *
+ * This function is only relevant to Linux.
+ */
+__rte_internal
+void rte_vfio_cleanup(void);
+
 /**
  * @internal
  * Check whether a VFIO-related kmod is enabled.
lib/eal/linux/eal.c +1 -2
index fc2e9b8c0e..5577bab24a 100644
@@ -54,7 +54,6 @@
 #include "eal_memcfg.h"
 #include "eal_trace.h"
 #include "eal_options.h"
-#include "eal_vfio.h"
 #include "hotplug_mp.h"
 #include "log_internal.h"
 
@@ -986,7 +985,7 @@ rte_eal_cleanup(void)
 
 	rte_service_finalize();
 	eal_bus_cleanup();
-	vfio_mp_sync_cleanup();
+	rte_vfio_cleanup();
 	rte_mp_channel_cleanup();
 	rte_eal_alarm_cleanup();
 	rte_trace_save();
lib/eal/linux/eal_vfio.c +7 -0
index 33fa04feaf..6c77076bc3 100644
@@ -2217,3 +2217,10 @@ rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova,
 
 	return container_dma_unmap(vfio_cfg, vaddr, iova, len);
 }
+
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
+void
+rte_vfio_cleanup(void)
+{
+	vfio_mp_sync_cleanup();
+}
lib/eal/windows/eal.c +6 -0
index de7a89a829..b8771d4d85 100644
@@ -152,6 +152,12 @@ rte_eal_cleanup(void)
 	return 0;
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
+void
+rte_vfio_cleanup(void)
+{
+}
+
 /* Launch threads, called at application init(). */
 RTE_EXPORT_SYMBOL(rte_eal_init)
 int
Signature · 1 line
2.52.0
#265 lore raw

PATCH v17 6/26 vfio: do proper teardown on VFIO cleanup

In reply to Anatoly Burakov

Currently, VFIO cleanup only unregisters multiprocess callback, but does not destroy containers, groups, and user mem maps. Do all of that on VFIO cleanup. In order to distinguish between config that is not initialized vs. config that has been initialized but happens to have fd == 0, move the global VFIO enabled flag out of the config, and add a separate per-config "enabled" flag that can be checked to avoid attempting to clean up configs that were never initialized in the first place.

While we're at it, also harden the API against repeated initialization and attempts at using the API without having VFIO initialized.

---
 lib/eal/freebsd/eal.c    |   3 +-
 lib/eal/linux/eal_vfio.c | 151 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 147 insertions(+), 7 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index 991ca45064..aa6d4c2e16 100644
@@ -846,8 +846,7 @@ int rte_vfio_enable(__rte_unused const char *modname)
 }
 
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
-void
-rte_vfio_cleanup(void)
+void rte_vfio_cleanup(void)
 {
 }
 
lib/eal/linux/eal_vfio.c +146 -5

292 lines not on this page · raw message

Signature · 1 line
2.52.0
#266 lore raw

Re: [PATCH v17 06/26] vfio: do proper teardown on VFIO cleanup

Quoted 11 lines · Anatoly Burakov

Currently, VFIO cleanup only unregisters multiprocess callback, but does not destroy containers, groups, and user mem maps. Do all of that on VFIO cleanup. In order to distinguish between config that is not initialized vs. config that has been initialized but happens to have fd == 0, move the global VFIO enabled flag out of the config, and add a separate per-config "enabled" flag that can be checked to avoid attempting to clean up configs that were never initialized in the first place.

While we're at it, also harden the API against repeated initialization and attempts at using the API without having VFIO initialized.

- At this point of the series, I don't see the need for this change. The default config vfio_enabled should be set to 0 and could serve the same purpose?

- Should we reset vfio_enabled in rte_vfio_cleanup()?

Quoted 12 lines
---
 lib/eal/freebsd/eal.c    |   3 +-
 lib/eal/linux/eal_vfio.c | 151 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 147 insertions(+), 7 deletions(-)
lib/eal/freebsd/eal.c +0 -0
index 991ca45064..aa6d4c2e16 100644

lib/eal/freebsd/eal.c int rte_vfio_enable(__rte_unused const char *modname) · line 852

Quoted 9 lines
lib/eal/freebsd/eal.c +1 -2
@@ -846,8 +846,7 @@ int rte_vfio_enable(__rte_unused const char *modname)
 }
 
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
-void
-rte_vfio_cleanup(void)
+void rte_vfio_cleanup(void)
 {
 }
 

Nit: unrelated.

Quoted 4 lines
lib/eal/linux/eal_vfio.c +0 -0
index 6c77076bc3..d4173f7a01 100644

[snip]

Quoted 8 lines
lib/eal/linux/eal_vfio.c +4 -0
@@ -2218,9 +2296,72 @@ rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova,
        return container_dma_unmap(vfio_cfg, vaddr, iova, len);
 }
 
+static void
+vfio_cleanup_config(struct vfio_config *vfio_cfg)
+{
+       unsigned int i;

lib/eal/linux/eal_vfio.c rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova, · line 2312

Quoted 10 lines
lib/eal/linux/eal_vfio.c +10 -0
+
+       for (i = 0; i < RTE_DIM(vfio_cfg->vfio_groups); i++) {
+               struct vfio_group *group = &vfio_cfg->vfio_groups[i];
+
+               if (group->group_num == -1)
+                       continue;
+               if (group->devices != 0) {
+                       EAL_LOG(ERR, "Cannot cleanup VFIO group %d with %d devices",
+                               group->group_num, group->devices);
+                       return;

Why stop?
Should we continue for other groups?

Quoted 33 lines
lib/eal/linux/eal_vfio.c +33 -0
+               }
+               if (group->fd >= 0 && close(group->fd) < 0) {
+                       EAL_LOG(ERR, "Cannot close VFIO group %d: %s",
+                               group->group_num, strerror(errno));
+                       return;
+               }
+
+               group->group_num = -1;
+               group->fd = -1;
+               group->devices = 0;
+               vfio_cfg->vfio_active_groups--;
+       }
+
+       /* if there are still active groups, we cannot cleanup the container */
+       if (vfio_cfg->vfio_active_groups != 0) {
+               EAL_LOG(ERR, "Cannot cleanup VFIO container with %d active groups",
+                       vfio_cfg->vfio_active_groups);
+               return;
+       }
+
+       if (vfio_cfg->vfio_container_fd >= 0 &&
+                       close(vfio_cfg->vfio_container_fd) < 0) {
+               EAL_LOG(ERR, "Cannot close VFIO container: %s", strerror(errno));
+               return;
+       }
+
+       vfio_cfg->vfio_container_fd = -1;
+       vfio_cfg->enabled = false;
+       vfio_cfg->vfio_iommu_type = NULL;
+
+       vfio_cfg->mem_maps.n_maps = 0;
+       memset(vfio_cfg->mem_maps.maps, 0, sizeof(vfio_cfg->mem_maps.maps));
+}
Signature · 1 line
David Marchand
#267 lore raw

Re: [PATCH v17 06/26] vfio: do proper teardown on VFIO cleanup

Quoted 11 lines · David Marchand
Quoted 9 lines · Anatoly Burakov

Currently, VFIO cleanup only unregisters multiprocess callback, but does not destroy containers, groups, and user mem maps. Do all of that on VFIO cleanup. In order to distinguish between config that is not initialized vs. config that has been initialized but happens to have fd == 0, move the global VFIO enabled flag out of the config, and add a separate per-config "enabled" flag that can be checked to avoid attempting to clean up configs that were never initialized in the first place.

Quoted 6 lines
Quoted 2 lines

While we're at it, also harden the API against repeated initialization and attempts at using the API without having VFIO initialized.

- At this point of the series, I don't see the need for this change. The default config vfio_enabled should be set to 0 and could serve the same purpose?

It is not necessary to do it in this specific patch, I just thought to add it because having a proper rte_vfio_cleanup() implies some more rigor than just releasing the multiprocess state. We can move it till later, although it would require rebase work.

Quoted 2 lines

- Should we reset vfio_enabled in rte_vfio_cleanup()?

Yes, we should.

Quoted 14 lines
Quoted 14 lines
lib/eal/linux/eal_vfio.c +9 -0
@@ -2218,9 +2296,72 @@ rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova,
         return container_dma_unmap(vfio_cfg, vaddr, iova, len);
  }
 
+static void
+vfio_cleanup_config(struct vfio_config *vfio_cfg)
+{
+       unsigned int i;
+
+       for (i = 0; i < RTE_DIM(vfio_cfg->vfio_groups); i++) {
+               struct vfio_group *group = &vfio_cfg->vfio_groups[i];
+
+               if (group->group_num == -1)
Quoted 8 lines

lib/eal/linux/eal_vfio.c rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova, · line 2312

Quoted 5 lines
lib/eal/linux/eal_vfio.c +5 -0
+                       continue;
+               if (group->devices != 0) {
+                       EAL_LOG(ERR, "Cannot cleanup VFIO group %d with %d devices",
+                               group->group_num, group->devices);
+                       return;

Why stop?
Should we continue for other groups?

It wouldn't really matter as cleanup would fail anyway and there's nothing we can do about it if we couldn't close all groups. So, tomato, tomato. We can, of course, continue here, and cleanup all groups that we can.

Signature · 2 lines
Thanks,
Anatoly
#268 lore raw

PATCH v17 7/26 vfio: remove modname parameter from init

In reply to Anatoly Burakov

All VFIO initialization always happens with "vfio" module, and now that the API is not public, having a way to override the module name seems redundant as there is not going to be a use case that calls into rte_vfio_enable that isn't coming from EAL init. So, remove the parameter, and hardcode the modname to "vfio" instead.

---
 drivers/bus/pci/linux/pci_vfio.c | 2 +-
 lib/eal/freebsd/eal.c            | 2 +-
 lib/eal/include/rte_vfio.h       | 7 ++-----
 lib/eal/linux/eal.c              | 2 +-
 lib/eal/linux/eal_vfio.c         | 5 +++--
 5 files changed, 8 insertions(+), 10 deletions(-)
drivers/bus/pci/linux/pci_vfio.c +1 -1
index bc5c5c2499..f3791cce98 100644
@@ -1303,7 +1303,7 @@ pci_vfio_is_enabled(void)
 	int status = rte_vfio_is_enabled("vfio_pci");
 
 	if (!status) {
-		rte_vfio_enable("vfio");
+		rte_vfio_enable();
 		status = rte_vfio_is_enabled("vfio_pci");
 	}
 	return status;
lib/eal/freebsd/eal.c +1 -1
index aa6d4c2e16..52d265769e 100644
@@ -839,7 +839,7 @@ int rte_vfio_release_device(__rte_unused const char *sysfs_base,
 }
 
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_enable)
-int rte_vfio_enable(__rte_unused const char *modname)
+int rte_vfio_enable(void)
 {
 	rte_errno = ENOTSUP;
 	return -1;
lib/eal/include/rte_vfio.h +2 -5
index e76181c83c..b53ce56a8d 100644
@@ -94,20 +94,17 @@ int rte_vfio_release_device(const char *sysfs_base, const char *dev_addr, int fd
 
 /**
  * @internal
- * Enable a VFIO-related kmod.
+ * Initialize VFIO.
  *
  * This function is only relevant to linux and will return
  * an error on BSD.
  *
- * @param modname
- *   kernel module name.
- *
  * @return
  *   0 on success.
  *   <0 on failure.
  */
 __rte_internal
-int rte_vfio_enable(const char *modname);
+int rte_vfio_enable(void);
 
 /**
  * @internal
lib/eal/linux/eal.c +1 -1
index 5577bab24a..17977baedc 100644
@@ -771,7 +771,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (rte_vfio_enable("vfio")) {
+	if (rte_vfio_enable()) {
 		rte_eal_init_alert("Cannot init VFIO");
 		rte_errno = EAGAIN;
 		goto err_out;
lib/eal/linux/eal_vfio.c +3 -2
index d4173f7a01..da46ef2f17 100644
@@ -25,6 +25,7 @@
 #include "eal_internal_cfg.h"
 
 #define VFIO_MEM_EVENT_CLB_NAME "vfio_mem_event_clb"
+#define VFIO_MODNAME "vfio"
 
 /* hot plug/unplug of VFIO groups may cause all DMA maps to be dropped. we can
  * recreate the mappings for DPDK segments, but we cannot do so for memory that
@@ -1123,7 +1124,7 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
 
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_enable)
 int
-rte_vfio_enable(const char *modname)
+rte_vfio_enable(void)
 {
 	/* initialize group list */
 	unsigned int i, j;
@@ -1154,7 +1155,7 @@ rte_vfio_enable(const char *modname)
 	EAL_LOG(DEBUG, "Probing VFIO support...");
 
 	/* check if vfio module is loaded */
-	vfio_available = rte_eal_check_module(modname);
+	vfio_available = rte_eal_check_module(VFIO_MODNAME);
 
 	/* return error directly */
 	if (vfio_available == -1) {
Signature · 1 line
2.52.0
#269 lore raw

PATCH v17 8/26 vfio: rename API to reflect internal status

In reply to Anatoly Burakov

Currently, even though VFIO API is internal-only, it is still named with an rte_ prefix, which implies public API. To reflect the fact that this API is no longer public, rename all symbols and macros from rte_/RTE_ to dev_/DEV_, and adjust all callers.

---
 doc/guides/rel_notes/release_26_11.rst     |   4 +-
 drivers/bus/cdx/cdx.c                      |   6 +-
 drivers/bus/cdx/cdx_vfio.c                 |  14 +--
 drivers/bus/fslmc/fslmc_bus.c              |   4 +-
 drivers/bus/fslmc/fslmc_vfio.c             |  12 +-
 drivers/bus/pci/linux/pci.c                |   4 +-
 drivers/bus/pci/linux/pci_vfio.c           |  38 +++----
 drivers/bus/pci/pci_common.c               |  10 +-
 drivers/bus/platform/platform.c            |  10 +-
 drivers/crypto/bcmfs/bcmfs_vfio.c          |   8 +-
 drivers/net/hinic3/base/hinic3_hwdev.c     |   4 +-
 drivers/net/nbl/nbl_common/nbl_userdev.c   |  16 +--
 drivers/net/ntnic/ntnic_ethdev.c           |  10 +-
 drivers/net/ntnic/ntnic_vfio.c             |  22 ++--
 drivers/vdpa/ifc/ifcvf_vdpa.c              |  24 ++--
 drivers/vdpa/nfp/nfp_vdpa.c                |  24 ++--
 drivers/vdpa/sfc/sfc_vdpa.c                |  16 +--
 drivers/vdpa/sfc/sfc_vdpa_hw.c             |  12 +-
 lib/eal/freebsd/eal.c                      |  73 ++++++------
 lib/eal/include/{rte_vfio.h => dev_vfio.h} |  58 +++++-----
 lib/eal/include/meson.build                |   2 +-
 lib/eal/linux/eal.c                        |   6 +-
 lib/eal/linux/eal_vfio.c                   | 122 ++++++++++-----------
 lib/eal/linux/eal_vfio_mp_sync.c           |   6 +-
 lib/eal/windows/eal.c                      |  14 +--
 lib/vhost/vhost_user.c                     |  16 +--
 26 files changed, 271 insertions(+), 264 deletions(-)
 rename lib/eal/include/{rte_vfio.h => dev_vfio.h} (82%)
doc/guides/rel_notes/release_26_11.rst +2 -2
index b5793b5c94..71d12a4398 100644
@@ -94,8 +94,8 @@ API Changes
    =======================================================
 
 * vfio: The entire VFIO API (``rte_vfio_*``) was made internal.
-  These functions are now available only to EAL and drivers,
-  and are no longer part of the public API.
+  These functions were renamed to ``dev_vfio_*``, are now available
+  only to EAL and drivers, and are no longer part of public API.
 
 
 ABI Changes
drivers/bus/cdx/cdx.c +3 -3
index c0b46a41ad..ee8f24e67e 100644
@@ -73,7 +73,7 @@
 #include <rte_devargs.h>
 #include <rte_kvargs.h>
 #include <rte_malloc.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include <eal_export.h>
 #include <eal_filesystem.h>
@@ -403,7 +403,7 @@ cdx_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 {
 	RTE_SET_USED(dev);
 
-	return rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD,
+	return dev_vfio_container_dma_map(DEV_VFIO_DEFAULT_CONTAINER_FD,
 					  (uintptr_t)addr, iova, len);
 }
 
@@ -412,7 +412,7 @@ cdx_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 {
 	RTE_SET_USED(dev);
 
-	return rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD,
+	return dev_vfio_container_dma_unmap(DEV_VFIO_DEFAULT_CONTAINER_FD,
 					    (uintptr_t)addr, iova, len);
 }
 
drivers/bus/cdx/cdx_vfio.c +7 -7
index 11fe3265d2..02a34d6f18 100644
@@ -23,7 +23,7 @@
 #include <eal_export.h>
 #include <rte_eal_paging.h>
 #include <rte_malloc.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "bus_cdx_driver.h"
 #include "cdx_logs.h"
@@ -121,7 +121,7 @@ cdx_vfio_unmap_resource_primary(struct rte_cdx_device *dev)
 	if (vfio_dev_fd < 0)
 		return -1;
 
-	ret = rte_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev->device.name,
+	ret = dev_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev->device.name,
 				      vfio_dev_fd);
 	if (ret < 0) {
 		CDX_BUS_ERR("Cannot release VFIO device");
@@ -155,7 +155,7 @@ cdx_vfio_unmap_resource_secondary(struct rte_cdx_device *dev)
 	if (vfio_dev_fd < 0)
 		return -1;
 
-	ret = rte_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev->device.name,
+	ret = dev_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev->device.name,
 				      vfio_dev_fd);
 	if (ret < 0) {
 		CDX_BUS_ERR("Cannot release VFIO device");
@@ -400,7 +400,7 @@ cdx_vfio_map_resource_primary(struct rte_cdx_device *dev)
 	if (rte_intr_fd_set(dev->intr_handle, -1))
 		return -1;
 
-	ret = rte_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
+	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
 				    &vfio_dev_fd, &device_info);
 	if (ret)
 		return ret;
@@ -477,7 +477,7 @@ cdx_vfio_map_resource_primary(struct rte_cdx_device *dev)
 	cdx_vfio_find_and_unmap_resource(vfio_res_list, dev);
 	rte_free(vfio_res);
 err_vfio_dev_fd:
-	rte_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, vfio_dev_fd);
+	dev_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, vfio_dev_fd);
 	return -1;
 }
 
@@ -509,7 +509,7 @@ cdx_vfio_map_resource_secondary(struct rte_cdx_device *dev)
 		return -1;
 	}
 
-	ret = rte_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
+	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
 					&vfio_dev_fd, &device_info);
 	if (ret)
 		return ret;
@@ -535,7 +535,7 @@ cdx_vfio_map_resource_secondary(struct rte_cdx_device *dev)
 
 	return 0;
 err_vfio_dev_fd:
-	rte_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, vfio_dev_fd);
+	dev_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, vfio_dev_fd);
 	return -1;
 }
 
drivers/bus/fslmc/fslmc_bus.c +2 -2
index 3626b12316..d55c414ead 100644
@@ -17,7 +17,7 @@
 #include <rte_memcpy.h>
 #include <ethdev_driver.h>
 #include <rte_mbuf_dyn.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "private.h"
 #include <fslmc_vfio.h>
@@ -500,7 +500,7 @@ rte_dpaa2_get_iommu_class(void)
 		return RTE_IOVA_DC;
 
 	/* check if all devices on the bus support Virtual addressing or not */
-	if (fslmc_all_device_support_iova() != 0 && rte_vfio_noiommu_is_enabled() == 0)
+	if (fslmc_all_device_support_iova() != 0 && dev_vfio_noiommu_is_enabled() == 0)
 		return RTE_IOVA_VA;
 
 	return RTE_IOVA_PA;
drivers/bus/fslmc/fslmc_vfio.c +6 -6
index 8d39895bac..153e6112db 100644
@@ -34,7 +34,7 @@
 #include <rte_kvargs.h>
 #include <dev_driver.h>
 #include <rte_eal_memconfig.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "private.h"
 #include "fslmc_vfio.h"
@@ -204,7 +204,7 @@ fslmc_vfio_add_group(int vfio_group_fd,
 	group->fd = vfio_group_fd;
 	group->groupid = iommu_group_num;
 	rte_strscpy(group->group_name, group_name, sizeof(group->group_name));
-	if (rte_vfio_noiommu_is_enabled() > 0)
+	if (dev_vfio_noiommu_is_enabled() > 0)
 		group->iommu_type = VFIO_NOIOMMU_IOMMU;
 	else
 		group->iommu_type = VFIO_TYPE1_IOMMU;
@@ -374,7 +374,7 @@ fslmc_get_group_id(const char *group_name,
 	int ret;
 
 	/* get group number */
-	ret = rte_vfio_get_group_num(SYSFS_FSL_MC_DEVICES,
+	ret = dev_vfio_get_group_num(SYSFS_FSL_MC_DEVICES,
 			group_name, groupid);
 	if (ret <= 0) {
 		DPAA2_BUS_ERR("Find %s IOMMU group", group_name);
@@ -411,7 +411,7 @@ fslmc_vfio_open_group_fd(const char *group_name)
 	/* if primary, try to open the group */
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
 		/* try regular group format */
-		snprintf(filename, sizeof(filename), RTE_VFIO_GROUP_FMT, iommu_group_num);
+		snprintf(filename, sizeof(filename), DEV_VFIO_GROUP_FMT, iommu_group_num);
 		vfio_group_fd = open(filename, O_RDWR);
 
 		goto add_vfio_group;
@@ -509,10 +509,10 @@ fslmc_vfio_open_container_fd(void)
 
 	/* if we're in a primary process, try to open the container */
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
-		vfio_container_fd = open(RTE_VFIO_CONTAINER_PATH, O_RDWR);
+		vfio_container_fd = open(DEV_VFIO_CONTAINER_PATH, O_RDWR);
 		if (vfio_container_fd < 0) {
 			DPAA2_BUS_ERR("Open VFIO container(%s), err(%d)",
-				RTE_VFIO_CONTAINER_PATH, vfio_container_fd);
+				DEV_VFIO_CONTAINER_PATH, vfio_container_fd);
 			ret = vfio_container_fd;
 			goto err_exit;
 		}
drivers/bus/pci/linux/pci.c +2 -2
index 9aae0a5d14..af37a65c45 100644
@@ -11,7 +11,7 @@
 #include <rte_malloc.h>
 #include <rte_devargs.h>
 #include <rte_memcpy.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include <eal_export.h>
 #include "eal_filesystem.h"
@@ -596,7 +596,7 @@ pci_device_iova_mode(const struct rte_pci_driver *pdrv,
 		static int is_vfio_noiommu_enabled = -1;
 
 		if (is_vfio_noiommu_enabled == -1) {
-			if (rte_vfio_noiommu_is_enabled() == 1)
+			if (dev_vfio_noiommu_is_enabled() == 1)
 				is_vfio_noiommu_enabled = 1;
 			else
 				is_vfio_noiommu_enabled = 0;
drivers/bus/pci/linux/pci_vfio.c +19 -19
index f3791cce98..71afc383e6 100644
@@ -18,7 +18,7 @@
 #include <rte_bus_pci.h>
 #include <rte_eal_paging.h>
 #include <rte_malloc.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_eal.h>
 #include <bus_driver.h>
 #include <rte_spinlock.h>
@@ -29,10 +29,10 @@
 #include "pci_init.h"
 #include "private.h"
 
-static struct rte_tailq_elem rte_vfio_tailq = {
+static struct rte_tailq_elem dev_vfio_tailq = {
 	.name = "VFIO_RESOURCE_LIST",
 };
-EAL_REGISTER_TAILQ(rte_vfio_tailq)
+EAL_REGISTER_TAILQ(dev_vfio_tailq)
 
 static int
 pci_vfio_get_region(const struct rte_pci_device *dev, int index,
@@ -418,7 +418,7 @@ pci_vfio_is_ioport_bar(const struct rte_pci_device *dev, int vfio_dev_fd,
 }
 
 static int
-pci_rte_vfio_setup_device(struct rte_pci_device *dev, int vfio_dev_fd)
+pci_vfio_setup_device(struct rte_pci_device *dev, int vfio_dev_fd)
 {
 	if (pci_vfio_setup_interrupts(dev, vfio_dev_fd) != 0) {
 		PCI_LOG(ERR, "Error setting up interrupts!");
@@ -738,7 +738,7 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 	int i, j, ret;
 	struct mapped_pci_resource *vfio_res = NULL;
 	struct mapped_pci_res_list *vfio_res_list =
-		RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+		RTE_TAILQ_CAST(dev_vfio_tailq.head, mapped_pci_res_list);
 
 	struct pci_map *maps;
 
@@ -752,7 +752,7 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 	snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,
 			loc->domain, loc->bus, loc->devid, loc->function);
 
-	ret = rte_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
+	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
 					&vfio_dev_fd, &device_info);
 	if (ret)
 		return ret;
@@ -897,7 +897,7 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 		free(reg);
 	}
 
-	if (pci_rte_vfio_setup_device(dev, vfio_dev_fd) < 0) {
+	if (pci_vfio_setup_device(dev, vfio_dev_fd) < 0) {
 		PCI_LOG(ERR, "%s setup device failed", pci_addr);
 		goto err_map;
 	}
@@ -920,7 +920,7 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 err_vfio_res:
 	rte_free(vfio_res);
 err_vfio_dev_fd:
-	rte_vfio_release_device(rte_pci_get_sysfs_path(),
+	dev_vfio_release_device(rte_pci_get_sysfs_path(),
 			pci_addr, vfio_dev_fd);
 	return -1;
 }
@@ -935,7 +935,7 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 	int j, ret, i = 0;
 	struct mapped_pci_resource *vfio_res = NULL;
 	struct mapped_pci_res_list *vfio_res_list =
-		RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+		RTE_TAILQ_CAST(dev_vfio_tailq.head, mapped_pci_res_list);
 
 	struct pci_map *maps;
 
@@ -961,7 +961,7 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 		return -1;
 	}
 
-	ret = rte_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
+	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
 					&vfio_dev_fd, &device_info);
 	if (ret)
 		return ret;
@@ -1006,7 +1006,7 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 			pci_unmap_resource(maps[j].addr, maps[j].size);
 	}
 err_vfio_dev:
-	rte_vfio_release_device(rte_pci_get_sysfs_path(),
+	dev_vfio_release_device(rte_pci_get_sysfs_path(),
 			pci_addr, vfio_dev_fd);
 	return -1;
 }
@@ -1101,7 +1101,7 @@ pci_vfio_unmap_resource_primary(struct rte_pci_device *dev)
 		return -1;
 	}
 
-	ret = rte_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
+	ret = dev_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
 				      vfio_dev_fd);
 	if (ret < 0) {
 		PCI_LOG(ERR, "Cannot release VFIO device");
@@ -1109,7 +1109,7 @@ pci_vfio_unmap_resource_primary(struct rte_pci_device *dev)
 	}
 
 	vfio_res_list =
-		RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+		RTE_TAILQ_CAST(dev_vfio_tailq.head, mapped_pci_res_list);
 	vfio_res = find_and_unmap_vfio_resource(vfio_res_list, dev, pci_addr);
 
 	/* if we haven't found our tailq entry, something's wrong */
@@ -1140,7 +1140,7 @@ pci_vfio_unmap_resource_secondary(struct rte_pci_device *dev)
 	if (vfio_dev_fd < 0)
 		return -1;
 
-	ret = rte_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
+	ret = dev_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
 				      vfio_dev_fd);
 	if (ret < 0) {
 		PCI_LOG(ERR, "Cannot release VFIO device");
@@ -1148,7 +1148,7 @@ pci_vfio_unmap_resource_secondary(struct rte_pci_device *dev)
 	}
 
 	vfio_res_list =
-		RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+		RTE_TAILQ_CAST(dev_vfio_tailq.head, mapped_pci_res_list);
 	vfio_res = find_and_unmap_vfio_resource(vfio_res_list, dev, pci_addr);
 
 	/* if we haven't found our tailq entry, something's wrong */
@@ -1195,7 +1195,7 @@ pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,
 		if (vfio_dev_fd < 0) {
 			return -1;
 		} else if (vfio_dev_fd == 0) {
-			if (rte_vfio_get_device_info(rte_pci_get_sysfs_path(), pci_addr,
+			if (dev_vfio_get_device_info(rte_pci_get_sysfs_path(), pci_addr,
 				&vfio_dev_fd, &device_info) != 0)
 				return -1;
 			/* save vfio_dev_fd so it can be used during release */
@@ -1300,11 +1300,11 @@ pci_vfio_mmio_write(const struct rte_pci_device *dev, int bar,
 int
 pci_vfio_is_enabled(void)
 {
-	int status = rte_vfio_is_enabled("vfio_pci");
+	int status = dev_vfio_is_enabled("vfio_pci");
 
 	if (!status) {
-		rte_vfio_enable();
-		status = rte_vfio_is_enabled("vfio_pci");
+		dev_vfio_enable();
+		status = dev_vfio_is_enabled("vfio_pci");
 	}
 	return status;
 }
drivers/bus/pci/pci_common.c +5 -5
index dc8db80d3b..fcc4495b92 100644
@@ -25,7 +25,7 @@
 #include <rte_string_fns.h>
 #include <rte_common.h>
 #include <rte_devargs.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_tailq.h>
 
 #include "private.h"
@@ -487,8 +487,8 @@ pci_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 	 *  try fallback to VFIO.
 	 */
 	if (pdev->kdrv == RTE_PCI_KDRV_VFIO)
-		return rte_vfio_container_dma_map
-				(RTE_VFIO_DEFAULT_CONTAINER_FD, (uintptr_t)addr,
+		return dev_vfio_container_dma_map
+				(DEV_VFIO_DEFAULT_CONTAINER_FD, (uintptr_t)addr,
 				 iova, len);
 	rte_errno = ENOTSUP;
 	return -1;
@@ -507,8 +507,8 @@ pci_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 	 *  try fallback to VFIO.
 	 */
 	if (pdev->kdrv == RTE_PCI_KDRV_VFIO)
-		return rte_vfio_container_dma_unmap
-				(RTE_VFIO_DEFAULT_CONTAINER_FD, (uintptr_t)addr,
+		return dev_vfio_container_dma_unmap
+				(DEV_VFIO_DEFAULT_CONTAINER_FD, (uintptr_t)addr,
 				 iova, len);
 	rte_errno = ENOTSUP;
 	return -1;
drivers/bus/platform/platform.c +5 -5
index 90d865a8df..9d7df9be80 100644
@@ -23,7 +23,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_string_fns.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "private.h"
 
@@ -282,7 +282,7 @@ static void
 device_cleanup(struct rte_platform_device *pdev)
 {
 	device_unmap_resources(pdev);
-	rte_vfio_release_device(PLATFORM_BUS_DEVICES_PATH, pdev->name, pdev->dev_fd);
+	dev_vfio_release_device(PLATFORM_BUS_DEVICES_PATH, pdev->name, pdev->dev_fd);
 }
 
 static int
@@ -292,7 +292,7 @@ device_setup(struct rte_platform_device *pdev)
 	const char *name = pdev->name;
 	int ret;
 
-	ret = rte_vfio_setup_device(PLATFORM_BUS_DEVICES_PATH, name, &pdev->dev_fd, &dev_info);
+	ret = dev_vfio_setup_device(PLATFORM_BUS_DEVICES_PATH, name, &pdev->dev_fd, &dev_info);
 	if (ret) {
 		PLATFORM_LOG_LINE(ERR, "failed to setup %s", name);
 		return -ENODEV;
@@ -458,7 +458,7 @@ platform_bus_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t l
 	if (pdrv->dma_map != NULL)
 		return pdrv->dma_map(pdev, addr, iova, len);
 
-	return rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD, (uint64_t)addr, iova, len);
+	return dev_vfio_container_dma_map(DEV_VFIO_DEFAULT_CONTAINER_FD, (uint64_t)addr, iova, len);
 }
 
 static int
@@ -470,7 +470,7 @@ platform_bus_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t
 	if (pdrv->dma_unmap != NULL)
 		return pdrv->dma_unmap(pdev, addr, iova, len);
 
-	return rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD, (uint64_t)addr, iova,
+	return dev_vfio_container_dma_unmap(DEV_VFIO_DEFAULT_CONTAINER_FD, (uint64_t)addr, iova,
 					    len);
 }
 
drivers/crypto/bcmfs/bcmfs_vfio.c +4 -4
index e7f7ed994c..053af0d227 100644
@@ -9,7 +9,7 @@
 #include <sys/mman.h>
 #include <sys/ioctl.h>
 
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "bcmfs_device.h"
 #include "bcmfs_logs.h"
@@ -25,7 +25,7 @@ vfio_map_dev_obj(const char *path, const char *dev_obj,
 	struct vfio_device_info d_info = { .argsz = sizeof(d_info) };
 	struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
 
-	ret = rte_vfio_setup_device(path, dev_obj, dev_fd, &d_info);
+	ret = dev_vfio_setup_device(path, dev_obj, dev_fd, &d_info);
 	if (ret) {
 		BCMFS_LOG(ERR, "VFIO Setting for device failed");
 		return ret;
@@ -51,7 +51,7 @@ vfio_map_dev_obj(const char *path, const char *dev_obj,
 	return 0;
 
 map_failed:
-	rte_vfio_release_device(path, dev_obj, *dev_fd);
+	dev_vfio_release_device(path, dev_obj, *dev_fd);
 
 	return ret;
 }
@@ -87,7 +87,7 @@ bcmfs_release_vfio(struct bcmfs_device *dev)
 	/* unmap the addr */
 	munmap(dev->mmap_addr, dev->mmap_size);
 	/* release the device */
-	ret = rte_vfio_release_device(dev->dirname, dev->name,
+	ret = dev_vfio_release_device(dev->dirname, dev->name,
 				      dev->vfio_dev_fd);
 	if (ret < 0) {
 		BCMFS_LOG(ERR, "cannot release device");
drivers/net/hinic3/base/hinic3_hwdev.c +2 -2
index d09a8f7e7d..6a6cf44752 100644
@@ -2,7 +2,7 @@
  * Copyright(c) 2025 Huawei Technologies Co., Ltd
  */
 
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "hinic3_compat.h"
 #include "hinic3_cmd.h"
@@ -78,7 +78,7 @@ hinic3_is_vfio_iommu_enable(const struct rte_eth_dev *eth_dev)
 {
 	struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
 
-	return pci_dev->kdrv == RTE_PCI_KDRV_VFIO && rte_vfio_noiommu_is_enabled() != 1;
+	return pci_dev->kdrv == RTE_PCI_KDRV_VFIO && dev_vfio_noiommu_is_enabled() != 1;
 }
 
 int
drivers/net/nbl/nbl_common/nbl_userdev.c +8 -8
index ec6840d60e..f1522772f5 100644
@@ -4,7 +4,7 @@
 
 #include "nbl_userdev.h"
 #include <uapi/linux/vfio.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #define NBL_USERDEV_EVENT_CLB_NAME	"nbl_userspace_mem_event_clb"
 #define NBL_USERDEV_BAR0_SIZE		65536
@@ -405,7 +405,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	snprintf(pathname, sizeof(pathname),
 		 "%s/%s/", rte_pci_get_sysfs_path(), dev_name);
 
-	ret = rte_vfio_get_group_num(pathname, dev_name, &common->iommu_group_num);
+	ret = dev_vfio_get_group_num(pathname, dev_name, &common->iommu_group_num);
 	if (ret <= 0) {
 		NBL_LOG(ERR, "nbl vfio group number failed");
 		return -1;
@@ -414,7 +414,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	NBL_LOG(DEBUG, "nbl vfio group number %d", common->iommu_group_num);
 	/* vfio_container */
 	if (nbl_default_container < 0) {
-		container = rte_vfio_container_create();
+		container = dev_vfio_container_create();
 		container_create = 1;
 
 		if (container < 0) {
@@ -424,7 +424,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	}
 
 	NBL_LOG(DEBUG, "nbl vfio container %d", container);
-	vfio_group_fd = rte_vfio_container_group_bind(container, common->iommu_group_num);
+	vfio_group_fd = dev_vfio_container_group_bind(container, common->iommu_group_num);
 	if (vfio_group_fd < 0) {
 		NBL_LOG(ERR, "nbl vfio group bind failed, %d", vfio_group_fd);
 		goto free_container;
@@ -535,10 +535,10 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	}
 free_group:
 	close(vfio_group_fd);
-	rte_vfio_clear_group(vfio_group_fd);
+	dev_vfio_clear_group(vfio_group_fd);
 free_container:
 	if (container_create)
-		rte_vfio_container_destroy(container);
+		dev_vfio_container_destroy(container);
 	return -1;
 }
 
@@ -550,7 +550,7 @@ static int nbl_mdev_unmap_device(struct nbl_adapter *adapter)
 	rte_mcfg_mem_read_lock();
 	TAILQ_REMOVE(&nbl_adapter_list, adapter, next);
 	close(common->devfd);
-	vfio_group_fd = rte_vfio_container_group_bind(nbl_default_container,
+	vfio_group_fd = dev_vfio_container_group_bind(nbl_default_container,
 						      common->iommu_group_num);
 	NBL_LOG(DEBUG, "close vfio_group_fd %d", vfio_group_fd);
 	ret = ioctl(vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, &nbl_default_container);
@@ -558,7 +558,7 @@ static int nbl_mdev_unmap_device(struct nbl_adapter *adapter)
 		NBL_LOG(ERR, "unset container, error %i (%s) %d",
 			errno, strerror(errno), ret);
 	nbl_group_count--;
-	ret = rte_vfio_container_group_unbind(nbl_default_container, common->iommu_group_num);
+	ret = dev_vfio_container_group_unbind(nbl_default_container, common->iommu_group_num);
 	if (ret)
 		NBL_LOG(ERR, "vfio container group unbind failed %d", ret);
 	if (!nbl_group_count) {
drivers/net/ntnic/ntnic_ethdev.c +5 -5
index 7cc90a7a5b..d9744a7d05 100644
@@ -7,7 +7,7 @@
 
 #include <rte_eal.h>
 #include <rte_dev.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_ethdev.h>
 #include <rte_bus_pci.h>
 #include <ethdev_pci.h>
@@ -2690,12 +2690,12 @@ nthw_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			(pci_dev->device.devargs->data ? pci_dev->device.devargs->data : "NULL"));
 	}
 
-	const int n_rte_vfio_no_io_mmu_enabled = rte_vfio_noiommu_is_enabled();
-	NT_LOG(DBG, NTNIC, "vfio_no_iommu_enabled=%d", n_rte_vfio_no_io_mmu_enabled);
+	const int n_dev_vfio_no_io_mmu_enabled = dev_vfio_noiommu_is_enabled();
+	NT_LOG(DBG, NTNIC, "vfio_no_iommu_enabled=%d", n_dev_vfio_no_io_mmu_enabled);
 
-	if (n_rte_vfio_no_io_mmu_enabled) {
+	if (n_dev_vfio_no_io_mmu_enabled) {
 		NT_LOG(ERR, NTNIC, "vfio_no_iommu_enabled=%d: this PMD needs VFIO IOMMU",
-			n_rte_vfio_no_io_mmu_enabled);
+			n_dev_vfio_no_io_mmu_enabled);
 		return -1;
 	}
 
drivers/net/ntnic/ntnic_vfio.c +11 -11
index 439468b3a2..8489a59859 100644
@@ -6,7 +6,7 @@
 
 #include <rte_malloc.h>
 #include <rte_memory.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_dev.h>
 #include <rte_bus_pci.h>
 #include <rte_spinlock.h>
@@ -70,16 +70,16 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 	vfio->iova_addr = START_VF_IOVA;
 
 	rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
-	ret = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), devname, &iommu_group_num);
+	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), devname, &iommu_group_num);
 	if (ret <= 0)
 		return -1;
 
 	if (vf_num == 0) {
 		/* use default container for pf0 */
-		vfio->container_fd = RTE_VFIO_DEFAULT_CONTAINER_FD;
+		vfio->container_fd = DEV_VFIO_DEFAULT_CONTAINER_FD;
 
 	} else {
-		vfio->container_fd = rte_vfio_container_create();
+		vfio->container_fd = dev_vfio_container_create();
 
 		if (vfio->container_fd < 0) {
 			NT_LOG(ERR, NTNIC,
@@ -88,7 +88,7 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 		}
 	}
 
-	vfio->group_fd = rte_vfio_container_group_bind(vfio->container_fd, iommu_group_num);
+	vfio->group_fd = dev_vfio_container_group_bind(vfio->container_fd, iommu_group_num);
 
 	if (vfio->group_fd < 0) {
 		NT_LOG(ERR, NTNIC,
@@ -115,8 +115,8 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 
 err:
 
-	if (vfio->container_fd != RTE_VFIO_DEFAULT_CONTAINER_FD)
-		rte_vfio_container_destroy(vfio->container_fd);
+	if (vfio->container_fd != DEV_VFIO_DEFAULT_CONTAINER_FD)
+		dev_vfio_container_destroy(vfio->container_fd);
 
 	return -1;
 }
@@ -135,7 +135,7 @@ nthw_vfio_remove(int vf_num)
 		return -1;
 	}
 
-	rte_vfio_container_destroy(vfio->container_fd);
+	dev_vfio_container_destroy(vfio->container_fd);
 	return 0;
 }
 
@@ -169,14 +169,14 @@ nthw_vfio_dma_map(int vf_num, void *virt_addr, uint64_t *iova_addr, uint64_t siz
 		vf_num, virt_addr, rte_malloc_virt2iova(virt_addr), gp_virt_base, vfio->iova_addr,
 		size);
 
-	int res = rte_vfio_container_dma_map(vfio->container_fd, gp_virt_base, vfio->iova_addr,
+	int res = dev_vfio_container_dma_map(vfio->container_fd, gp_virt_base, vfio->iova_addr,
 			size);
 
 	NT_LOG(DBG, NTNIC, "VFIO MMAP res %i, container_fd %i, vf_num %i", res,
 		vfio->container_fd, vf_num);
 
 	if (res) {
-		NT_LOG(ERR, NTNIC, "rte_vfio_container_dma_map failed: res %d", res);
+		NT_LOG(ERR, NTNIC, "dev_vfio_container_dma_map failed: res %d", res);
 		return -1;
 	}
 
@@ -210,7 +210,7 @@ nthw_vfio_dma_unmap(int vf_num, void *virt_addr, uint64_t iova_addr, uint64_t si
 		return -1;
 	}
 
-	int res = rte_vfio_container_dma_unmap(vfio->container_fd, gp_virt_base, iova_addr, size);
+	int res = dev_vfio_container_dma_unmap(vfio->container_fd, gp_virt_base, iova_addr, size);
 
 	if (res != 0) {
 		NT_LOG(ERR, NTNIC,
drivers/vdpa/ifc/ifcvf_vdpa.c +12 -12
index f319d455ba..36d06f1e3f 100644
@@ -20,7 +20,7 @@
 #include <rte_vhost.h>
 #include <rte_vdpa.h>
 #include <vdpa_driver.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_spinlock.h>
 #include <rte_log.h>
 #include <rte_kvargs.h>
@@ -182,18 +182,18 @@ ifcvf_vfio_setup(struct ifcvf_internal *internal)
 	internal->vfio_container_fd = -1;
 
 	rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
-	ret = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), devname,
+	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), devname,
 			&iommu_group_num);
 	if (ret <= 0) {
 		DRV_LOG(ERR, "%s failed to get IOMMU group", devname);
 		return -1;
 	}
 
-	internal->vfio_container_fd = rte_vfio_container_create();
+	internal->vfio_container_fd = dev_vfio_container_create();
 	if (internal->vfio_container_fd < 0)
 		return -1;
 
-	internal->vfio_group_fd = rte_vfio_container_group_bind(
+	internal->vfio_group_fd = dev_vfio_container_group_bind(
 			internal->vfio_container_fd, iommu_group_num);
 	if (internal->vfio_group_fd < 0)
 		goto err;
@@ -216,7 +216,7 @@ ifcvf_vfio_setup(struct ifcvf_internal *internal)
 	return 0;
 
 err:
-	rte_vfio_container_destroy(internal->vfio_container_fd);
+	dev_vfio_container_destroy(internal->vfio_container_fd);
 	return -1;
 }
 
@@ -246,7 +246,7 @@ ifcvf_dma_map(struct ifcvf_internal *internal, bool do_map)
 			reg->host_user_addr, reg->guest_phys_addr, reg->size);
 
 		if (do_map) {
-			ret = rte_vfio_container_dma_map(vfio_container_fd,
+			ret = dev_vfio_container_dma_map(vfio_container_fd,
 				reg->host_user_addr, reg->guest_phys_addr,
 				reg->size);
 			if (ret < 0) {
@@ -254,7 +254,7 @@ ifcvf_dma_map(struct ifcvf_internal *internal, bool do_map)
 				goto exit;
 			}
 		} else {
-			ret = rte_vfio_container_dma_unmap(vfio_container_fd,
+			ret = dev_vfio_container_dma_unmap(vfio_container_fd,
 				reg->host_user_addr, reg->guest_phys_addr,
 				reg->size);
 			if (ret < 0) {
@@ -388,7 +388,7 @@ vdpa_ifcvf_stop(struct ifcvf_internal *internal)
 	if (RTE_VHOST_NEED_LOG(features)) {
 		ifcvf_disable_logging(hw);
 		rte_vhost_get_log_base(internal->vid, &log_base, &log_size);
-		rte_vfio_container_dma_unmap(internal->vfio_container_fd,
+		dev_vfio_container_dma_unmap(internal->vfio_container_fd,
 				log_base, IFCVF_LOG_BASE, log_size);
 		/*
 		 * IFCVF marks dirty memory pages for only packet buffer,
@@ -791,7 +791,7 @@ m_ifcvf_start(struct ifcvf_internal *internal)
 		vring_init(&internal->m_vring[i], vq.size, vring_buf,
 				rte_mem_page_size());
 
-		ret = rte_vfio_container_dma_map(internal->vfio_container_fd,
+		ret = dev_vfio_container_dma_map(internal->vfio_container_fd,
 			(uint64_t)(uintptr_t)vring_buf, m_vring_iova, size);
 		if (ret < 0) {
 			DRV_LOG(ERR, "mediated vring DMA map failed.");
@@ -900,7 +900,7 @@ m_ifcvf_stop(struct ifcvf_internal *internal)
 
 		size = RTE_ALIGN_CEIL(vring_size(vq.size, rte_mem_page_size()),
 				rte_mem_page_size());
-		rte_vfio_container_dma_unmap(internal->vfio_container_fd,
+		dev_vfio_container_dma_unmap(internal->vfio_container_fd,
 			(uint64_t)(uintptr_t)internal->m_vring[i].desc,
 			m_vring_iova, size);
 
@@ -1205,7 +1205,7 @@ ifcvf_set_features(int vid)
 		ifcvf_sw_fallback_switchover(internal);
 	} else {
 		rte_vhost_get_log_base(vid, &log_base, &log_size);
-		rte_vfio_container_dma_map(internal->vfio_container_fd,
+		dev_vfio_container_dma_map(internal->vfio_container_fd,
 				log_base, IFCVF_LOG_BASE, log_size);
 		ifcvf_enable_logging(&internal->hw, IFCVF_LOG_BASE, log_size);
 	}
@@ -1824,7 +1824,7 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 		DRV_LOG(ERR, "failed to update datapath %s", pci_dev->name);
 
 	rte_pci_unmap_device(internal->pdev);
-	rte_vfio_container_destroy(internal->vfio_container_fd);
+	dev_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
 	pthread_mutex_lock(&internal_list_lock);
drivers/vdpa/nfp/nfp_vdpa.c +12 -12
index 4c0ab3ff30..94740e768d 100644
@@ -12,7 +12,7 @@
 
 #include <nfp_common_pci.h>
 #include <nfp_dev.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_eal_paging.h>
 #include <rte_malloc.h>
 #include <vdpa_driver.h>
@@ -120,16 +120,16 @@ nfp_vdpa_vfio_setup(struct nfp_vdpa_dev *device)
 	struct rte_pci_device *pci_dev = device->pci_dev;
 
 	rte_pci_device_name(&pci_dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
-	ret = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
+	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
 			&device->iommu_group);
 	if (ret <= 0)
 		return -1;
 
-	device->vfio_container_fd = rte_vfio_container_create();
+	device->vfio_container_fd = dev_vfio_container_create();
 	if (device->vfio_container_fd < 0)
 		return -1;
 
-	device->vfio_group_fd = rte_vfio_container_group_bind(
+	device->vfio_group_fd = dev_vfio_container_group_bind(
 			device->vfio_container_fd, device->iommu_group);
 	if (device->vfio_group_fd < 0)
 		goto container_destroy;
@@ -146,9 +146,9 @@ nfp_vdpa_vfio_setup(struct nfp_vdpa_dev *device)
 	return 0;
 
 group_unbind:
-	rte_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
+	dev_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
 container_destroy:
-	rte_vfio_container_destroy(device->vfio_container_fd);
+	dev_vfio_container_destroy(device->vfio_container_fd);
 
 	return -1;
 }
@@ -157,8 +157,8 @@ static void
 nfp_vdpa_vfio_teardown(struct nfp_vdpa_dev *device)
 {
 	rte_pci_unmap_device(device->pci_dev);
-	rte_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
-	rte_vfio_container_destroy(device->vfio_container_fd);
+	dev_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
+	dev_vfio_container_destroy(device->vfio_container_fd);
 }
 
 static int
@@ -173,7 +173,7 @@ nfp_vdpa_dma_do_unmap(struct rte_vhost_memory *mem,
 	for (i = 0; i < times; i++) {
 		region = &mem->regions[i];
 
-		ret = rte_vfio_container_dma_unmap(vfio_container_fd,
+		ret = dev_vfio_container_dma_unmap(vfio_container_fd,
 				region->host_user_addr, region->guest_phys_addr,
 				region->size);
 		if (ret < 0) {
@@ -197,7 +197,7 @@ nfp_vdpa_dma_do_map(struct rte_vhost_memory *mem,
 	for (i = 0; i < times; i++) {
 		region = &mem->regions[i];
 
-		ret = rte_vfio_container_dma_map(vfio_container_fd,
+		ret = dev_vfio_container_dma_map(vfio_container_fd,
 				region->host_user_addr, region->guest_phys_addr,
 				region->size);
 		if (ret < 0) {
@@ -282,7 +282,7 @@ nfp_vdpa_relay_vring_free(struct nfp_vdpa_dev *device,
 
 		size = RTE_ALIGN_CEIL(vring_size(vring.size, rte_mem_page_size()),
 				rte_mem_page_size());
-		rte_vfio_container_dma_unmap(device->vfio_container_fd,
+		dev_vfio_container_dma_unmap(device->vfio_container_fd,
 				(uint64_t)(uintptr_t)device->hw.m_vring[i].desc,
 				m_vring_iova, size);
 
@@ -315,7 +315,7 @@ nfp_vdpa_relay_vring_alloc(struct nfp_vdpa_dev *device)
 
 		vring_init(&vdpa_hw->m_vring[i], vring.size, vring_buf, page_size);
 
-		ret = rte_vfio_container_dma_map(device->vfio_container_fd,
+		ret = dev_vfio_container_dma_map(device->vfio_container_fd,
 				(uint64_t)(uintptr_t)vring_buf, m_vring_iova, size);
 		if (ret != 0) {
 			DRV_VDPA_LOG(ERR, "vDPA vring relay dma map failed.");
drivers/vdpa/sfc/sfc_vdpa.c +8 -8
index eda111954f..c65f716a15 100644
@@ -12,7 +12,7 @@
 #include <rte_errno.h>
 #include <rte_kvargs.h>
 #include <rte_string_fns.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_vhost.h>
 
 #include "efx.h"
@@ -74,13 +74,13 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 
 	rte_pci_device_name(&dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
 
-	sva->vfio_container_fd = rte_vfio_container_create();
+	sva->vfio_container_fd = dev_vfio_container_create();
 	if (sva->vfio_container_fd < 0)	{
 		sfc_vdpa_err(sva, "failed to create VFIO container");
 		goto fail_container_create;
 	}
 
-	rc = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
+	rc = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
 				    &sva->iommu_group_num);
 	if (rc <= 0) {
 		sfc_vdpa_err(sva, "failed to get IOMMU group for %s : %s",
@@ -89,7 +89,7 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 	}
 
 	sva->vfio_group_fd =
-		rte_vfio_container_group_bind(sva->vfio_container_fd,
+		dev_vfio_container_group_bind(sva->vfio_container_fd,
 					      sva->iommu_group_num);
 	if (sva->vfio_group_fd < 0) {
 		sfc_vdpa_err(sva,
@@ -109,7 +109,7 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 	return 0;
 
 fail_pci_map_device:
-	if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
+	if (dev_vfio_container_group_unbind(sva->vfio_container_fd,
 					sva->iommu_group_num) != 0) {
 		sfc_vdpa_err(sva,
 			     "failed to unbind IOMMU group %d from container %d",
@@ -118,7 +118,7 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 
 fail_group_bind:
 fail_get_group_num:
-	if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
+	if (dev_vfio_container_destroy(sva->vfio_container_fd) != 0) {
 		sfc_vdpa_err(sva, "failed to destroy container %d",
 			     sva->vfio_container_fd);
 	}
@@ -132,14 +132,14 @@ sfc_vdpa_vfio_teardown(struct sfc_vdpa_adapter *sva)
 {
 	rte_pci_unmap_device(sva->pdev);
 
-	if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
+	if (dev_vfio_container_group_unbind(sva->vfio_container_fd,
 					    sva->iommu_group_num) != 0) {
 		sfc_vdpa_err(sva,
 			     "failed to unbind IOMMU group %d from container %d",
 			     sva->iommu_group_num, sva->vfio_container_fd);
 	}
 
-	if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
+	if (dev_vfio_container_destroy(sva->vfio_container_fd) != 0) {
 		sfc_vdpa_err(sva,
 			     "failed to destroy container %d",
 			     sva->vfio_container_fd);
drivers/vdpa/sfc/sfc_vdpa_hw.c +6 -6
index 7e43719f53..65050b9640 100644
@@ -6,7 +6,7 @@
 
 #include <rte_common.h>
 #include <rte_errno.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_vhost.h>
 
 #include "efx.h"
@@ -64,7 +64,7 @@ sfc_vdpa_dma_alloc(struct sfc_vdpa_adapter *sva, const char *name,
 	mcdi_iova = SFC_VDPA_DEFAULT_MCDI_IOVA;
 
 	for (;;) {
-		ret = rte_vfio_container_dma_map(sva->vfio_container_fd,
+		ret = dev_vfio_container_dma_map(sva->vfio_container_fd,
 						 (uint64_t)mz->addr, mcdi_iova,
 						 mcdi_buff_size);
 		if (ret == 0)
@@ -98,7 +98,7 @@ sfc_vdpa_dma_free(struct sfc_vdpa_adapter *sva, efsys_mem_t *esmp)
 
 	sfc_vdpa_log_init(sva, "name=%s", esmp->esm_mz->name);
 
-	ret = rte_vfio_container_dma_unmap(sva->vfio_container_fd,
+	ret = dev_vfio_container_dma_unmap(sva->vfio_container_fd,
 					   (uint64_t)esmp->esm_base,
 					   esmp->esm_addr, sva->mcdi_buff_size);
 	if (ret < 0)
@@ -140,7 +140,7 @@ sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *ops_data, bool do_map)
 		mem_reg = &vhost_mem->regions[i];
 
 		if (do_map) {
-			rc = rte_vfio_container_dma_map(vfio_container_fd,
+			rc = dev_vfio_container_dma_map(vfio_container_fd,
 						mem_reg->host_user_addr,
 						mem_reg->guest_phys_addr,
 						mem_reg->size);
@@ -151,7 +151,7 @@ sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *ops_data, bool do_map)
 				goto failed_vfio_dma_map;
 			}
 		} else {
-			rc = rte_vfio_container_dma_unmap(vfio_container_fd,
+			rc = dev_vfio_container_dma_unmap(vfio_container_fd,
 						mem_reg->host_user_addr,
 						mem_reg->guest_phys_addr,
 						mem_reg->size);
@@ -171,7 +171,7 @@ sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *ops_data, bool do_map)
 failed_vfio_dma_map:
 	for (j = 0; j < i; j++) {
 		mem_reg = &vhost_mem->regions[j];
-		rte_vfio_container_dma_unmap(vfio_container_fd,
+		dev_vfio_container_dma_unmap(vfio_container_fd,
 					     mem_reg->host_user_addr,
 					     mem_reg->guest_phys_addr,
 					     mem_reg->size);
lib/eal/freebsd/eal.c +40 -33

171 lines not on this page · raw message

lib/eal/include/dev_vfio.h renamed from lib/eal/include/rte_vfio.h +29 -29

198 lines not on this page · raw message

lib/eal/include/meson.build +1 -1
index 9282143918..8d3a6d5e00 100644
@@ -60,7 +60,7 @@ headers += files(
 driver_sdk_headers = files(
         'bus_driver.h',
         'dev_driver.h',
-        'rte_vfio.h',
+        'dev_vfio.h',
 )
 
 # special case install the generic headers, since they go in a subdir
lib/eal/linux/eal.c +3 -3
index 17977baedc..d63edb4192 100644
@@ -41,7 +41,7 @@
 #include <rte_bus.h>
 #include <rte_version.h>
 #include <malloc_heap.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include <telemetry_internal.h>
 #include <eal_export.h>
@@ -771,7 +771,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (rte_vfio_enable()) {
+	if (dev_vfio_enable()) {
 		rte_eal_init_alert("Cannot init VFIO");
 		rte_errno = EAGAIN;
 		goto err_out;
@@ -985,7 +985,7 @@ rte_eal_cleanup(void)
 
 	rte_service_finalize();
 	eal_bus_cleanup();
-	rte_vfio_cleanup();
+	dev_vfio_cleanup();
 	rte_mp_channel_cleanup();
 	rte_eal_alarm_cleanup();
 	rte_trace_save();
lib/eal/linux/eal_vfio.c +61 -61

389 lines not on this page · raw message

lib/eal/linux/eal_vfio_mp_sync.c +3 -3
index 22136f2e8b..ae1c8b40b9 100644
@@ -8,7 +8,7 @@
 
 #include <rte_errno.h>
 #include <rte_log.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_eal.h>
 
 #include "eal_private.h"
@@ -34,7 +34,7 @@ vfio_mp_primary(const struct rte_mp_msg *msg, const void *peer)
 	case SOCKET_REQ_GROUP:
 		r->req = SOCKET_REQ_GROUP;
 		r->group_num = m->group_num;
-		fd = rte_vfio_get_group_fd(m->group_num);
+		fd = dev_vfio_get_group_fd(m->group_num);
 		if (fd < 0 && fd != -ENOENT)
 			r->result = SOCKET_ERR;
 		else if (fd == -ENOENT)
@@ -49,7 +49,7 @@ vfio_mp_primary(const struct rte_mp_msg *msg, const void *peer)
 		break;
 	case SOCKET_REQ_CONTAINER:
 		r->req = SOCKET_REQ_CONTAINER;
-		fd = rte_vfio_get_container_fd();
+		fd = dev_vfio_get_container_fd();
 		if (fd < 0)
 			r->result = SOCKET_ERR;
 		else {
lib/eal/windows/eal.c +7 -7
index b8771d4d85..d59ce9331f 100644
@@ -24,7 +24,7 @@
 #include <eal_options.h>
 #include <eal_private.h>
 #include <rte_service_component.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "eal_firmware.h"
 #include "eal_hugepages.h"
@@ -152,9 +152,9 @@ rte_eal_cleanup(void)
 	return 0;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_cleanup)
 void
-rte_vfio_cleanup(void)
+dev_vfio_cleanup(void)
 {
 }
 
@@ -459,9 +459,9 @@ eal_asprintf(char **buffer, const char *format, ...)
 	return ret;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_map)
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_dma_map)
 int
-rte_vfio_container_dma_map(__rte_unused int container_fd,
+dev_vfio_container_dma_map(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
 			__rte_unused uint64_t iova,
 			__rte_unused uint64_t len)
@@ -470,9 +470,9 @@ rte_vfio_container_dma_map(__rte_unused int container_fd,
 	return -1;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_unmap)
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_dma_unmap)
 int
-rte_vfio_container_dma_unmap(__rte_unused int container_fd,
+dev_vfio_container_dma_unmap(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
 			__rte_unused uint64_t iova,
 			__rte_unused uint64_t len)
lib/vhost/vhost_user.c +8 -8
index 020c993b29..35aa70dffc 100644
@@ -42,7 +42,7 @@
 #include <rte_common.h>
 #include <rte_malloc.h>
 #include <rte_log.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_errno.h>
 
 #include "iotlb.h"
@@ -191,7 +191,7 @@ async_dma_map_region(struct virtio_net *dev, struct rte_vhost_mem_region *reg, b
 			continue;
 
 		if (do_map) {
-			ret = rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD,
+			ret = dev_vfio_container_dma_map(DEV_VFIO_DEFAULT_CONTAINER_FD,
 					page->host_user_addr,
 					page->host_iova,
 					page->size);
@@ -216,7 +216,7 @@ async_dma_map_region(struct virtio_net *dev, struct rte_vhost_mem_region *reg, b
 				return -1;
 			}
 		} else {
-			ret = rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD,
+			ret = dev_vfio_container_dma_unmap(DEV_VFIO_DEFAULT_CONTAINER_FD,
 					page->host_user_addr,
 					page->host_iova,
 					page->size);
@@ -267,7 +267,7 @@ free_all_mem_regions(struct virtio_net *dev)
 	if (!dev || !dev->mem)
 		return;
 
-	if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+	if (dev->async_copy && dev_vfio_is_enabled("vfio"))
 		async_dma_map(dev, false);
 
 	for (i = 0; i < VHOST_MEMORY_MAX_NREGIONS; i++) {
@@ -1564,7 +1564,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev,
 		dev->mem->nregions++;
 	}
 
-	if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+	if (dev->async_copy && dev_vfio_is_enabled("vfio"))
 		async_dma_map(dev, true);
 
 	if (vhost_user_postcopy_register(dev, main_fd, ctx) < 0)
@@ -1750,7 +1750,7 @@ vhost_user_add_mem_reg(struct virtio_net **pdev,
 
 	dev->mem->nregions++;
 
-	if (dev->async_copy && rte_vfio_is_enabled("vfio")) {
+	if (dev->async_copy && dev_vfio_is_enabled("vfio")) {
 		if (async_dma_map_region(dev, reg, true) < 0)
 			goto free_new_region_no_dma;
 	}
@@ -1791,7 +1791,7 @@ vhost_user_add_mem_reg(struct virtio_net **pdev,
 	return RTE_VHOST_MSG_RESULT_OK;
 
 free_new_region:
-	if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+	if (dev->async_copy && dev_vfio_is_enabled("vfio"))
 		async_dma_map_region(dev, reg, false);
 free_new_region_no_dma:
 	remove_guest_pages(dev, reg);
@@ -1827,7 +1827,7 @@ vhost_user_rem_mem_reg(struct virtio_net **pdev,
 		if (region->userspace_addr == current_region->guest_user_addr
 			&& region->guest_phys_addr == current_region->guest_phys_addr
 			&& region->memory_size == current_region->size) {
-			if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+			if (dev->async_copy && dev_vfio_is_enabled("vfio"))
 				async_dma_map_region(dev, current_region, false);
 			if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))
 				vhost_user_iotlb_cache_remove(dev,
Signature · 1 line
2.52.0
#270 lore raw

PATCH v17 9/26 bus/pci: rename mismatching error labels

In reply to Anatoly Burakov

Currently, there are two VFIO map functions - primary and secondary - that use a very similar goto error pattern. However, the label names are confusing.

Specifically, for primary, we have three error labels: vfio_res (release VFIO resource), vfio_dev_fd (close the fd), and map (unmap all the mapped regions). For secondary, there is vfio_dev (close the fd), and vfio_dev_fd (unmap all mapped regions).

For consistency, align secondary process function's error labels to match semantics of how they work in primary process function.

---
 drivers/bus/pci/linux/pci_vfio.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/bus/pci/linux/pci_vfio.c +7 -7
index 71afc383e6..3e87e759f5 100644
@@ -968,7 +968,7 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 
 	ret = pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info);
 	if (ret)
-		goto err_vfio_dev;
+		goto err_vfio_dev_fd;
 
 	/* map BARs */
 	maps = vfio_res->maps;
@@ -979,14 +979,14 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 			if (ret < 0) {
 				PCI_LOG(ERR, "%s sparse mapping BAR%i failed: %s",
 					pci_addr, i, strerror(errno));
-				goto err_vfio_dev_fd;
+				goto err_map;
 			}
 		} else {
 			ret = pci_vfio_mmap_bar(vfio_dev_fd, vfio_res, i, MAP_FIXED);
 			if (ret < 0) {
 				PCI_LOG(ERR, "%s mapping BAR%i failed: %s",
 					pci_addr, i, strerror(errno));
-				goto err_vfio_dev_fd;
+				goto err_map;
 			}
 		}
 
@@ -995,17 +995,17 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 
 	/* we need save vfio_dev_fd, so it can be used during release */
 	if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd))
-		goto err_vfio_dev_fd;
+		goto err_map;
 	if (rte_intr_dev_fd_set(dev->vfio_req_intr_handle, vfio_dev_fd))
-		goto err_vfio_dev_fd;
+		goto err_map;
 
 	return 0;
-err_vfio_dev_fd:
+err_map:
 	for (j = 0; j < i; j++) {
 		if (maps[j].addr)
 			pci_unmap_resource(maps[j].addr, maps[j].size);
 	}
-err_vfio_dev:
+err_vfio_dev_fd:
 	dev_vfio_release_device(rte_pci_get_sysfs_path(),
 			pci_addr, vfio_dev_fd);
 	return -1;
Signature · 1 line
2.52.0
#271 lore raw

PATCH v17 10/26 vfio: split get device info from setup

In reply to Anatoly Burakov

Currently, setup gets device info as part of setup, while the separate get device info API also calls setup if the fd is zero. Untangle these two APIs and make each do one thing, and adjust all existing callers.

---
 drivers/bus/cdx/cdx_vfio.c        | 12 ++++++++--
 drivers/bus/pci/linux/pci_vfio.c  | 18 ++++++++++----
 drivers/bus/platform/platform.c   |  9 ++++++-
 drivers/crypto/bcmfs/bcmfs_vfio.c |  8 ++++++-
 lib/eal/freebsd/eal.c             | 12 ++++++++--
 lib/eal/include/dev_vfio.h        | 23 +++++++-----------
 lib/eal/linux/eal_vfio.c          | 40 +++++++++----------------------
 7 files changed, 68 insertions(+), 54 deletions(-)
drivers/bus/cdx/cdx_vfio.c +10 -2
index 02a34d6f18..531e4ccc8d 100644
@@ -401,10 +401,14 @@ cdx_vfio_map_resource_primary(struct rte_cdx_device *dev)
 		return -1;
 
 	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
-				    &vfio_dev_fd, &device_info);
+				    &vfio_dev_fd);
 	if (ret)
 		return ret;
 
+	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+	if (ret)
+		goto err_vfio_dev_fd;
+
 	/* allocate vfio_res and get region info */
 	vfio_res = rte_zmalloc("VFIO_RES", sizeof(*vfio_res), 0);
 	if (vfio_res == NULL) {
@@ -510,10 +514,14 @@ cdx_vfio_map_resource_secondary(struct rte_cdx_device *dev)
 	}
 
 	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
-					&vfio_dev_fd, &device_info);
+					&vfio_dev_fd);
 	if (ret)
 		return ret;
 
+	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+	if (ret)
+		goto err_vfio_dev_fd;
+
 	/* map MMIO regions */
 	maps = vfio_res->maps;
 
drivers/bus/pci/linux/pci_vfio.c +14 -4
index 3e87e759f5..0363a4a6c5 100644
@@ -753,10 +753,14 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 			loc->domain, loc->bus, loc->devid, loc->function);
 
 	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-					&vfio_dev_fd, &device_info);
+					&vfio_dev_fd);
 	if (ret)
 		return ret;
 
+	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+	if (ret)
+		goto err_vfio_dev_fd;
+
 	if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd))
 		goto err_vfio_dev_fd;
 
@@ -962,10 +966,14 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 	}
 
 	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-					&vfio_dev_fd, &device_info);
+					&vfio_dev_fd);
 	if (ret)
 		return ret;
 
+	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+	if (ret)
+		goto err_vfio_dev_fd;
+
 	ret = pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info);
 	if (ret)
 		goto err_vfio_dev_fd;
@@ -1195,12 +1203,14 @@ pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,
 		if (vfio_dev_fd < 0) {
 			return -1;
 		} else if (vfio_dev_fd == 0) {
-			if (dev_vfio_get_device_info(rte_pci_get_sysfs_path(), pci_addr,
-				&vfio_dev_fd, &device_info) != 0)
+			if (dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
+				&vfio_dev_fd) != 0)
 				return -1;
 			/* save vfio_dev_fd so it can be used during release */
 			if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd) != 0)
 				return -1;
+			if (dev_vfio_get_device_info(vfio_dev_fd, &device_info) != 0)
+				return -1;
 
 			if (pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info) != 0)
 				return -1;
drivers/bus/platform/platform.c +8 -1
index 9d7df9be80..950306e2d9 100644
@@ -292,12 +292,19 @@ device_setup(struct rte_platform_device *pdev)
 	const char *name = pdev->name;
 	int ret;
 
-	ret = dev_vfio_setup_device(PLATFORM_BUS_DEVICES_PATH, name, &pdev->dev_fd, &dev_info);
+	ret = dev_vfio_setup_device(PLATFORM_BUS_DEVICES_PATH, name, &pdev->dev_fd);
 	if (ret) {
 		PLATFORM_LOG_LINE(ERR, "failed to setup %s", name);
 		return -ENODEV;
 	}
 
+	ret = dev_vfio_get_device_info(pdev->dev_fd, &dev_info);
+	if (ret) {
+		PLATFORM_LOG_LINE(ERR, "failed to get device info for %s", name);
+		ret = -ENODEV;
+		goto out;
+	}
+
 	/* This is an extra check to confirm that platform device was initialized
 	 * by a kernel vfio-platform driver. On kernels that predate vfio-platform
 	 * driver this flag obviously does not exist. In such scenarios this
drivers/crypto/bcmfs/bcmfs_vfio.c +7 -1
index 053af0d227..ad244d9756 100644
@@ -25,12 +25,18 @@ vfio_map_dev_obj(const char *path, const char *dev_obj,
 	struct vfio_device_info d_info = { .argsz = sizeof(d_info) };
 	struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
 
-	ret = dev_vfio_setup_device(path, dev_obj, dev_fd, &d_info);
+	ret = dev_vfio_setup_device(path, dev_obj, dev_fd);
 	if (ret) {
 		BCMFS_LOG(ERR, "VFIO Setting for device failed");
 		return ret;
 	}
 
+	ret = dev_vfio_get_device_info(*dev_fd, &d_info);
+	if (ret) {
+		BCMFS_LOG(ERR, "VFIO Getting device info failed");
+		goto map_failed;
+	}
+
 	/* getting device region info*/
 	ret = ioctl(*dev_fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info);
 	if (ret < 0) {
lib/eal/freebsd/eal.c +10 -2
index e35aae2540..b2d902f060 100644
@@ -823,8 +823,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_setup_device)
 int
 dev_vfio_setup_device(__rte_unused const char *sysfs_base,
 		      __rte_unused const char *dev_addr,
-		      __rte_unused int *vfio_dev_fd,
-		      __rte_unused struct vfio_device_info *device_info)
+		      __rte_unused int *vfio_dev_fd)
 {
 	rte_errno = ENOTSUP;
 	return -1;
@@ -957,3 +956,12 @@ dev_vfio_container_dma_unmap(__rte_unused int container_fd,
 	rte_errno = ENOTSUP;
 	return -1;
 }
+
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_get_device_info)
+int
+dev_vfio_get_device_info(__rte_unused int vfio_dev_fd,
+		__rte_unused struct vfio_device_info *device_info)
+{
+	rte_errno = ENOTSUP;
+	return -1;
+}
lib/eal/include/dev_vfio.h +8 -15
index d0f741061e..099a35aa0e 100644
@@ -55,10 +55,7 @@ struct vfio_device_info;
  *   device location.
  *
  * @param vfio_dev_fd
- *   VFIO fd.
- *
- * @param device_info
- *   Device information.
+ *   Pointer to VFIO fd, will be set to the opened device fd on success.
  *
  * @return
  *   0 on success.
@@ -67,7 +64,7 @@ struct vfio_device_info;
  */
 __rte_internal
 int dev_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
-		int *vfio_dev_fd, struct vfio_device_info *device_info);
+		int *vfio_dev_fd);
 
 /**
  * @internal
@@ -193,19 +190,16 @@ dev_vfio_get_group_num(const char *sysfs_base,
  * @internal
  * Get device information.
  *
+ * This function retrieves VFIO device information from an already opened
+ * device. The device must be opened with `dev_vfio_setup_device()` first.
+ *
  * This function is only relevant to Linux and will return an error on BSD.
  *
- * @param sysfs_base
- *   sysfs path prefix.
- *
- * @param dev_addr
- *   device location.
- *
  * @param vfio_dev_fd
- *   VFIO fd.
+ *   VFIO device fd (must be a valid, already opened fd).
  *
  * @param device_info
- *   Device information.
+ *   Pointer to device information structure to be filled.
  *
  * @return
  *   0 on success.
@@ -213,8 +207,7 @@ dev_vfio_get_group_num(const char *sysfs_base,
  */
 __rte_internal
 int
-dev_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
-		int *vfio_dev_fd, struct vfio_device_info *device_info);
+dev_vfio_get_device_info(int vfio_dev_fd, struct vfio_device_info *device_info);
 
 /**
  * @internal
lib/eal/linux/eal_vfio.c +11 -29
index ea7e028cfa..0a7e3e9c9b 100644
@@ -772,7 +772,7 @@ dev_vfio_clear_group(int vfio_group_fd)
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_setup_device)
 int
 dev_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
-		int *vfio_dev_fd, struct vfio_device_info *device_info)
+		int *vfio_dev_fd)
 {
 	struct vfio_group_status group_status = {
 			.argsz = sizeof(group_status)
@@ -994,7 +994,7 @@ dev_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 		*vfio_dev_fd = ioctl(vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD,
 				     dev);
 		if (*vfio_dev_fd >= 0)
-			goto dev_get_info;
+			goto out;
 	}
 
 	/* get a file descriptor for the device */
@@ -1011,18 +1011,8 @@ dev_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 		return -1;
 	}
 
-	/* test and setup the device */
-dev_get_info:
-	ret = ioctl(*vfio_dev_fd, VFIO_DEVICE_GET_INFO, device_info);
-	if (ret) {
-		EAL_LOG(ERR, "%s cannot get device info, "
-				"error %i (%s)", dev_addr, errno,
-				strerror(errno));
-		close(*vfio_dev_fd);
-		close(vfio_group_fd);
-		dev_vfio_clear_group(vfio_group_fd);
-		return -1;
-	}
+	/* device is now set up */
+out:
 	vfio_group_device_get(vfio_group_fd);
 
 	return 0;
@@ -1249,8 +1239,7 @@ vfio_set_iommu_type(int vfio_container_fd)
 
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_get_device_info)
 int
-dev_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
-		int *vfio_dev_fd, struct vfio_device_info *device_info)
+dev_vfio_get_device_info(int vfio_dev_fd, struct vfio_device_info *device_info)
 {
 	int ret;
 
@@ -1259,21 +1248,14 @@ dev_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
 		return -1;
 	}
 
-	if (device_info == NULL || *vfio_dev_fd < 0)
+	if (device_info == NULL || vfio_dev_fd < 0)
 		return -1;
 
-	if (*vfio_dev_fd == 0) {
-		ret = dev_vfio_setup_device(sysfs_base, dev_addr,
-				vfio_dev_fd, device_info);
-		if (ret)
-			return -1;
-	} else {
-		ret = ioctl(*vfio_dev_fd, VFIO_DEVICE_GET_INFO, device_info);
-		if (ret) {
-			EAL_LOG(ERR, "%s cannot get device info, error %i (%s)",
-					dev_addr, errno, strerror(errno));
-			return -1;
-		}
+	ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_INFO, device_info);
+	if (ret) {
+		EAL_LOG(ERR, "Cannot get device info, error %i (%s)",
+				errno, strerror(errno));
+		return -1;
 	}
 
 	return 0;
Signature · 1 line
2.52.0
#272 lore raw

Re: [PATCH v17 10/26] vfio: split get device info from setup

Quoted 89 lines · Anatoly Burakov

Currently, setup gets device info as part of setup, while the separate get device info API also calls setup if the fd is zero. Untangle these two APIs and make each do one thing, and adjust all existing callers.

---
 drivers/bus/cdx/cdx_vfio.c        | 12 ++++++++--
 drivers/bus/pci/linux/pci_vfio.c  | 18 ++++++++++----
 drivers/bus/platform/platform.c   |  9 ++++++-
 drivers/crypto/bcmfs/bcmfs_vfio.c |  8 ++++++-
 lib/eal/freebsd/eal.c             | 12 ++++++++--
 lib/eal/include/dev_vfio.h        | 23 +++++++-----------
 lib/eal/linux/eal_vfio.c          | 40 +++++++++----------------------
 7 files changed, 68 insertions(+), 54 deletions(-)
drivers/bus/cdx/cdx_vfio.c +10 -2
index 02a34d6f18..531e4ccc8d 100644
@@ -401,10 +401,14 @@ cdx_vfio_map_resource_primary(struct rte_cdx_device *dev)
                return -1;
 
        ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
-                                   &vfio_dev_fd, &device_info);
+                                   &vfio_dev_fd);
        if (ret)
                return ret;
 
+       ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+       if (ret)
+               goto err_vfio_dev_fd;
+
        /* allocate vfio_res and get region info */
        vfio_res = rte_zmalloc("VFIO_RES", sizeof(*vfio_res), 0);
        if (vfio_res == NULL) {
@@ -510,10 +514,14 @@ cdx_vfio_map_resource_secondary(struct rte_cdx_device *dev)
        }
 
        ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
-                                       &vfio_dev_fd, &device_info);
+                                       &vfio_dev_fd);
        if (ret)
                return ret;
 
+       ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+       if (ret)
+               goto err_vfio_dev_fd;
+
        /* map MMIO regions */
        maps = vfio_res->maps;
 
drivers/bus/pci/linux/pci_vfio.c +10 -2
index 3e87e759f5..0363a4a6c5 100644
@@ -753,10 +753,14 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
                        loc->domain, loc->bus, loc->devid, loc->function);
 
        ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-                                       &vfio_dev_fd, &device_info);
+                                       &vfio_dev_fd);
        if (ret)
                return ret;
 
+       ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+       if (ret)
+               goto err_vfio_dev_fd;
+
        if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd))
                goto err_vfio_dev_fd;
 
@@ -962,10 +966,14 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
        }
 
        ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-                                       &vfio_dev_fd, &device_info);
+                                       &vfio_dev_fd);
        if (ret)
                return ret;
 
+       ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+       if (ret)
+               goto err_vfio_dev_fd;
+
        ret = pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info);
        if (ret)
                goto err_vfio_dev_fd;

drivers/bus/pci/linux/pci_vfio.c pci_vfio_ioport_map(struct rte_pci_device *dev, int bar, · line 1205

Quoted 3 lines
drivers/bus/pci/linux/pci_vfio.c +0 -0
@@ -1195,12 +1203,14 @@ pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,
                if (vfio_dev_fd < 0) {
                        return -1;
                } else if (vfio_dev_fd == 0) {

Not the fault of this patch, but comparing a FD against 0 is a bad sign...

drivers/bus/pci/linux/pci_vfio.c pci_vfio_ioport_map(struct rte_pci_device *dev, int bar, · line 1216

Quoted 13 lines
drivers/bus/pci/linux/pci_vfio.c +4 -2
-                       if (dev_vfio_get_device_info(rte_pci_get_sysfs_path(), pci_addr,
-                               &vfio_dev_fd, &device_info) != 0)
+                       if (dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
+                               &vfio_dev_fd) != 0)
                                return -1;
                        /* save vfio_dev_fd so it can be used during release */
                        if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd) != 0)
                                return -1;
+                       if (dev_vfio_get_device_info(vfio_dev_fd, &device_info) != 0)
+                               return -1;
 
                        if (pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info) != 0)
                                return -1;

And we have various leaks in case VFIO fails...

I'll make a note to fix this later as this is already present, unless you can have a look.

Signature · 1 line
David Marchand
#273 lore raw

Re: [PATCH v17 10/26] vfio: split get device info from setup

Quoted 26 lines · David Marchand
Quoted 7 lines · Anatoly Burakov

Currently, setup gets device info as part of setup, while the separate get device info API also calls setup if the fd is zero. Untangle these two APIs and make each do one thing, and adjust all existing callers.

---

Not the fault of this patch, but comparing a FD against 0 is a bad sign...

Quoted 11 lines
drivers/bus/pci/linux/pci_vfio.c +4 -2
-                       if (dev_vfio_get_device_info(rte_pci_get_sysfs_path(), pci_addr,
-                               &vfio_dev_fd, &device_info) != 0)
+                       if (dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
+                               &vfio_dev_fd) != 0)
                                 return -1;
                         /* save vfio_dev_fd so it can be used during release */
                         if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd) != 0)
                                 return -1;
+                       if (dev_vfio_get_device_info(vfio_dev_fd, &device_info) != 0)
+                               return -1;
Quoted 8 lines
Quoted 2 lines
                         if (pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info) != 0)
                                 return -1;

And we have various leaks in case VFIO fails...

I'll make a note to fix this later as this is already present, unless you can have a look.

Yeah, this whole "save fd in interrupt handle" is a bit suspect, I didn't want to touch that :D I can have a look later, but not as part of this patchset obviously.

Signature · 2 lines
Thanks,
Anatoly
#274 lore raw

PATCH v17 11/26 vfio: add container device assignment API

In reply to Anatoly Burakov

Currently, VFIO has explicit group bind API's, but the way they're used is such that no one actually cares about VFIO groups, and the real goal of everyone using VFIO group bind API is to bind devices to particular VFIO container, such that when dev_vfio_setup_device call eventually comes, VFIO will pick up the correct container.

To remove dependency on group API's, add a new "container assign device" API call that will do the same thing, but will not depend on managing VFIO group fd's.

---
 lib/eal/freebsd/eal.c      | 10 ++++++++++
 lib/eal/include/dev_vfio.h | 26 ++++++++++++++++++++++++++
 lib/eal/linux/eal_vfio.c   | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+)
lib/eal/freebsd/eal.c +10 -0
index b2d902f060..31340bb49a 100644
@@ -965,3 +965,13 @@ dev_vfio_get_device_info(__rte_unused int vfio_dev_fd,
 	rte_errno = ENOTSUP;
 	return -1;
 }
+
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_assign_device)
+int
+dev_vfio_container_assign_device(__rte_unused int vfio_container_fd,
+		__rte_unused const char *sysfs_base,
+		__rte_unused const char *dev_addr)
+{
+	rte_errno = ENOTSUP;
+	return -1;
+}
lib/eal/include/dev_vfio.h +26 -0
index 099a35aa0e..eb8697e75c 100644
@@ -277,6 +277,32 @@ __rte_internal
 int
 dev_vfio_container_destroy(int container_fd);
 
+/**
+ * @internal
+ *
+ * Assign a device to a VFIO container.
+ *
+ * Doing so will cause `dev_vfio_setup_device()` call to set up the device with
+ * the VFIO container specified in this assign operation.
+ *
+ * This function is only relevant on Linux.
+ *
+ * @param vfio_container_fd
+ *   VFIO container file descriptor.
+ * @param sysfs_base
+ *   Sysfs path prefix.
+ * @param dev_addr
+ *   Device identifier.
+ *
+ * @return
+ *   0 on success.
+ *   <0 on failure.
+ */
+__rte_internal
+int
+dev_vfio_container_assign_device(int vfio_container_fd, const char *sysfs_base,
+		const char *dev_addr);
+
 /**
  * @internal
  * Bind a IOMMU group to a container.
lib/eal/linux/eal_vfio.c +32 -0
index 0a7e3e9c9b..ae53d95de5 100644
@@ -2161,6 +2161,38 @@ dev_vfio_container_destroy(int container_fd)
 	return 0;
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_assign_device)
+int
+dev_vfio_container_assign_device(int vfio_container_fd, const char *sysfs_base,
+		const char *dev_addr)
+{
+	int iommu_group_num;
+	int ret;
+
+	ret = dev_vfio_get_group_num(sysfs_base, dev_addr, &iommu_group_num);
+	if (ret < 0) {
+		EAL_LOG(ERR, "Cannot get IOMMU group number for device %s",
+			dev_addr);
+		return -1;
+	} else if (ret == 0) {
+		EAL_LOG(ERR,
+			"Device %s is not assigned to any IOMMU group",
+			dev_addr);
+		return -1;
+	}
+
+	ret = dev_vfio_container_group_bind(vfio_container_fd,
+			iommu_group_num);
+	if (ret < 0) {
+		EAL_LOG(ERR,
+			"Cannot bind IOMMU group %d for device %s",
+			iommu_group_num, dev_addr);
+		return -1;
+	}
+
+	return 0;
+}
+
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_group_bind)
 int
 dev_vfio_container_group_bind(int container_fd, int iommu_group_num)
Signature · 1 line
2.52.0
#275 lore raw

PATCH v17 12/26 net/nbl: do not use VFIO group bind API

In reply to Anatoly Burakov

The NBL driver currently uses group bind API, but it is using it only to get group fd and nothing else. In context of NBL driver, this is the only usage of VFIO API's in the driver, and it is not necessary to use it for what NBL driver is trying to accomplish.

Use a direct open() call instead, store the group fd in common structure, and find group fd's opened earlier to prevent us from opening the same group fd twice.

---
 drivers/net/nbl/nbl_common/nbl_userdev.c  | 63 +++++++++++++++++------
 drivers/net/nbl/nbl_common/nbl_userdev.h  |  1 +
 drivers/net/nbl/nbl_include/nbl_include.h |  1 +
 3 files changed, 50 insertions(+), 15 deletions(-)
drivers/net/nbl/nbl_common/nbl_userdev.c +48 -15
index f1522772f5..66ec8a69af 100644
@@ -387,6 +387,28 @@ nbl_userdev_mem_event_callback(enum rte_mem_event type, const void *addr, size_t
 	}
 }
 
+static int
+nbl_open_group_fd(int iommu_group_num)
+{
+	char path[PATH_MAX];
+
+	snprintf(path, sizeof(path), DEV_VFIO_GROUP_FMT, iommu_group_num);
+	return open(path, O_RDWR);
+}
+
+static int
+nbl_find_group_fd(int iommu_group_num)
+{
+	struct nbl_adapter *adapter;
+
+	TAILQ_FOREACH(adapter, &nbl_adapter_list, next) {
+		if (adapter->common.iommu_group_num == iommu_group_num)
+			return adapter->common.groupfd;
+	}
+
+	return -1;
+}
+
 static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 {
 	const struct rte_pci_device *pci_dev = adapter->pci_dev;
@@ -400,6 +422,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	u64 dma_limit = NBL_USERDEV_DMA_LIMIT;
 	int ret, container_create = 0, container_set = 0;
 	int vfio_group_fd, container = nbl_default_container;
+	bool new_group = false;
 
 	rte_pci_device_name(&pci_dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
 	snprintf(pathname, sizeof(pathname),
@@ -424,11 +447,18 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	}
 
 	NBL_LOG(DEBUG, "nbl vfio container %d", container);
-	vfio_group_fd = dev_vfio_container_group_bind(container, common->iommu_group_num);
+	rte_mcfg_mem_read_lock();
+	vfio_group_fd = nbl_find_group_fd(common->iommu_group_num);
+	rte_mcfg_mem_read_unlock();
+	if (vfio_group_fd < 0) {
+		vfio_group_fd = nbl_open_group_fd(common->iommu_group_num);
+		new_group = true;
+	}
 	if (vfio_group_fd < 0) {
 		NBL_LOG(ERR, "nbl vfio group bind failed, %d", vfio_group_fd);
 		goto free_container;
 	}
+	common->groupfd = vfio_group_fd;
 
 	/* check if the group is viable */
 	ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_STATUS, &group_status);
@@ -517,13 +547,13 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 close_fd:
 	close(common->devfd);
 unregister_mem_event:
-	if (nbl_group_count == 1) {
+	if (container_set && nbl_group_count == 1) {
 		rte_mcfg_mem_read_lock();
 		rte_mem_event_callback_unregister(NBL_USERDEV_EVENT_CLB_NAME, NULL);
 		rte_mcfg_mem_read_unlock();
 	}
 free_dma_map:
-	if (nbl_group_count == 1) {
+	if (container_set && nbl_group_count == 1) {
 		rte_mcfg_mem_read_lock();
 		nbl_userdev_dma_free();
 		rte_mcfg_mem_read_unlock();
@@ -534,8 +564,8 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 		nbl_group_count--;
 	}
 free_group:
-	close(vfio_group_fd);
-	dev_vfio_clear_group(vfio_group_fd);
+	if (new_group)
+		close(vfio_group_fd);
 free_container:
 	if (container_create)
 		dev_vfio_container_destroy(container);
@@ -546,21 +576,24 @@ static int nbl_mdev_unmap_device(struct nbl_adapter *adapter)
 {
 	struct nbl_common_info *common = &adapter->common;
 	int vfio_group_fd, ret;
+	bool last_group_user;
 
 	rte_mcfg_mem_read_lock();
 	TAILQ_REMOVE(&nbl_adapter_list, adapter, next);
 	close(common->devfd);
-	vfio_group_fd = dev_vfio_container_group_bind(nbl_default_container,
-						      common->iommu_group_num);
+	common->devfd = -1;
+	vfio_group_fd = common->groupfd;
+	last_group_user = nbl_find_group_fd(common->iommu_group_num) < 0;
 	NBL_LOG(DEBUG, "close vfio_group_fd %d", vfio_group_fd);
-	ret = ioctl(vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, &nbl_default_container);
-	if (ret)
-		NBL_LOG(ERR, "unset container, error %i (%s) %d",
-			errno, strerror(errno), ret);
-	nbl_group_count--;
-	ret = dev_vfio_container_group_unbind(nbl_default_container, common->iommu_group_num);
-	if (ret)
-		NBL_LOG(ERR, "vfio container group unbind failed %d", ret);
+	if (last_group_user) {
+		ret = ioctl(vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, &nbl_default_container);
+		if (ret)
+			NBL_LOG(ERR, "unset container, error %i (%s) %d",
+				errno, strerror(errno), ret);
+		nbl_group_count--;
+		close(vfio_group_fd);
+		common->groupfd = -1;
+	}
 	if (!nbl_group_count) {
 		rte_mem_event_callback_unregister(NBL_USERDEV_EVENT_CLB_NAME, NULL);
 		nbl_userdev_dma_free();
drivers/net/nbl/nbl_common/nbl_userdev.h +1 -0
index 2221e19c67..1ebc86baf6 100644
@@ -11,6 +11,7 @@
 #define NBL_USERDEV_INIT_COMMON(common) do {		\
 	typeof(common) _comm = (common);		\
 	_comm->devfd = -1;				\
+	_comm->groupfd = -1;				\
 	_comm->eventfd = -1;				\
 	_comm->specific_dma = false;			\
 	_comm->dma_set_msb = false;			\
drivers/net/nbl/nbl_include/nbl_include.h +1 -0
index eeae6a3301..ba99b9f8e7 100644
@@ -132,6 +132,7 @@ struct nbl_common_info {
 	u16 vsi_id;
 	u16 instance_id;
 	int devfd;
+	int groupfd;
 	int eventfd;
 	int ifindex;
 	int iommu_group_num;
Signature · 1 line
2.52.0
#276 lore raw

PATCH v17 13/26 net/ntnic: use container device assignment API

In reply to Anatoly Burakov

The NTNIC driver uses VFIO group bind/unbind functionality for container device assignment purposes. Use the new container device assignment API instead to provide clearer semantics.

---
 drivers/net/ntnic/ntnic_vfio.c | 30 +++++++++---------------------
 1 file changed, 9 insertions(+), 21 deletions(-)
drivers/net/ntnic/ntnic_vfio.c +9 -21
index 8489a59859..cacd81643f 100644
@@ -28,7 +28,6 @@ nt_vfio_vf_num(const struct rte_pci_device *pdev)
 /* Internal API */
 struct vfio_dev {
 	int container_fd;
-	int group_fd;
 	int dev_fd;
 	uint64_t iova_addr;
 };
@@ -50,7 +49,6 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 {
 	int ret;
 	char devname[RTE_DEV_NAME_MAX_LEN] = { 0 };
-	int iommu_group_num;
 	int vf_num;
 	struct vfio_dev *vfio;
 
@@ -66,14 +64,9 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 	}
 
 	vfio->dev_fd = -1;
-	vfio->group_fd = -1;
 	vfio->iova_addr = START_VF_IOVA;
 
 	rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
-	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), devname, &iommu_group_num);
-	if (ret <= 0)
-		return -1;
-
 	if (vf_num == 0) {
 		/* use default container for pf0 */
 		vfio->container_fd = DEV_VFIO_DEFAULT_CONTAINER_FD;
@@ -86,17 +79,14 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 				"VFIO device setup failed. VFIO container creation failed.");
 			return -1;
 		}
-	}
+		ret = dev_vfio_container_assign_device(vfio->container_fd,
+				rte_pci_get_sysfs_path(), devname);
+		if (ret < 0) {
+			NT_LOG(ERR, NTNIC,
+				"VFIO device setup failed. Assign device to container failed.");
+			goto err;
+		}
 
-	vfio->group_fd = dev_vfio_container_group_bind(vfio->container_fd, iommu_group_num);
-
-	if (vfio->group_fd < 0) {
-		NT_LOG(ERR, NTNIC,
-			"VFIO device setup failed. VFIO container group bind failed.");
-		goto err;
-	}
-
-	if (vf_num > 0) {
 		if (rte_pci_map_device(dev)) {
 			NT_LOG(ERR, NTNIC,
 				"Map VFIO device failed. is the vfio-pci driver loaded?");
@@ -106,10 +96,8 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 
 	vfio->dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
 
-	NT_LOG(DBG, NTNIC,
-		"%s: VFIO id=%d, dev_fd=%d, container_fd=%d, group_fd=%d, iommu_group_num=%d",
-		dev->name, vf_num, vfio->dev_fd, vfio->container_fd, vfio->group_fd,
-		iommu_group_num);
+	NT_LOG(DBG, NTNIC, "%s: VFIO id=%d, dev_fd=%d, container_fd=%d",
+		dev->name, vf_num, vfio->dev_fd, vfio->container_fd);
 
 	return vf_num;
 
Signature · 1 line
2.52.0
#277 lore raw

PATCH v17 14/26 vdpa/ifc: use container device assignment API

In reply to Anatoly Burakov

The IFC vDPA driver uses VFIO group bind/unbind functionality for container device assignment purposes. Use the new container device assignment API instead to provide clearer semantics. Since group API is no longer used after these changes, remove its implementation.

---
 drivers/vdpa/ifc/ifcvf_vdpa.c | 34 +++-------------------------------
 1 file changed, 3 insertions(+), 31 deletions(-)
drivers/vdpa/ifc/ifcvf_vdpa.c +3 -31
index 36d06f1e3f..04ed2052d3 100644
@@ -58,7 +58,6 @@ struct ifcvf_internal {
 	struct ifcvf_hw hw;
 	int configured;
 	int vfio_container_fd;
-	int vfio_group_fd;
 	int vfio_dev_fd;
 	rte_thread_t tid; /* thread for notify relay */
 	rte_thread_t intr_tid; /* thread for config space change interrupt relay */
@@ -174,28 +173,19 @@ ifcvf_vfio_setup(struct ifcvf_internal *internal)
 {
 	struct rte_pci_device *dev = internal->pdev;
 	char devname[RTE_DEV_NAME_MAX_LEN] = {0};
-	int iommu_group_num;
-	int i, ret;
+	int i;
 
 	internal->vfio_dev_fd = -1;
-	internal->vfio_group_fd = -1;
 	internal->vfio_container_fd = -1;
 
 	rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
-	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), devname,
-			&iommu_group_num);
-	if (ret <= 0) {
-		DRV_LOG(ERR, "%s failed to get IOMMU group", devname);
-		return -1;
-	}
 
 	internal->vfio_container_fd = dev_vfio_container_create();
 	if (internal->vfio_container_fd < 0)
 		return -1;
 
-	internal->vfio_group_fd = dev_vfio_container_group_bind(
-			internal->vfio_container_fd, iommu_group_num);
-	if (internal->vfio_group_fd < 0)
+	if (dev_vfio_container_assign_device(internal->vfio_container_fd,
+			rte_pci_get_sysfs_path(), devname) < 0)
 		goto err;
 
 	if (rte_pci_map_device(dev))
@@ -1213,22 +1203,6 @@ ifcvf_set_features(int vid)
 	return 0;
 }
 
-static int
-ifcvf_get_vfio_group_fd(int vid)
-{
-	struct rte_vdpa_device *vdev;
-	struct internal_list *list;
-
-	vdev = rte_vhost_get_vdpa_device(vid);
-	list = find_internal_resource_by_vdev(vdev);
-	if (list == NULL) {
-		DRV_LOG(ERR, "Invalid vDPA device: %p", vdev);
-		return -1;
-	}
-
-	return list->internal->vfio_group_fd;
-}
-
 static int
 ifcvf_get_vfio_device_fd(int vid)
 {
@@ -1474,7 +1448,6 @@ static struct rte_vdpa_dev_ops ifcvf_net_ops = {
 	.set_vring_state = ifcvf_set_vring_state,
 	.set_features = ifcvf_set_features,
 	.migration_done = NULL,
-	.get_vfio_group_fd = ifcvf_get_vfio_group_fd,
 	.get_vfio_device_fd = ifcvf_get_vfio_device_fd,
 	.get_notify_area = ifcvf_get_notify_area,
 	.get_dev_type = ifcvf_get_device_type,
@@ -1605,7 +1578,6 @@ static struct rte_vdpa_dev_ops ifcvf_blk_ops = {
 	.dev_close = ifcvf_dev_close,
 	.set_vring_state = ifcvf_set_vring_state,
 	.migration_done = NULL,
-	.get_vfio_group_fd = ifcvf_get_vfio_group_fd,
 	.get_vfio_device_fd = ifcvf_get_vfio_device_fd,
 	.get_notify_area = ifcvf_get_notify_area,
 	.get_config = ifcvf_blk_get_config,
Signature · 1 line
2.52.0
#278 lore raw

PATCH v17 15/26 vdpa/nfp: use container device assignment API

In reply to Anatoly Burakov

The NFP vDPA driver uses VFIO group bind/unbind functionality for container device assignment purposes. Use the new container device assignment API instead to provide clearer semantics. Since group API is no longer used after these changes, remove its implementation.

---
 drivers/vdpa/nfp/nfp_vdpa.c | 37 +++++--------------------------------
 1 file changed, 5 insertions(+), 32 deletions(-)
drivers/vdpa/nfp/nfp_vdpa.c +5 -32
index 94740e768d..76d7d616a6 100644
@@ -36,9 +36,7 @@ struct nfp_vdpa_dev {
 	struct nfp_vdpa_hw hw;
 
 	int vfio_container_fd;
-	int vfio_group_fd;
 	int vfio_dev_fd;
-	int iommu_group;
 
 	rte_thread_t tid;    /**< Thread for notify relay */
 	int epoll_fd;
@@ -120,33 +118,26 @@ nfp_vdpa_vfio_setup(struct nfp_vdpa_dev *device)
 	struct rte_pci_device *pci_dev = device->pci_dev;
 
 	rte_pci_device_name(&pci_dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
-	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
-			&device->iommu_group);
-	if (ret <= 0)
-		return -1;
 
 	device->vfio_container_fd = dev_vfio_container_create();
 	if (device->vfio_container_fd < 0)
 		return -1;
 
-	device->vfio_group_fd = dev_vfio_container_group_bind(
-			device->vfio_container_fd, device->iommu_group);
-	if (device->vfio_group_fd < 0)
+	ret = dev_vfio_container_assign_device(device->vfio_container_fd,
+			rte_pci_get_sysfs_path(), dev_name);
+	if (ret < 0)
 		goto container_destroy;
 
-	DRV_VDPA_LOG(DEBUG, "The container_fd=%d, group_fd=%d.",
-			device->vfio_container_fd, device->vfio_group_fd);
+	DRV_VDPA_LOG(DEBUG, "container_fd=%d", device->vfio_container_fd);
 
 	ret = rte_pci_map_device(pci_dev);
 	if (ret != 0)
-		goto group_unbind;
+		goto container_destroy;
 
 	device->vfio_dev_fd = rte_intr_dev_fd_get(pci_dev->intr_handle);
 
 	return 0;
 
-group_unbind:
-	dev_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
 container_destroy:
 	dev_vfio_container_destroy(device->vfio_container_fd);
 
@@ -157,7 +148,6 @@ static void
 nfp_vdpa_vfio_teardown(struct nfp_vdpa_dev *device)
 {
 	rte_pci_unmap_device(device->pci_dev);
-	dev_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
 	dev_vfio_container_destroy(device->vfio_container_fd);
 }
 
@@ -1023,22 +1013,6 @@ nfp_vdpa_dev_close(int vid)
 	return 0;
 }
 
-static int
-nfp_vdpa_get_vfio_group_fd(int vid)
-{
-	struct rte_vdpa_device *vdev;
-	struct nfp_vdpa_dev_node *node;
-
-	vdev = rte_vhost_get_vdpa_device(vid);
-	node = nfp_vdpa_find_node_by_vdev(vdev);
-	if (node == NULL) {
-		DRV_VDPA_LOG(ERR, "Invalid vDPA device: %p.", vdev);
-		return -ENODEV;
-	}
-
-	return node->device->vfio_group_fd;
-}
-
 static int
 nfp_vdpa_get_vfio_device_fd(int vid)
 {
@@ -1190,7 +1164,6 @@ struct rte_vdpa_dev_ops nfp_vdpa_ops = {
 	.dev_close = nfp_vdpa_dev_close,
 	.set_vring_state = nfp_vdpa_set_vring_state,
 	.set_features = nfp_vdpa_set_features,
-	.get_vfio_group_fd = nfp_vdpa_get_vfio_group_fd,
 	.get_vfio_device_fd = nfp_vdpa_get_vfio_device_fd,
 	.get_notify_area = nfp_vdpa_get_notify_area,
 };
Signature · 1 line
2.52.0
#279 lore raw

PATCH v17 16/26 vdpa/sfc: use container device assignment API

In reply to Anatoly Burakov

The SFC vDPA driver uses VFIO group bind/unbind functionality for container device assignment purposes. Use the new container device assignment API instead to provide clearer semantics.

---
 drivers/vdpa/sfc/sfc_vdpa.c | 39 +++++++------------------------------
 drivers/vdpa/sfc/sfc_vdpa.h |  2 --
 2 files changed, 7 insertions(+), 34 deletions(-)
drivers/vdpa/sfc/sfc_vdpa.c +7 -32
index c65f716a15..bd5420cfa5 100644
@@ -80,22 +80,12 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 		goto fail_container_create;
 	}
 
-	rc = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
-				    &sva->iommu_group_num);
-	if (rc <= 0) {
-		sfc_vdpa_err(sva, "failed to get IOMMU group for %s : %s",
-			     dev_name, rte_strerror(-rc));
-		goto fail_get_group_num;
-	}
-
-	sva->vfio_group_fd =
-		dev_vfio_container_group_bind(sva->vfio_container_fd,
-					      sva->iommu_group_num);
-	if (sva->vfio_group_fd < 0) {
-		sfc_vdpa_err(sva,
-			     "failed to bind IOMMU group %d to container %d",
-			     sva->iommu_group_num, sva->vfio_container_fd);
-		goto fail_group_bind;
+	rc = dev_vfio_container_assign_device(sva->vfio_container_fd,
+			rte_pci_get_sysfs_path(), dev_name);
+	if (rc < 0) {
+		sfc_vdpa_err(sva, "failed to assign device %s to container %d",
+			     dev_name, sva->vfio_container_fd);
+		goto fail_device_assign;
 	}
 
 	if (rte_pci_map_device(dev) != 0) {
@@ -109,15 +99,7 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 	return 0;
 
 fail_pci_map_device:
-	if (dev_vfio_container_group_unbind(sva->vfio_container_fd,
-					sva->iommu_group_num) != 0) {
-		sfc_vdpa_err(sva,
-			     "failed to unbind IOMMU group %d from container %d",
-			     sva->iommu_group_num, sva->vfio_container_fd);
-	}
-
-fail_group_bind:
-fail_get_group_num:
+fail_device_assign:
 	if (dev_vfio_container_destroy(sva->vfio_container_fd) != 0) {
 		sfc_vdpa_err(sva, "failed to destroy container %d",
 			     sva->vfio_container_fd);
@@ -132,13 +114,6 @@ sfc_vdpa_vfio_teardown(struct sfc_vdpa_adapter *sva)
 {
 	rte_pci_unmap_device(sva->pdev);
 
-	if (dev_vfio_container_group_unbind(sva->vfio_container_fd,
-					    sva->iommu_group_num) != 0) {
-		sfc_vdpa_err(sva,
-			     "failed to unbind IOMMU group %d from container %d",
-			     sva->iommu_group_num, sva->vfio_container_fd);
-	}
-
 	if (dev_vfio_container_destroy(sva->vfio_container_fd) != 0) {
 		sfc_vdpa_err(sva,
 			     "failed to destroy container %d",
drivers/vdpa/sfc/sfc_vdpa.h +0 -2
index 2b843e563d..99a81fd1b0 100644
@@ -70,10 +70,8 @@ struct sfc_vdpa_adapter {
 
 	sfc_vdpa_filter_t		filters;
 
-	int				vfio_group_fd;
 	int				vfio_dev_fd;
 	int				vfio_container_fd;
-	int				iommu_group_num;
 	struct sfc_vdpa_ops_data	*ops_data;
 };
 
Signature · 1 line
2.52.0
#280 lore raw

PATCH v17 17/26 vdpa/mlx5: remove group-related API

In reply to Anatoly Burakov

The mlx5 driver does not use the get_group_fd API provided by vDPA. This API is about to be removed, so remove its mention from mlx5.

---
 drivers/vdpa/mlx5/mlx5_vdpa.c | 1 -
 1 file changed, 1 deletion(-)
drivers/vdpa/mlx5/mlx5_vdpa.c +0 -1
index 11708e2005..1bb5de51b6 100644
@@ -523,7 +523,6 @@ static struct rte_vdpa_dev_ops mlx5_vdpa_ops = {
 	.set_vring_state = mlx5_vdpa_set_vring_state,
 	.set_features = mlx5_vdpa_features_set,
 	.migration_done = NULL,
-	.get_vfio_group_fd = NULL,
 	.get_vfio_device_fd = mlx5_vdpa_get_device_fd,
 	.get_notify_area = mlx5_vdpa_get_notify_area,
 	.get_stats_names = mlx5_vdpa_get_stats_names,
Signature · 1 line
2.52.0
#281 lore raw

PATCH v17 18/26 vhost: remove group-related API from driver

In reply to Anatoly Burakov

The vDPA driver API has "get_vfio_group_fd" in its ops structure, but no driver is using it any more, as better API's were added and implemented. Remove this API from vDPA ops structure.

---
 doc/guides/prog_guide/vhost_lib.rst    | 4 ----
 doc/guides/rel_notes/deprecation.rst   | 4 ----
 doc/guides/rel_notes/release_26_11.rst | 3 +++
 lib/vhost/vdpa_driver.h                | 3 ---
 4 files changed, 3 insertions(+), 11 deletions(-)
doc/guides/prog_guide/vhost_lib.rst +0 -4
index 345a621716..99355b8afd 100644
@@ -471,10 +471,6 @@ Finally, a set of device ops is defined for device specific operations:
 
   Called to allow the device to respond to RARP sending.
 
-* ``get_vfio_group_fd``
-
-   Called to get the VFIO group fd of the device.
-
 * ``get_vfio_device_fd``
 
   Called to get the VFIO device fd of the device.
doc/guides/rel_notes/deprecation.rst +0 -4
index 8a82c815e3..e4a754d037 100644
@@ -29,10 +29,6 @@ Deprecation Notices
   Use the ``-S <service-corelist>`` parameter instead
   to specify the cores to be used for background services in DPDK.
 
-* vdpa: The vDPA driver API will no longer offer ``get_vfio_group_fd``
-  as part of its internal API. All drivers will be adjusted
-  to use the new unified VFIO container device assignment API.
-
 * rte_atomicNN_xxx: These APIs do not take memory order parameter. This does
   not allow for writing optimized code for all the CPU architectures supported
   in DPDK. DPDK has adopted the atomic operations from
doc/guides/rel_notes/release_26_11.rst +3 -0
index 71d12a4398..006b1d3e5a 100644
@@ -117,6 +117,9 @@ ABI Changes
   These functions are now available only to EAL and drivers,
   and are no longer part of the public ABI.
 
+* vdpa: Removed ``get_vfio_group_fd`` from ``struct rte_vdpa_dev_ops``.
+  vDPA drivers should now use the VFIO container device assignment API.
+
 
 Known Issues
 ------------
lib/vhost/vdpa_driver.h +0 -3
index 42392a0d14..c7b9be09fb 100644
@@ -50,9 +50,6 @@ struct rte_vdpa_dev_ops {
 	/** Destination operations when migration done */
 	int (*migration_done)(int vid);
 
-	/** Get the vfio group fd */
-	int (*get_vfio_group_fd)(int vid);
-
 	/** Get the vfio device fd */
 	int (*get_vfio_device_fd)(int vid);
 
Signature · 1 line
2.52.0
#282 lore raw

PATCH v17 19/26 vfio: remove group-based API

In reply to Anatoly Burakov

All drivers have been adjusted to not use the VFIO group API directly and instead rely on container device assignment model, so the group API is no longer useful and can be removed.

---
 lib/eal/freebsd/eal.c            | 34 ---------------
 lib/eal/include/dev_vfio.h       | 72 --------------------------------
 lib/eal/linux/eal_vfio.c         | 47 ++++++++++-----------
 lib/eal/linux/eal_vfio.h         |  2 +
 lib/eal/linux/eal_vfio_mp_sync.c |  2 +-
 5 files changed, 26 insertions(+), 131 deletions(-)
lib/eal/freebsd/eal.c +0 -34
index 31340bb49a..b607ea50b8 100644
@@ -867,14 +867,6 @@ dev_vfio_noiommu_is_enabled(void)
 	return 0;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_clear_group)
-int
-dev_vfio_clear_group(__rte_unused int vfio_group_fd)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_get_group_num)
 int
 dev_vfio_get_group_num(__rte_unused const char *sysfs_base,
@@ -893,14 +885,6 @@ dev_vfio_get_container_fd(void)
 	return -1;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_get_group_fd)
-int
-dev_vfio_get_group_fd(__rte_unused int iommu_group_num)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_create)
 int
 dev_vfio_container_create(void)
@@ -917,24 +901,6 @@ dev_vfio_container_destroy(__rte_unused int container_fd)
 	return -1;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_group_bind)
-int
-dev_vfio_container_group_bind(__rte_unused int container_fd,
-		__rte_unused int iommu_group_num)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_group_unbind)
-int
-dev_vfio_container_group_unbind(__rte_unused int container_fd,
-		__rte_unused int iommu_group_num)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_dma_map)
 int
 dev_vfio_container_dma_map(__rte_unused int container_fd,
lib/eal/include/dev_vfio.h +0 -72

90 lines not on this page · raw message

lib/eal/linux/eal_vfio.c +23 -24

151 lines not on this page · raw message

lib/eal/linux/eal_vfio.h +2 -0
index 89c4b5ba45..30389fb274 100644
@@ -51,6 +51,8 @@ vfio_set_iommu_type(int vfio_container_fd);
 int
 vfio_get_iommu_type(void);
 
+int vfio_get_group_fd_by_num(int iommu_group_num);
+
 /* check if we have any supported extensions */
 int
 vfio_has_supported_extensions(int vfio_container_fd);
lib/eal/linux/eal_vfio_mp_sync.c +1 -1
index ae1c8b40b9..66341a701a 100644
@@ -34,7 +34,7 @@ vfio_mp_primary(const struct rte_mp_msg *msg, const void *peer)
 	case SOCKET_REQ_GROUP:
 		r->req = SOCKET_REQ_GROUP;
 		r->group_num = m->group_num;
-		fd = dev_vfio_get_group_fd(m->group_num);
+		fd = vfio_get_group_fd_by_num(m->group_num);
 		if (fd < 0 && fd != -ENOENT)
 			r->result = SOCKET_ERR;
 		else if (fd == -ENOENT)
Signature · 1 line
2.52.0
#283 lore raw

PATCH v17 20/26 vfio: cleanup and refactor

In reply to Anatoly Burakov

Currently, VFIO code is a bit of an incoherent mess internally, with API's bleeding into each other, inconsistent returns, and a certain amount of spaghetti stemming from organic growth.

Refactor VFIO code to achieve the following goals:

- Make all error handling consistent, and provide/document rte_errno values returned from API's to indicate various conditions.

- Introduce new "VFIO mode" concept. This new API will tell caller if VFIO is enabled, and whether it is using group API.

- Introduce new "IOMMU mode" concept. This new API will tell caller if IOMMU is enabled or disabled.

- Decouple dev_vfio_setup_device semantics from PCI bus return convention. Currently, when device is not managed by VFIO, dev_vfio_setup_device will return 1, which is bus speak for "skip this device", however VFIO has nothing to do with PCI bus and should not follow its API conventions.

- Perform device setup in device assign, and make device setup use shared code path with device assign and explicitly assuming default container. This is technically not necessary for group mode as device set up is a two-step process in that mode, but coming cdev mode will have a single-step device setup, and it would be easier if the worked the same way under the hood.

- Add device deduplication based on sysfs path and device address.

- Make VFIO internals more readable. Introduce a lot of infrastructure and more explicit validation, rather than over-reliance on sentinel values and implicit assumptions. This will also make it easier to integrate cdev mode down the line, as it will rely on most of this infrastructure.

- Rename internal structs and macros to use vfio_* namespace

This will change behavior of the following functions:

- dev_vfio_setup_device - when the device is not managed by VFIO, the function will now return -1 with rte_errno set to ENODEV
- dev_vfio_get_group_num - when the device is not managed by VFIO, the function will now return -1 with rte_errno set to ENODEV
- dev_vfio_container_destroy - the function will now release and close all group and device resources associated with the container being destroyed by this call
- dev_vfio_noiommu_is_enabled is now using the new IOMMU mode infrastructure rather than reading a sysfs value

All users of dev_vfio_setup_device and dev_vfio_get_group_num have been adjusted to account for API change.

Because the no-IOMMU check now relies on new mode infrastructure, the VFIO initialization now needs to happen before bus scan, as buses depend on no-IOMMU information.

---
 config/arm/meson.build                   |    1 +
 config/meson.build                       |    1 +
 drivers/bus/cdx/cdx_vfio.c               |   17 +-
 drivers/bus/fslmc/fslmc_vfio.c           |    4 +-
 drivers/bus/pci/linux/pci_vfio.c         |   19 +-
 drivers/crypto/bcmfs/bcmfs_vfio.c        |    6 +-
 drivers/net/nbl/nbl_common/nbl_userdev.c |    2 +-
 lib/eal/freebsd/eal.c                    |   14 +
 lib/eal/include/dev_vfio.h               |  276 ++-
 lib/eal/linux/eal.c                      |   15 +-
 lib/eal/linux/eal_vfio.c                 | 2626 ++++++++--------------
 lib/eal/linux/eal_vfio.h                 |  158 +-
 lib/eal/linux/eal_vfio_group.c           |  951 ++++++++
 lib/eal/linux/eal_vfio_mp_sync.c         |   72 +-
 lib/eal/linux/meson.build                |    1 +
 15 files changed, 2324 insertions(+), 1839 deletions(-)
 create mode 100644 lib/eal/linux/eal_vfio_group.c
config/arm/meson.build +1 -0
index 27b549a052..2b73cbef7e 100644
@@ -147,6 +147,7 @@ implementer_cavium = {
     'description': 'Cavium',
     'flags': [
         ['RTE_MAX_VFIO_GROUPS', 128],
+        ['RTE_MAX_VFIO_DEVICES', 256],
         ['RTE_MAX_LCORE', 96],
         ['RTE_MAX_NUMA_NODES', 2]
     ],
config/meson.build +1 -0
index d7f5e55c18..0e6e478fc8 100644
@@ -387,6 +387,7 @@ dpdk_conf.set('RTE_ENABLE_TRACE_FP', get_option('enable_trace_fp'))
 dpdk_conf.set('RTE_PKTMBUF_HEADROOM', get_option('pkt_mbuf_headroom'))
 # values which have defaults which may be overridden
 dpdk_conf.set('RTE_MAX_VFIO_GROUPS', 64)
+dpdk_conf.set('RTE_MAX_VFIO_DEVICES', 256)
 dpdk_conf.set('RTE_DRIVER_MEMPOOL_BUCKET_SIZE_KB', 64)
 dpdk_conf.set('RTE_LIBRTE_DPAA2_USE_PHYS_IOVA', true)
 if get_option('mbuf_refcnt_atomic')
drivers/bus/cdx/cdx_vfio.c +12 -5
index 531e4ccc8d..7ba0937950 100644
@@ -22,6 +22,7 @@
 
 #include <eal_export.h>
 #include <rte_eal_paging.h>
+#include <rte_errno.h>
 #include <rte_malloc.h>
 #include <dev_vfio.h>
 
@@ -402,8 +403,12 @@ cdx_vfio_map_resource_primary(struct rte_cdx_device *dev)
 
 	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
 				    &vfio_dev_fd);
-	if (ret)
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		return ret;
+	}
 
 	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
 	if (ret)
@@ -513,11 +518,13 @@ cdx_vfio_map_resource_secondary(struct rte_cdx_device *dev)
 		return -1;
 	}
 
-	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
-					&vfio_dev_fd);
-	if (ret)
+	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, &vfio_dev_fd);
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		return ret;
-
+	}
 	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
 	if (ret)
 		goto err_vfio_dev_fd;
drivers/bus/fslmc/fslmc_vfio.c +2 -2
index 153e6112db..c2b6ac1f3f 100644
@@ -376,9 +376,9 @@ fslmc_get_group_id(const char *group_name,
 	/* get group number */
 	ret = dev_vfio_get_group_num(SYSFS_FSL_MC_DEVICES,
 			group_name, groupid);
-	if (ret <= 0) {
+	if (ret < 0) {
 		DPAA2_BUS_ERR("Find %s IOMMU group", group_name);
-		if (ret < 0)
+		if (rte_errno != ENODEV)
 			return ret;
 
 		return -EIO;
drivers/bus/pci/linux/pci_vfio.c +13 -6
index 0363a4a6c5..61489922da 100644
@@ -20,6 +20,7 @@
 #include <rte_malloc.h>
 #include <dev_vfio.h>
 #include <rte_eal.h>
+#include <rte_errno.h>
 #include <bus_driver.h>
 #include <rte_spinlock.h>
 #include <rte_tailq.h>
@@ -752,10 +753,13 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 	snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,
 			loc->domain, loc->bus, loc->devid, loc->function);
 
-	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-					&vfio_dev_fd);
-	if (ret)
+	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr, &vfio_dev_fd);
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		return ret;
+	}
 
 	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
 	if (ret)
@@ -965,10 +969,13 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 		return -1;
 	}
 
-	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-					&vfio_dev_fd);
-	if (ret)
+	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr, &vfio_dev_fd);
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		return ret;
+	}
 
 	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
 	if (ret)
drivers/crypto/bcmfs/bcmfs_vfio.c +5 -1
index ad244d9756..0e16af0365 100644
@@ -9,6 +9,7 @@
 #include <sys/mman.h>
 #include <sys/ioctl.h>
 
+#include <rte_errno.h>
 #include <dev_vfio.h>
 
 #include "bcmfs_device.h"
@@ -26,7 +27,10 @@ vfio_map_dev_obj(const char *path, const char *dev_obj,
 	struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
 
 	ret = dev_vfio_setup_device(path, dev_obj, dev_fd);
-	if (ret) {
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		BCMFS_LOG(ERR, "VFIO Setting for device failed");
 		return ret;
 	}
drivers/net/nbl/nbl_common/nbl_userdev.c +1 -1
index 66ec8a69af..9676ef18ae 100644
@@ -429,7 +429,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 		 "%s/%s/", rte_pci_get_sysfs_path(), dev_name);
 
 	ret = dev_vfio_get_group_num(pathname, dev_name, &common->iommu_group_num);
-	if (ret <= 0) {
+	if (ret < 0) {
 		NBL_LOG(ERR, "nbl vfio group number failed");
 		return -1;
 	}
lib/eal/freebsd/eal.c +14 -0
index b607ea50b8..574a3a9fa4 100644
@@ -941,3 +941,17 @@ dev_vfio_container_assign_device(__rte_unused int vfio_container_fd,
 	rte_errno = ENOTSUP;
 	return -1;
 }
+
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_get_mode)
+enum dev_vfio_mode
+dev_vfio_get_mode(void)
+{
+	return DEV_VFIO_MODE_NONE;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_get_iommu_mode)
+enum dev_vfio_iommu_mode
+dev_vfio_get_iommu_mode(void)
+{
+	return DEV_VFIO_IOMMU_MODE_UNKNOWN;
+}
lib/eal/include/dev_vfio.h +197 -79

438 lines not on this page · raw message

lib/eal/linux/eal.c +10 -5
index d63edb4192..722cacdb45 100644
@@ -676,6 +676,16 @@ rte_eal_init(int argc, char **argv)
 		}
 	}
 
+	/*
+	 * VFIO must be initialized before bus scan because buses need to know
+	 * about no-IOMMU mode status.
+	 */
+	if (dev_vfio_enable()) {
+		rte_eal_init_alert("Cannot init VFIO");
+		rte_errno = EAGAIN;
+		goto err_out;
+	}
+
 	if (rte_bus_scan()) {
 		rte_eal_init_alert("Cannot scan the buses for devices");
 		rte_errno = ENODEV;
@@ -771,11 +781,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (dev_vfio_enable()) {
-		rte_eal_init_alert("Cannot init VFIO");
-		rte_errno = EAGAIN;
-		goto err_out;
-	}
 	/* in secondary processes, memory init may allocate additional fbarrays
 	 * not present in primary processes, so to avoid any potential issues,
 	 * initialize memzones first.
lib/eal/linux/eal_vfio.c +930 -1696

2,391 lines not on this page · raw message

lib/eal/linux/eal_vfio.h +134 -24

158 lines not on this page · raw message

lib/eal/linux/eal_vfio_group.c new file +951 -0

951 lines not on this page · raw message

lib/eal/linux/eal_vfio_mp_sync.c +52 -20

72 lines not on this page · raw message

lib/eal/linux/meson.build +1 -0
index 29ba313218..5ec8eddaa2 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.52.0

Part of the diff is not shown here. View the raw message.

#284 lore raw

Re: [PATCH v17 20/26] vfio: cleanup and refactor

Quoted 44 lines · Anatoly Burakov
lib/eal/include/dev_vfio.h +20 -2
index f2dbf46481..c62d38e524 100644
@@ -18,6 +18,7 @@
 #include <stdint.h>
 
 #include <rte_compat.h>
+#include <rte_common.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -29,8 +30,6 @@ extern "C" {
 #define DEV_VFIO_CONTAINER_PATH "/dev/vfio/vfio"
 #define DEV_VFIO_GROUP_FMT "/dev/vfio/%u"
 #define DEV_VFIO_NOIOMMU_GROUP_FMT "/dev/vfio/noiommu-%u"
-#define DEV_VFIO_NOIOMMU_MODE      \
-       "/sys/module/vfio/parameters/enable_unsafe_noiommu_mode"
 
 #endif /* RTE_EXEC_ENV_LINUX */
 
@@ -39,28 +38,64 @@ struct vfio_device_info;
 
 #define DEV_VFIO_DEFAULT_CONTAINER_FD (-1)
 
+/**
+ * @enum dev_vfio_mode
+ * Enumeration of VFIO operational modes.
+ *
+ * These modes define how VFIO devices are accessed.
+ *
+ * - DEV_VFIO_MODE_NONE: VFIO is not enabled.
+ * - DEV_VFIO_MODE_GROUP: Legacy group mode.
+ */
+enum dev_vfio_mode {
+       DEV_VFIO_MODE_NONE = 0, /**< VFIO not enabled */
+       DEV_VFIO_MODE_GROUP,    /**< Group mode */
+};
+
+/**
+ * @enum dev_vfio_iommu_mode
+ * Enumeration of VFIO IOMMU protection modes.
+ *
+ * These modes define whether devices are protected by an IOMMU.

lib/eal/include/dev_vfio.h struct vfio_device_info; · line 69

Quoted 10 lines
lib/eal/include/dev_vfio.h +10 -0
+ *
+ * - DEV_VFIO_IOMMU_MODE_UNKNOWN: IOMMU mode has not been determined.
+ * - DEV_VFIO_IOMMU_MODE_SAFE: Devices are protected by an IOMMU.
+ * - DEV_VFIO_IOMMU_MODE_UNSAFE: Devices are not protected by an IOMMU.
+ */
+enum dev_vfio_iommu_mode {
+       DEV_VFIO_IOMMU_MODE_UNKNOWN = 0, /**< IOMMU mode not determined */
+       DEV_VFIO_IOMMU_MODE_SAFE,        /**< IOMMU protection enabled */
+       DEV_VFIO_IOMMU_MODE_UNSAFE,      /**< IOMMU protection disabled */
+};

My two cents.

This "safety" mode is ambiguous (for example, the bus/fslmc change looks wrong, as I reported earlier).

The main concern for drivers is the "class" (physical, virtual) of addresses. The noiommu notion was simple in that drivers understood they had to handle physical addresses.

There is some other concern about iommu capability that is not captured in the new API.
Take a look at the PCI bus for example, where some decision is taken on a DMA mask.

In the end, it may mean that the whole iommu class discovery (that impacts IOVA mode) should get revisited too... ?

At least, with an *internal* VFIO API, we can revisit more easily in the future, so those comments are not blocking the series.

Signature · 1 line
David Marchand
#285 lore raw

Re: [PATCH v17 20/26] vfio: cleanup and refactor

Quoted 59 lines · David Marchand
Quoted 44 lines · Anatoly Burakov
lib/eal/include/dev_vfio.h +20 -2
index f2dbf46481..c62d38e524 100644
@@ -18,6 +18,7 @@
  #include <stdint.h>
 
  #include <rte_compat.h>
+#include <rte_common.h>
 
  #ifdef __cplusplus
  extern "C" {
@@ -29,8 +30,6 @@ extern "C" {
  #define DEV_VFIO_CONTAINER_PATH "/dev/vfio/vfio"
  #define DEV_VFIO_GROUP_FMT "/dev/vfio/%u"
  #define DEV_VFIO_NOIOMMU_GROUP_FMT "/dev/vfio/noiommu-%u"
-#define DEV_VFIO_NOIOMMU_MODE      \
-       "/sys/module/vfio/parameters/enable_unsafe_noiommu_mode"
 
  #endif /* RTE_EXEC_ENV_LINUX */
 
@@ -39,28 +38,64 @@ struct vfio_device_info;
 
  #define DEV_VFIO_DEFAULT_CONTAINER_FD (-1)
 
+/**
+ * @enum dev_vfio_mode
+ * Enumeration of VFIO operational modes.
+ *
+ * These modes define how VFIO devices are accessed.
+ *
+ * - DEV_VFIO_MODE_NONE: VFIO is not enabled.
+ * - DEV_VFIO_MODE_GROUP: Legacy group mode.
+ */
+enum dev_vfio_mode {
+       DEV_VFIO_MODE_NONE = 0, /**< VFIO not enabled */
+       DEV_VFIO_MODE_GROUP,    /**< Group mode */
+};
+
+/**
+ * @enum dev_vfio_iommu_mode
+ * Enumeration of VFIO IOMMU protection modes.
+ *
+ * These modes define whether devices are protected by an IOMMU.

lib/eal/include/dev_vfio.h struct vfio_device_info; · line 69

Quoted 10 lines
lib/eal/include/dev_vfio.h +10 -0
+ *
+ * - DEV_VFIO_IOMMU_MODE_UNKNOWN: IOMMU mode has not been determined.
+ * - DEV_VFIO_IOMMU_MODE_SAFE: Devices are protected by an IOMMU.
+ * - DEV_VFIO_IOMMU_MODE_UNSAFE: Devices are not protected by an IOMMU.
+ */
+enum dev_vfio_iommu_mode {
+       DEV_VFIO_IOMMU_MODE_UNKNOWN = 0, /**< IOMMU mode not determined */
+       DEV_VFIO_IOMMU_MODE_SAFE,        /**< IOMMU protection enabled */
+       DEV_VFIO_IOMMU_MODE_UNSAFE,      /**< IOMMU protection disabled */
+};

My two cents.

Quoted 2 lines

This "safety" mode is ambiguous (for example, the bus/fslmc change looks wrong, as I reported earlier).

Yes, that's a typo. It should've been not wrong!

Quoted 4 lines

The main concern for drivers is the "class" (physical, virtual) of addresses. The noiommu notion was simple in that drivers understood they had to handle physical addresses.

That is arguably still the case. It is the same semantic meaning, just wrapped under a different name because I wanted to signal that using no-iommu mode is bad practice. It's still effectively IOMMU vs no-IOMMU.

Quoted 5 lines

There is some other concern about iommu capability that is not captured in the new API.
Take a look at the PCI bus for example, where some decision is taken on a DMA mask.

Arguably this is not *VFIO* related (it's rather the property of IOMMU) so there is little place for that notion in this API except to group all IOMMU stuff under the same roof, which may or may not be semantically coherent depending on your view of what this API should be.

Quoted 8 lines

In the end, it may mean that the whole iommu class discovery (that impacts IOVA mode) should get revisited too... ?

At least, with an *internal* VFIO API, we can revisit more easily in the future, so those comments are not blocking the series.

We can do all sorts of things now that we are allowed to, yes!

Signature · 2 lines
Thanks,
Anatoly
#286 lore raw

Re: [PATCH v17 20/26] vfio: cleanup and refactor

Quoted 8 lines · Anatoly
Quoted 4 lines

The main concern for drivers is the "class" (physical, virtual) of addresses. The noiommu notion was simple in that drivers understood they had to handle physical addresses.

That is arguably still the case. It is the same semantic meaning, just wrapped under a different name because I wanted to signal that using no-iommu mode is bad practice. It's still effectively IOMMU vs no-IOMMU.

Drivers do not care about this "bad practice".
No user will ever see this.

Most of the code now is generated by AI.
If you mix concerns in API, I am pretty sure the original intent will be lost/distorted and we will just see some funny claims like "such code is unsafe".

Quoted 10 lines
Quoted 5 lines

There is some other concern about iommu capability that is not captured in the new API.
Take a look at the PCI bus for example, where some decision is taken on a DMA mask.

Arguably this is not *VFIO* related (it's rather the property of IOMMU) so there is little place for that notion in this API except to group all IOMMU stuff under the same roof, which may or may not be semantically coherent depending on your view of what this API should be.

Well, yes, but drivers do not care about VFIO in the first place.

We may have a cleaner VFIO API now, but then drivers need to understand it. I just want to preach for a simple API for the drivers, and maybe we are missing an abstraction...

Quoted 10 lines
Quoted 8 lines

In the end, it may mean that the whole iommu class discovery (that impacts IOVA mode) should get revisited too... ?

At least, with an *internal* VFIO API, we can revisit more easily in the future, so those comments are not blocking the series.

We can do all sorts of things now that we are allowed to, yes!

... but ok, I won't insist.
We will see in the future...

Signature · 1 line
David Marchand
#287 lore raw

Re: [PATCH v17 20/26] vfio: cleanup and refactor

Quoted 11 lines · David Marchand
Quoted 8 lines · Anatoly
Quoted 4 lines

The main concern for drivers is the "class" (physical, virtual) of addresses. The noiommu notion was simple in that drivers understood they had to handle physical addresses.

That is arguably still the case. It is the same semantic meaning, just wrapped under a different name because I wanted to signal that using no-iommu mode is bad practice. It's still effectively IOMMU vs no-IOMMU.

Quoted 8 lines

Drivers do not care about this "bad practice".
No user will ever see this.

Most of the code now is generated by AI.
If you mix concerns in API, I am pretty sure the original intent will be lost/distorted and we will just see some funny claims like "such code is unsafe".

Fair enough. I will pick a better name.

Quoted 12 lines
Quoted 11 lines
Quoted 6 lines

There is some other concern about iommu capability that is not captured in the new API.
Take a look at the PCI bus for example, where some decision is taken on a DMA mask.

Arguably this is not *VFIO* related (it's rather the property of IOMMU) so there is little place for that notion in this API except to group all IOMMU stuff under the same roof, which may or may not be semantically coherent depending on your view of what this API should be.

Quoted 7 lines

Well, yes, but drivers do not care about VFIO in the first place.

We may have a cleaner VFIO API now, but then drivers need to understand it. I just want to preach for a simple API for the drivers, and maybe we are missing an abstraction...

We really do miss a generic IOMMU abstraction but the problem is I don't like building abstractions that only have one user (VFIO) and that mix different subsystems into one blob. The one saving grace of such an approach is that this API is no longer public so we're allowed to do whatever and experiment.

I agree that a simpler API is a valid goal, and in fact this refactor/rework is in large part *about* simplifying the container assignment API. The IOMMU stuff really was tacked on at the last minute because I noticed that despite earlier talk about how cdev mode is not going to provide no-IOMMU support, that actually did end up happening, so I added another axis to my API.

We can't make drivers *not care about VFIO* unless we replace the terminology wholesale (containers, cdev/group modes, etc), and arguably while drivers don't care about *internals* of VFIO, some drivers *do* care about VFIO specifically, and the extra stuff in the API is for them. DMA mask isn't really about VFIO because it affects physical addressing ranges too, not just IOVA. So if there is an abstraction here that maps well onto VFIO API *and* the DMA mask, I'm not quite seeing it.

(not saying it's not there, maybe I'm just tunnel visioning on this after having spent so much work on VFIO! I'm all for good suggestions on this front)

Signature · 2 lines
Thanks,
Anatoly
#288 lore raw

PATCH v17 21/26 bus/pci: use the new VFIO IOMMU mode API

In reply to Anatoly Burakov

Use the new VFIO IOMMU mode API to query no-IOMMU status.

---
 drivers/bus/pci/linux/pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/bus/pci/linux/pci.c +1 -1
index af37a65c45..9961f5b2c9 100644
@@ -596,7 +596,7 @@ pci_device_iova_mode(const struct rte_pci_driver *pdrv,
 		static int is_vfio_noiommu_enabled = -1;
 
 		if (is_vfio_noiommu_enabled == -1) {
-			if (dev_vfio_noiommu_is_enabled() == 1)
+			if (dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE)
 				is_vfio_noiommu_enabled = 1;
 			else
 				is_vfio_noiommu_enabled = 0;
Signature · 1 line
2.52.0
#289 lore raw

PATCH v17 22/26 bus/fslmc: use the new VFIO IOMMU mode API

In reply to Anatoly Burakov

FSLMC bus only supports operating in group mode, and relies on no-IOMMU mode checks. Use the new VFIO API's to query no-IOMMU status as well as to protect the bus from initializing in non-group mode.

---
 drivers/bus/fslmc/fslmc_bus.c  | 10 +++++++++-
 drivers/bus/fslmc/fslmc_vfio.c |  2 +-
 2 files changed, 10 insertions(+), 2 deletions(-)
drivers/bus/fslmc/fslmc_bus.c +9 -1
index d55c414ead..aeef49a5ff 100644
@@ -332,6 +332,13 @@ rte_fslmc_scan(void)
 		goto scan_fail;
 	}
 
+	/* for container groups to work, VFIO must be in group mode */
+	if (dev_vfio_get_mode() != DEV_VFIO_MODE_GROUP) {
+		DPAA2_BUS_DEBUG("DPAA2: VFIO not in group mode");
+		ret = -EINVAL;
+		goto scan_fail;
+	}
+
 	ret = fslmc_get_container_group(group_name, &groupid);
 	if (ret != 0)
 		goto scan_fail;
@@ -500,7 +507,8 @@ rte_dpaa2_get_iommu_class(void)
 		return RTE_IOVA_DC;
 
 	/* check if all devices on the bus support Virtual addressing or not */
-	if (fslmc_all_device_support_iova() != 0 && dev_vfio_noiommu_is_enabled() == 0)
+	if (fslmc_all_device_support_iova() != 0 &&
+			dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE)
 		return RTE_IOVA_VA;
 
 	return RTE_IOVA_PA;
drivers/bus/fslmc/fslmc_vfio.c +1 -1
index c2b6ac1f3f..0926ec9349 100644
@@ -204,7 +204,7 @@ fslmc_vfio_add_group(int vfio_group_fd,
 	group->fd = vfio_group_fd;
 	group->groupid = iommu_group_num;
 	rte_strscpy(group->group_name, group_name, sizeof(group->group_name));
-	if (dev_vfio_noiommu_is_enabled() > 0)
+	if (dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE)
 		group->iommu_type = VFIO_NOIOMMU_IOMMU;
 	else
 		group->iommu_type = VFIO_TYPE1_IOMMU;
Signature · 1 line
2.52.0
#290 lore raw

Re: [PATCH v17 22/26] bus/fslmc: use the new VFIO IOMMU mode API

drivers/bus/fslmc/fslmc_bus.c rte_dpaa2_get_iommu_class(void) · line 514

Quoted 10 lines · Anatoly Burakov
drivers/bus/fslmc/fslmc_bus.c +2 -1
@@ -500,7 +507,8 @@ rte_dpaa2_get_iommu_class(void)
                return RTE_IOVA_DC;
 
        /* check if all devices on the bus support Virtual addressing or not */
-       if (fslmc_all_device_support_iova() != 0 && dev_vfio_noiommu_is_enabled() == 0)
+       if (fslmc_all_device_support_iova() != 0 &&
+                       dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE)
                return RTE_IOVA_VA;
 
        return RTE_IOVA_PA;

IA flagged this part:

In fslmc_bus.c, the condition changed from:

```c
/* Old */
if (fslmc_all_device_support_iova() != 0 && dev_vfio_noiommu_is_enabled() == 0)
    return RTE_IOVA_VA;

/* New */
if (fslmc_all_device_support_iova() != 0 &&
        dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE)
    return RTE_IOVA_VA;
```

The old code returned RTE_IOVA_VA when NOIOMMU was **disabled** (== 0), but the new code returns RTE_IOVA_VA when IOMMU mode is **UNSAFE** (i.e., NOIOMMU is enabled).

Looking at dev_vfio_noiommu_is_enabled():

```c
int
dev_vfio_noiommu_is_enabled(void)
{
    return vfio_global_cfg.iommu_mode == DEV_VFIO_IOMMU_MODE_UNSAFE;
}
```

So:
- Old: dev_vfio_noiommu_is_enabled() == 0 → NOIOMMU is NOT enabled → IOMMU is SAFE
- New: dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE → NOIOMMU IS enabled

**This is an inverted condition.** The old code returned RTE_IOVA_VA when IOMMU was safe (NOIOMMU disabled), but the new code returns RTE_IOVA_VA when IOMMU is unsafe (NOIOMMU enabled). This appears to be a correctness bug that will change the IOVA mode selection behavior.

**Suggested fix:** The new condition should likely be:

```c
if (fslmc_all_device_support_iova() != 0 &&
        dev_vfio_get_iommu_mode() != DEV_VFIO_IOMMU_MODE_UNSAFE)
    return RTE_IOVA_VA;
```

Or if the intent was to check for safe mode:

```c
if (fslmc_all_device_support_iova() != 0 &&
        dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_SAFE)
    return RTE_IOVA_VA;
```
Signature · 1 line
David Marchand
#291 lore raw

Re: [PATCH v17 22/26] bus/fslmc: use the new VFIO IOMMU mode API

Quoted 59 lines · David Marchand

drivers/bus/fslmc/fslmc_bus.c rte_dpaa2_get_iommu_class(void) · line 514

Quoted 10 lines · Anatoly Burakov
drivers/bus/fslmc/fslmc_bus.c +2 -1
@@ -500,7 +507,8 @@ rte_dpaa2_get_iommu_class(void)
                 return RTE_IOVA_DC;
 
         /* check if all devices on the bus support Virtual addressing or not */
-       if (fslmc_all_device_support_iova() != 0 && dev_vfio_noiommu_is_enabled() == 0)
+       if (fslmc_all_device_support_iova() != 0 &&
+                       dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE)
                 return RTE_IOVA_VA;
 
         return RTE_IOVA_PA;

IA flagged this part:

In fslmc_bus.c, the condition changed from:

```c
/* Old */
if (fslmc_all_device_support_iova() != 0 && dev_vfio_noiommu_is_enabled() == 0)
     return RTE_IOVA_VA;

/* New */
if (fslmc_all_device_support_iova() != 0 &&
         dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE)
     return RTE_IOVA_VA;
```

The old code returned RTE_IOVA_VA when NOIOMMU was **disabled** (== 0), but the new code returns RTE_IOVA_VA when IOMMU mode is **UNSAFE** (i.e., NOIOMMU is enabled).

Looking at dev_vfio_noiommu_is_enabled():

```c
int
dev_vfio_noiommu_is_enabled(void)
{
     return vfio_global_cfg.iommu_mode == DEV_VFIO_IOMMU_MODE_UNSAFE;
}
```

So:
- Old: dev_vfio_noiommu_is_enabled() == 0 → NOIOMMU is NOT enabled → IOMMU is SAFE
- New: dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE → NOIOMMU IS enabled

**This is an inverted condition.** The old code returned RTE_IOVA_VA when IOMMU was safe (NOIOMMU disabled), but the new code returns RTE_IOVA_VA when IOMMU is unsafe (NOIOMMU enabled). This appears to be a correctness bug that will change the IOVA mode selection behavior.

**Suggested fix:** The new condition should likely be:

```c
if (fslmc_all_device_support_iova() != 0 &&
         dev_vfio_get_iommu_mode() != DEV_VFIO_IOMMU_MODE_UNSAFE)
     return RTE_IOVA_VA;
```
Quoted 7 lines

Or if the intent was to check for safe mode:

```c
if (fslmc_all_device_support_iova() != 0 &&
         dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_SAFE)
     return RTE_IOVA_VA;
```

Yep, a typo.

Signature · 2 lines
Thanks,
Anatoly
#292 lore raw

PATCH v17 23/26 net/hinic3: use the new VFIO IOMMU mode API

In reply to Anatoly Burakov

Use new VFIO IOMMU mode API to query no-IOMMU status.

---
 drivers/net/hinic3/base/hinic3_hwdev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/hinic3/base/hinic3_hwdev.c +2 -1
index 6a6cf44752..e8ad013345 100644
@@ -78,7 +78,8 @@ hinic3_is_vfio_iommu_enable(const struct rte_eth_dev *eth_dev)
 {
 	struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
 
-	return pci_dev->kdrv == RTE_PCI_KDRV_VFIO && dev_vfio_noiommu_is_enabled() != 1;
+	return pci_dev->kdrv == RTE_PCI_KDRV_VFIO &&
+			dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_SAFE;
 }
 
 int
Signature · 1 line
2.52.0
#293 lore raw

PATCH v17 24/26 net/ntnic: use the new VFIO IOMMU mode API

In reply to Anatoly Burakov

Use new VFIO IOMMU mode API to query no-IOMMU status.

---
 drivers/net/ntnic/ntnic_ethdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ntnic/ntnic_ethdev.c +1 -1
index d9744a7d05..79f4dd5279 100644
@@ -2690,7 +2690,7 @@ nthw_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			(pci_dev->device.devargs->data ? pci_dev->device.devargs->data : "NULL"));
 	}
 
-	const int n_dev_vfio_no_io_mmu_enabled = dev_vfio_noiommu_is_enabled();
+	const int n_dev_vfio_no_io_mmu_enabled = dev_vfio_get_iommu_mode() == DEV_VFIO_IOMMU_MODE_UNSAFE;
 	NT_LOG(DBG, NTNIC, "vfio_no_iommu_enabled=%d", n_dev_vfio_no_io_mmu_enabled);
 
 	if (n_dev_vfio_no_io_mmu_enabled) {
Signature · 1 line
2.52.0
#294 lore raw

PATCH v17 25/26 vfio: remove no-IOMMU check API

In reply to Anatoly Burakov

The dev_vfio_noiommu_is_enabled() check has now been replaced by the new IOMMU mode API, so remove it.

---
 lib/eal/freebsd/eal.c      |  7 -------
 lib/eal/include/dev_vfio.h | 14 --------------
 lib/eal/linux/eal_vfio.c   |  7 -------
 3 files changed, 28 deletions(-)
lib/eal/freebsd/eal.c +0 -7
index 574a3a9fa4..62b8e04ea1 100644
@@ -860,13 +860,6 @@ dev_vfio_is_enabled(__rte_unused const char *modname)
 	return 0;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_noiommu_is_enabled)
-int
-dev_vfio_noiommu_is_enabled(void)
-{
-	return 0;
-}
-
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_get_group_num)
 int
 dev_vfio_get_group_num(__rte_unused const char *sysfs_base,
lib/eal/include/dev_vfio.h +0 -14
index c62d38e524..cd7232ccd5 100644
@@ -203,20 +203,6 @@ __rte_internal
 enum dev_vfio_iommu_mode
 dev_vfio_get_iommu_mode(void);
 
-/**
- * @internal
- * Check if VFIO NOIOMMU mode is enabled.
- *
- * This function is only relevant on Linux.
- *
- * @return
- *   1 if enabled.
- *   0 if not enabled or not supported.
- */
-__rte_internal
-int
-dev_vfio_noiommu_is_enabled(void);
-
 /**
  * @internal
  * Parse IOMMU group number for a device.
lib/eal/linux/eal_vfio.c +0 -7
index af48f95d8f..0415c621ea 100644
@@ -1400,13 +1400,6 @@ container_dma_unmap(struct vfio_container *cfg, uint64_t vaddr, uint64_t iova,
 	return ret;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_noiommu_is_enabled)
-int
-dev_vfio_noiommu_is_enabled(void)
-{
-	return vfio_global_cfg.iommu_mode == DEV_VFIO_IOMMU_MODE_UNSAFE;
-}
-
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_create)
 int
 dev_vfio_container_create(void)
Signature · 1 line
2.52.0
#295 lore raw

PATCH v17 26/26 vfio: introduce cdev mode

In reply to Anatoly Burakov

Add support for VFIO cdev (also known as IOMMUFD) API. The group API is now considered legacy in the kernel, and all further development is expected to happen in IOMMUFD infrastructure.

The implementation largely follows the kernel reference code, with most differences from group mode concentrated in how the container and the devices are set up. The VFIO container allocates an "IOAS" (IO address space), maps the memory into that space, and attaches devices to IOAS - there is no IOMMU type discovery at device attach time.

Unlike group mode, the cdev mode is device-centric, and all DMA mappings are made for an IOAS and not into VFIO container itself. As a result, while group mode only maps memory during first device attach, cdev mode can map memory without having any devices attached. However, current VFIO init has moved to before bus scan, because we need VFIO mode information for buses to decide on IOVA mode. DMA memory mapping, however, must be performed after the DPDK memory was already initialized, so we add another internal API to trigger VFIO DMA maps for cdev mode right after memory init.

To assist any future use of VFIO cdev mode for custom behavior, also introduce "get device number" API, which is kind-of-but-not-really similar to the concept of IOMMU group.

---
 doc/guides/linux_gsg/linux_drivers.rst |  30 ++
 doc/guides/rel_notes/release_26_11.rst |   5 +
 lib/eal/freebsd/eal.c                  |  16 +
 lib/eal/include/dev_vfio.h             |  46 +++
 lib/eal/linux/eal.c                    |   7 +
 lib/eal/linux/eal_vfio.c               | 287 ++++++++++++++++-
 lib/eal/linux/eal_vfio.h               |  38 ++-
 lib/eal/linux/eal_vfio_cdev.c          | 420 +++++++++++++++++++++++++
 lib/eal/linux/eal_vfio_mp_sync.c       |  42 +++
 lib/eal/linux/meson.build              |   1 +
 10 files changed, 878 insertions(+), 14 deletions(-)
 create mode 100644 lib/eal/linux/eal_vfio_cdev.c
doc/guides/linux_gsg/linux_drivers.rst +30 -0
index 12e9faf4a2..7dd38a69f8 100644
@@ -133,6 +133,31 @@ For proper operation of VFIO when running DPDK applications as a non-privileged
 For more information, please refer to :ref:`linux_gsg_running_without_root_privileges`.
 
 
+.. _linux_gsg_vfio_modes:
+
+VFIO group and cdev modes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Linux kernel provides two different interfaces for VFIO:
+
+group mode
+   The original interface, based on IOMMU groups.
+   It is accessed through the container device ``/dev/vfio/vfio`` and the per-group devices under ``/dev/vfio/``.
+
+cdev mode
+   The newer interface, based on iommufd.
+   It is accessed through ``/dev/iommu`` and the per-device character devices under ``/dev/vfio/devices/``.
+
+DPDK selects the mode automatically; there is no EAL option to force a particular mode.
+Currently, group mode is preferred and is used whenever the container device ``/dev/vfio/vfio`` is usable.
+Using cdev mode requires ``/dev/iommu`` to be present and accessible.
+
+.. note::
+
+   Using VF tokens in cdev mode requires Linux kernel version 6.17 or later.
+   On older kernels the device is bound without the token, so the kernel should be configured to use group mode if VF token support is required.
+
+
 .. _linux_gsg_vfio_noiommu:
 
 VFIO no-IOMMU mode
@@ -265,6 +290,11 @@ The token will be used for all PF and VF ports within the application.
    Linux versions earlier than version 5.7 do not support the creation of
    virtual functions within the VFIO framework.
 
+.. note::
+
+   When VFIO uses cdev mode, VF tokens require a newer kernel.
+   See :ref:`linux_gsg_vfio_modes` for details.
+
 Troubleshooting VFIO
 ~~~~~~~~~~~~~~~~~~~~
 
doc/guides/rel_notes/release_26_11.rst +5 -0
index 006b1d3e5a..ed56021c83 100644
@@ -55,6 +55,11 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added VFIO cdev (IOMMUFD) mode.**
+
+  Added support for the VFIO character device (cdev) API, also known as IOMMUFD.
+  DPDK now supports both the group mode and the new cdev mode.
+
 
 Removed Items
 -------------
lib/eal/freebsd/eal.c +16 -0
index 62b8e04ea1..257c8dcb15 100644
@@ -853,6 +853,12 @@ dev_vfio_cleanup(void)
 {
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_init_mem)
+int dev_vfio_init_mem(void)
+{
+	return 0;
+}
+
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_is_enabled)
 int
 dev_vfio_is_enabled(__rte_unused const char *modname)
@@ -948,3 +954,13 @@ dev_vfio_get_iommu_mode(void)
 {
 	return DEV_VFIO_IOMMU_MODE_UNKNOWN;
 }
+
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_get_device_num)
+int
+dev_vfio_get_device_num(__rte_unused const char *sysfs_base,
+		__rte_unused const char *dev_addr,
+		__rte_unused int *vfio_device_num)
+{
+	rte_errno = ENOTSUP;
+	return -1;
+}
lib/eal/include/dev_vfio.h +46 -0

76 lines not on this page · raw message

lib/eal/linux/eal.c +7 -0
index 722cacdb45..7cfb253824 100644
@@ -818,6 +818,13 @@ rte_eal_init(int argc, char **argv)
 		goto err_out;
 	}
 
+	/* VFIO memory setup that requires DPDK memory to be available. */
+	if (dev_vfio_init_mem() < 0) {
+		rte_eal_init_alert("Cannot init VFIO memory");
+		rte_errno = EAGAIN;
+		goto err_out;
+	}
+
 	/* register multi-process action callbacks for hotplug after memory init */
 	if (eal_mp_dev_hotplug_init() < 0) {
 		rte_eal_init_alert("failed to register mp callback for hotplug");
lib/eal/linux/eal_vfio.c +277 -10

381 lines not on this page · raw message

lib/eal/linux/eal_vfio.h +34 -4
index fe13e58002..3263f082ca 100644
@@ -50,9 +50,16 @@ struct vfio_device {
 	bool active;
 	enum dev_vfio_mode mode;
 	int fd;
-	int group; /**< back-reference to group list */
-	char *sysfs_base; /**< sysfs path prefix */
-	char *dev_addr;   /**< device address */
+	union {
+		struct {
+			int dev_num;   /**< device number, e.g., X in /dev/vfio/devices/vfioX */
+		};
+		struct {
+			int group; /**< back-reference to group list */
+			char *sysfs_base; /**< sysfs path prefix */
+			char *dev_addr;   /**< device address */
+		};
+	};
 };
 
 /* group mode specific configuration */
@@ -63,13 +70,21 @@ struct vfio_group_config {
 	struct vfio_group groups[RTE_MAX_VFIO_GROUPS];
 };
 
+/* cdev mode specific configuration */
+struct vfio_cdev_config {
+	uint32_t ioas_id;
+};
+
 /* per-container configuration */
 struct vfio_container {
 	bool active;
 	bool dma_setup_done;
 	int container_fd;
 	struct vfio_user_mem_maps mem_maps;
-	struct vfio_group_config group_cfg;
+	union {
+		struct vfio_group_config group_cfg;
+		struct vfio_cdev_config cdev_cfg;
+	};
 	int n_devices;
 	struct vfio_device devices[RTE_MAX_VFIO_DEVICES];
 };
@@ -164,6 +179,17 @@ int vfio_group_setup_iommu(struct vfio_container *cfg);
 int vfio_group_setup_device_fd(const char *dev_addr,
 		struct vfio_group *grp, struct vfio_device *dev);
 
+/* cdev mode functions */
+int vfio_cdev_enable(struct vfio_container *cfg);
+void vfio_cdev_setup_ops(void);
+int vfio_cdev_setup_ioas(struct vfio_container *cfg);
+int vfio_cdev_sync_ioas(struct vfio_container *cfg);
+int vfio_cdev_get_iommufd(void);
+int vfio_cdev_get_device_num(const char *sysfs_base, const char *dev_addr,
+		int *cdev_dev_num);
+struct vfio_device *vfio_cdev_get_dev_by_num(struct vfio_container *cfg, int cdev_dev_num);
+int vfio_cdev_setup_device(struct vfio_container *cfg, struct vfio_device *dev);
+
 #define VFIO_NOIOMMU_MODE_PATH "/sys/module/vfio/parameters/enable_unsafe_noiommu_mode"
 #define VFIO_MEM_EVENT_CLB_NAME "vfio_mem_event_clb"
 #define VFIO_MODNAME "vfio"
@@ -173,6 +199,8 @@ int vfio_group_setup_device_fd(const char *dev_addr,
 #define VFIO_SOCKET_REQ_GROUP 0x200
 #define VFIO_SOCKET_REQ_IOMMU_TYPE 0x400
 #define VFIO_SOCKET_REQ_IOMMU_MODE 0x800
+#define VFIO_SOCKET_REQ_CDEV 0x1000
+#define VFIO_SOCKET_REQ_IOAS_ID 0x2000
 #define VFIO_SOCKET_OK 0x0
 #define VFIO_SOCKET_NO_FD 0x1
 #define VFIO_SOCKET_ERR 0xFF
@@ -183,6 +211,8 @@ struct vfio_mp_param {
 	union {
 		int group_num;
 		int iommu_type_id;
+		int cdev_dev_num;
+		int ioas_id;
 		enum dev_vfio_mode mode;
 		enum dev_vfio_iommu_mode iommu_mode;
 	};
lib/eal/linux/eal_vfio_cdev.c new file +420 -0

420 lines not on this page · raw message

lib/eal/linux/eal_vfio_mp_sync.c +42 -0

48 lines not on this page · raw message

lib/eal/linux/meson.build +1 -0
index 5ec8eddaa2..c164a30b49 100644
@@ -16,6 +16,7 @@ sources += files(
         'eal_thread.c',
         'eal_timer.c',
         'eal_vfio.c',
+        'eal_vfio_cdev.c',
         'eal_vfio_group.c',
         'eal_vfio_mp_sync.c',
 )
Signature · 1 line
2.52.0
#296 lore raw
In reply to Anatoly Burakov
Quoted 75 lines · Anatoly Burakov

This patchset introduces a major refactor of the VFIO subsystem in DPDK to support character device (cdev) interface introduced in Linux kernel, as well as make the API more streamlined and useful. The goal is to simplify device management, improve compatibility, make the code readable, and clarify API.

The following sections outline the key issues addressed by this patchset and the corresponding changes introduced.

1. Only group mode is supported
===============================

Since kernel version 4.14.327 (LTS), VFIO supports the new character device (cdev)-based way of working with VFIO devices (otherwise known as IOMMUFD). This is a device-centric mode and does away with all the complexity regarding groups and IOMMU types, delegating it all to the kernel, and exposes a much simpler interface to userspace. The old group-based implementation will still be around, and will need to be kept in DPDK for compatibility reasons.

To enable this, VFIO is heavily refactored, so that the code can support both modes while relying on (mostly) common infrastructure.

Additionally, new vfio_get_mode API is added for those cases that need some introspection into VFIO's internals, with two modes: group (old-style), and cdev (the new mode).

Historically, no-IOMMU mode was technically a variant of group mode, the distinction is largely irrelevant to the user, as all usages of noiommu checks in our codebase are for deciding whether to use IOVA or PA, not anything to do with managing groups. However, now that upcoming kernel versions will support no-IOMMU for both group, cdev compatibility, and full cdev paths, a new vfio_get_iommu_mode is also added, with two modes: safe (full IOMMU backing), and unsafe (no-IOMMU mode). The naming is chosen explicitly to emphasize that using no-IOMMU mode is not ideal.

2. Custom container assignment API does not map to cdev mode
============================================================

The existing rte_vfio_device_setup/release model is fundamentally incompatible with cdev mode, because for custom container cases, the expected flow is that the user binds the IOMMU group (and thus, implicitly, the device itself) to a specific container using rte_vfio_container_group_bind, whereas this step is not needed for cdev as the device fd is assigned to the container straight away.

Therefore, what we do instead is introduce a new API for container device assignment which, semantically, will assign a device to specified container, so that when it is mapped using rte_pci_map_device, the appropriate container is selected. Under the hood though, we essentially transition to getting device fd straight away at assign stage, so that by the time the PCI bus attempts to map the device, it is already mapped and we just return an fd. There is no "unassign" API because release_device already performs that function.

Because the API is now unified around device assignment, the old group-specific API's can be removed and, where appropriate, reimplemented using new API. There were other users of VFIO which relied on group API but only for convenience purposes; no actual VFIO functionality depended on those API's.

List of removed API's:

* rte_vfio_get_group_fd
* rte_vfio_clear_group
* rte_vfio_container_group_bind (replaced by container assign API)
* rte_vfio_container_group_unbind
* rte_vfio_noiommu_is_enabled (replaced by new mode API)

3. The API responsibilities aren't clear and bleed into each other
==================================================================

Some API's do multiple things at once. In particular:

* rte_vfio_get_device_info will setup the device
* rte_vfio_setup_device will get device info

These API's have been adjusted to do one thing only.

Quoted 7 lines

4. The API does not need to be public
=====================================

The initial idea for exposing VFIO API was to enable userspace applications to directly map memory for DMA, but it turns out that in practice only drivers use this API. Therefore, the entire VFIO API is made internal, driver-only, and is renamed from rte_vfio to dev_vfio.

Thanks for the cleanup!

I am still in the process of reviewing.
Some first comments.

- About patch 1, I am not sure I understand your intention. Without applying it, a conflict appears later in the series.

- Do you know if some Linux capability is needed for using the cdev mode? Did you test this change in (unpriviledged) containers for example?

- It was a ugly/gray area so far, but should we stop exposing an API that do nothing on Windows and FreeBSD?
Especially now that we make it internal.

Drivers calling the VFIO API may be broken/falsely announcing support on other OSes.
I prefer a clear broken build rather than some runtime failure on those OSes the day someone starts testing.

--vfio-intr / --vfio-vf-token EAL options are already Linux only. So EAL common code looks already ready.

There may be one complication on the PCI bus side, with its calls to vfio_dma_map/unmap but it seems doable (implement per OS dma_map/dma_unmap internal symbols ?).

Something like:
https://github.com/david-marchand/dpdk/commit/cc77440883b0d38b842d6c520292b540eabb78c4
https://github.com/david-marchand/dpdk/commit/8f426089f949e0694e5201193be88de673c4283d

- Probably for later, but I see one more constant added in config/meson.build. All VFIO objects seems to be local (or exchanged over MP messages).

How much effort would it take to remove those constants in config/meson.build? I am thinking about RTE_MAX_VFIO_CONTAINERS, RTE_MAX_VFIO_GROUPS, RTE_MAX_VFIO_DEVICES, EAL_VFIO_MAX_USER_MEM_MAPS.

- rte_eal_check_module() only user is VFIO.
No opensource project use it.
It could be removed in the future.

Signature · 1 line
David Marchand
#297 lore raw
Quoted 77 lines · David Marchand
Quoted 75 lines · Anatoly Burakov

This patchset introduces a major refactor of the VFIO subsystem in DPDK to support character device (cdev) interface introduced in Linux kernel, as well as make the API more streamlined and useful. The goal is to simplify device management, improve compatibility, make the code readable, and clarify API.

The following sections outline the key issues addressed by this patchset and the corresponding changes introduced.

1. Only group mode is supported
===============================

Since kernel version 4.14.327 (LTS), VFIO supports the new character device (cdev)-based way of working with VFIO devices (otherwise known as IOMMUFD). This is a device-centric mode and does away with all the complexity regarding groups and IOMMU types, delegating it all to the kernel, and exposes a much simpler interface to userspace. The old group-based implementation will still be around, and will need to be kept in DPDK for compatibility reasons.

To enable this, VFIO is heavily refactored, so that the code can support both modes while relying on (mostly) common infrastructure.

Additionally, new vfio_get_mode API is added for those cases that need some introspection into VFIO's internals, with two modes: group (old-style), and cdev (the new mode).

Historically, no-IOMMU mode was technically a variant of group mode, the distinction is largely irrelevant to the user, as all usages of noiommu checks in our codebase are for deciding whether to use IOVA or PA, not anything to do with managing groups. However, now that upcoming kernel versions will support no-IOMMU for both group, cdev compatibility, and full cdev paths, a new vfio_get_iommu_mode is also added, with two modes: safe (full IOMMU backing), and unsafe (no-IOMMU mode). The naming is chosen explicitly to emphasize that using no-IOMMU mode is not ideal.

2. Custom container assignment API does not map to cdev mode
============================================================

The existing rte_vfio_device_setup/release model is fundamentally incompatible with cdev mode, because for custom container cases, the expected flow is that the user binds the IOMMU group (and thus, implicitly, the device itself) to a specific container using rte_vfio_container_group_bind, whereas this step is not needed for cdev as the device fd is assigned to the container straight away.

Therefore, what we do instead is introduce a new API for container device assignment which, semantically, will assign a device to specified container, so that when it is mapped using rte_pci_map_device, the appropriate container is selected. Under the hood though, we essentially transition to getting device fd straight away at assign stage, so that by the time the PCI bus attempts to map the device, it is already mapped and we just return an fd. There is no "unassign" API because release_device already performs that function.

Because the API is now unified around device assignment, the old group-specific API's can be removed and, where appropriate, reimplemented using new API. There were other users of VFIO which relied on group API but only for convenience purposes; no actual VFIO functionality depended on those API's.

List of removed API's:

* rte_vfio_get_group_fd
* rte_vfio_clear_group
* rte_vfio_container_group_bind (replaced by container assign API)
* rte_vfio_container_group_unbind
* rte_vfio_noiommu_is_enabled (replaced by new mode API)

3. The API responsibilities aren't clear and bleed into each other
==================================================================

Some API's do multiple things at once. In particular:

* rte_vfio_get_device_info will setup the device
* rte_vfio_setup_device will get device info

These API's have been adjusted to do one thing only.

Quoted 8 lines
Quoted 7 lines

4. The API does not need to be public
=====================================

The initial idea for exposing VFIO API was to enable userspace applications to directly map memory for DMA, but it turns out that in practice only drivers use this API. Therefore, the entire VFIO API is made internal, driver-only, and is renamed from rte_vfio to dev_vfio.

Hi David!

Quoted 9 lines

Thanks for the cleanup!

I am still in the process of reviewing.
Some first comments.

- About patch 1, I am not sure I understand your intention. Without applying it, a conflict appears later in the series.

It's because the first patch is queued for next-net but our CI doesn't seem to be capable of rebasing on top of that tree yet, so as a workaround (to get compile checks etc.) I added it to the first patch series. The cover letter states that.

Quoted 3 lines

- Do you know if some Linux capability is needed for using the cdev mode? Did you test this change in (unpriviledged) containers for example?

I did not test such a scenario as I do not have a setup for this. I know we've done internal testing but not for unprivileged/non-root scenarios.

Quoted 3 lines

- It was a ugly/gray area so far, but should we stop exposing an API that do nothing on Windows and FreeBSD?
Especially now that we make it internal.

I am not 100% sure why this is necessary to do - my best guess is that some of the drivers call into VFIO API which means it needs to at least link correctly. I would gladly remove all such references, but I would suggest this to be future work and out of scope for this patchset. Now that we're removed the ABI surface we can do whatever!

Quoted 5 lines

Drivers calling the VFIO API may be broken/falsely announcing support on other OSes.
I prefer a clear broken build rather than some runtime failure on those OSes the day someone starts testing.

I agree.

Quoted 11 lines

--vfio-intr / --vfio-vf-token EAL options are already Linux only. So EAL common code looks already ready.

There may be one complication on the PCI bus side, with its calls to vfio_dma_map/unmap but it seems doable (implement per OS dma_map/dma_unmap internal symbols ?).

Something like:
https://github.com/david-marchand/dpdk/commit/cc77440883b0d38b842d6c520292b540eabb78c4
https://github.com/david-marchand/dpdk/commit/8f426089f949e0694e5201193be88de673c4283d

That can be done, yes.

Quoted 8 lines

- Probably for later, but I see one more constant added in config/meson.build. All VFIO objects seems to be local (or exchanged over MP messages).

How much effort would it take to remove those constants in config/meson.build? I am thinking about RTE_MAX_VFIO_CONTAINERS, RTE_MAX_VFIO_GROUPS, RTE_MAX_VFIO_DEVICES, EAL_VFIO_MAX_USER_MEM_MAPS.

Compile time constants is a balancing act between flexibility and and ease of implementation. *Technically*, because all of the configuration etc. is process local, I believe we can just do per process malloc/realloc and expand these lists as they grow, thereby doing away with any limitations. However, obviosly, it would require some plumbing work.

That said, now that VFIO code is much cleaner and more structured, I do not think it is difficult to do that.

Quoted 6 lines

- rte_eal_check_module() only user is VFIO.
No opensource project use it.
It could be removed in the future.

Agree.

Signature · 2 lines
Thanks,
Anatoly
#298 lore raw

v18 cover Support VFIO cdev API in DPDK

In reply to a message not in the archive

This patchset introduces a major refactor of the VFIO subsystem in DPDK to support character device (cdev) interface introduced in Linux kernel, as well as make the API more streamlined and useful. The goal is to simplify device management, improve compatibility, make the code readable, and clarify API.

The following sections outline the key issues addressed by this patchset and the corresponding changes introduced.

1. Only group mode is supported
===============================

Since kernel version 4.14.327 (LTS), VFIO supports the new character device (cdev)-based way of working with VFIO devices (otherwise known as IOMMUFD). This is a device-centric mode and does away with all the complexity regarding groups and IOMMU types, delegating it all to the kernel, and exposes a much simpler interface to userspace. The old group-based implementation will still be around, and will need to be kept in DPDK for compatibility reasons.

To enable this, VFIO is heavily refactored, so that the code can support both modes while relying on (mostly) common infrastructure.

Additionally, new vfio_get_mode API is added for those cases that need some introspection into VFIO's internals, with two modes: group (old-style), and cdev (the new mode).

Historically, no-IOMMU mode was technically a variant of group mode, the distinction is largely irrelevant to the user, as all usages of noiommu checks in our codebase are for deciding whether to use IOVA or PA, not anything to do with managing groups. However, now that upcoming kernel versions will support no-IOMMU for both group, cdev compatibility, and full cdev paths, a new vfio_get_iommu_mode is also added, with two modes: safe (full IOMMU backing), and unsafe (no-IOMMU mode). The naming is chosen explicitly to emphasize that using no-IOMMU mode is not ideal.

2. Custom container assignment API does not map to cdev mode
============================================================

The existing rte_vfio_device_setup/release model is fundamentally incompatible with cdev mode, because for custom container cases, the expected flow is that the user binds the IOMMU group (and thus, implicitly, the device itself) to a specific container using rte_vfio_container_group_bind, whereas this step is not needed for cdev as the device fd is assigned to the container straight away.

Therefore, what we do instead is introduce a new API for container device assignment which, semantically, will assign a device to specified container, so that when it is mapped using rte_pci_map_device, the appropriate container is selected. Under the hood though, we essentially transition to getting device fd straight away at assign stage, so that by the time the PCI bus attempts to map the device, it is already mapped and we just return an fd. There is no "unassign" API because release_device already performs that function.

Because the API is now unified around device assignment, the old group-specific API's can be removed and, where appropriate, reimplemented using new API. There were other users of VFIO which relied on group API but only for convenience purposes; no actual VFIO functionality depended on those API's.

List of removed API's:

* rte_vfio_get_group_fd
* rte_vfio_clear_group
* rte_vfio_container_group_bind (replaced by container assign API)
* rte_vfio_container_group_unbind
* rte_vfio_noiommu_is_enabled (replaced by new mode API)

3. The API responsibilities aren't clear and bleed into each other
==================================================================

Some API's do multiple things at once. In particular:

* rte_vfio_get_device_info will setup the device
* rte_vfio_setup_device will get device info

These API's have been adjusted to do one thing only.

4. The API does not need to be public
=====================================

The initial idea for exposing VFIO API was to enable userspace applications to directly map memory for DMA, but it turns out that in practice only drivers use this API. Therefore, the entire VFIO API is made internal, driver-only, and is renamed from rte_vfio to dev_vfio.

v18:
- Adjusted pre-refactor VFIO cleanup to not rely on per-config enabled flag
- Moved loaded module detection from EAL into VFIO
- Added API to check for specific VFIO modules being loaded
- Removed VFIO stubs from non-Linux code by removing PCI bus dependency on VFIO
- Reworked vhost DMA capability check
- Renamed "IOMMU mode" and "safe/unsafe" terminology to IOVA VA/PA
- Fixed typo in FSLMC bus IOVA mode selection

v17:
- Support multiple devices per group in NBL

v16:
- Fixed an unused variable compile error due to typo
- Fixed code for patch 19 being accidentally added into patch 21
- Included the NBL fix[1] in the patchset to enable CI testing

[1] https://patches.dpdk.org/project/dpdk/patch/75e8e3b8ff4d0647e2a5216dcde0d93f3856e821.1787820465.git.anatoly.burakov@intel.com/

v15:
- Fixed resource leak in group mode deduplication path
- On account of kernel 7.3 supporting no-IOMMU mode in kernel version 7.3, split the "VFIO mode" model into two distinct axis: group/cdev, and IOMMU mode

v14:
- Hardened the transitional patches against attempting to use VFIO without having done initialization
- Fixed a bunch of typos, moved a few hunks around to where they belong, and added a more release note entries

v13:
- Addressed feedback from Stephen's AI review:
- Added strdup-based deduplication for group mode to avoid leaking fd's when container assignment API is used
- Added more documentation about cdev mode to Linux GSG
- Fixed comments and log levels in a couple of places
- Renamed the API from rte_vfio_* to dev_vfio_* on account of it no longer being a publicly visible API
- Moved dev_vfio.h into driver SDK headers
- Decoupled VFIO internals from FSLMC and EAL
- Added proper teardown for VFIO subsystem on cleanup

v12:
- Addressed feedback from Stephen's AI review:
- Add release notes updates to patch 2 and 20
- Fix ENXIO typos
- Added a new init step after memory init to enable DMA mapping for cdev

v11:
- Addressed feedback from Stephen's AI review:
- Use CONTAINER_INITIALIZER for reset
- Set container fd to -1 in CONTAINER_INITIALIZER
- Fixed double close()
- Moved VFIO init to earlier in init sequence to account for bus drivers needing no-IOMMU mode status
- Fixed missing ops set for cdev mode, and missing ops reset
- Fixed fd leak on failed attach in cdev

v10:
- Added a patch that renames confusing error labels
- Fixed compiler warning about unused variable

v9:
- Moved erroneous rte_errno-related comments to later in the patchset
- Moved removal of vDPA group fd API's to their respective patches
- Fixed typo in errno comments (ENXIO vs ENOXIO)
- Fixed corruption of group config in secondary process (v8 AI review)

v8:
- Rebase
- Fixed build errors due to variable shadowing
- Removed duplicate fd check as kernel does not provide a way to distinguish between device fd's

v7:
- Rebase
- Added removal of deprecation notices
- Fixed implicit numeric comparison in patch 12

v6:
- Fixed missing header include in vfio cdev file

v5:
- Added back missing uapi patch

v4:
- Fixed issues with documenting rte_vfio_mode enum
- Separated deprecation notices into a separate patchset

v3:
- Make API removal cleaner
- Fix get_group_num usages to align with new API
- Fix issues with function exports
- Fix issues with setup_device returning old-style values in some cases

v2:
- Make the entire API internal
- More aggressive API pruning, complete removal of group API
- Fixed a bug in group mode where device could not be used
- Better documentation and deprecation notice patches
- Moved doc patches to beginning of patchset

Anatoly Burakov (29):
uapi: update to v6.17 and add iommufd.h
vfio: make all functions internal bus/fslmc: decouple from EAL VFIO
vfio: decouple EAL from VFIO internals
vhost: check DMA capability only once
vfio: do proper teardown on VFIO cleanup
eal: move kernel module check function into VFIO
vfio: remove modname parameter from init
vfio: add module check API
bus/pci: decouple PCI bus driver from VFIO
vfio: rename API to reflect internal status bus/pci: rename mismatching error labels
vfio: split get device info from setup
vfio: add container device assignment API net/nbl: do not use VFIO group bind API net/ntnic: use container device assignment API vdpa/ifc: use container device assignment API vdpa/nfp: use container device assignment API vdpa/sfc: use container device assignment API vdpa/mlx5: remove group-related API
vhost: remove group-related API from driver
vfio: remove group-based API
vfio: cleanup and refactor
bus/pci: use the new VFIO IOVA mode API bus/fslmc: use the new VFIO IOVA mode API net/hinic3: use the new VFIO IOVA mode API net/ntnic: use the new VFIO IOVA mode API
vfio: remove no-IOMMU check API
vfio: introduce cdev mode

 config/arm/meson.build                    |    1 +
 config/meson.build                        |    1 +
 doc/api/doxy-api-index.md                 |    3 +-
 doc/guides/linux_gsg/linux_drivers.rst    |   30 +
 doc/guides/prog_guide/vhost_lib.rst       |    4 -
 doc/guides/rel_notes/deprecation.rst      |   10 -
 doc/guides/rel_notes/release_26_11.rst    |   16 +
 drivers/bus/cdx/cdx.c                     |    6 +-
 drivers/bus/cdx/cdx_vfio.c                |   37 +-
 drivers/bus/fslmc/fslmc_bus.c             |   12 +-
 drivers/bus/fslmc/fslmc_vfio.c            |   66 +-
 drivers/bus/fslmc/meson.build             |    1 -
 drivers/bus/pci/bsd/pci.c                 |   24 +
 drivers/bus/pci/linux/pci.c               |   59 +-
 drivers/bus/pci/linux/pci_vfio.c          |   84 +-
 drivers/bus/pci/pci_common.c              |   64 +-
 drivers/bus/pci/private.h                 |  132 +
 drivers/bus/pci/windows/pci.c             |   24 +
 drivers/bus/platform/platform.c           |   17 +-
 drivers/crypto/bcmfs/bcmfs_vfio.c         |   20 +-
 drivers/net/hinic3/base/hinic3_hwdev.c    |    5 +-
 drivers/net/nbl/nbl_common/nbl_userdev.c  |   73 +-
 drivers/net/nbl/nbl_common/nbl_userdev.h  |    1 +
 drivers/net/nbl/nbl_include/nbl_include.h |    1 +
 drivers/net/ntnic/ntnic_ethdev.c          |    4 +-
 drivers/net/ntnic/ntnic_vfio.c            |   48 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c             |   54 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c             |    1 -
 drivers/vdpa/nfp/nfp_vdpa.c               |   53 +-
 drivers/vdpa/sfc/sfc_vdpa.c               |   47 +-
 drivers/vdpa/sfc/sfc_vdpa.h               |    2 -
 drivers/vdpa/sfc/sfc_vdpa_hw.c            |   12 +-
 kernel/linux/uapi/linux/iommufd.h         | 1292 ++++++++++
 kernel/linux/uapi/linux/vduse.h           |    2 +-
 kernel/linux/uapi/linux/vfio.h            |   12 +-
 kernel/linux/uapi/version                 |    2 +-
 lib/eal/common/eal_private.h              |   14 -
 lib/eal/freebsd/eal.c                     |  128 -
 lib/eal/include/dev_vfio.h                |  500 ++++
 lib/eal/include/meson.build               |    2 +-
 lib/eal/include/rte_vfio.h                |  338 ---
 lib/eal/linux/eal.c                       |   62 +-
 lib/eal/linux/eal_vfio.c                  | 2764 +++++++++------------
 lib/eal/linux/eal_vfio.h                  |  188 +-
 lib/eal/linux/eal_vfio_cdev.c             |  420 ++++
 lib/eal/linux/eal_vfio_group.c            |  951 +++++++
 lib/eal/linux/eal_vfio_mp_sync.c          |  118 +-
 lib/eal/linux/meson.build                 |    2 +
 lib/eal/windows/eal.c                     |   23 -
 lib/vhost/socket.c                        |    6 +-
 lib/vhost/vdpa_driver.h                   |    3 -
 lib/vhost/vhost.h                         |    1 +
 lib/vhost/vhost_user.c                    |   16 +-
 53 files changed, 5284 insertions(+), 2472 deletions(-)
 create mode 100644 kernel/linux/uapi/linux/iommufd.h
 create mode 100644 lib/eal/include/dev_vfio.h
 delete mode 100644 lib/eal/include/rte_vfio.h
 create mode 100644 lib/eal/linux/eal_vfio_cdev.c
 create mode 100644 lib/eal/linux/eal_vfio_group.c
Signature · 1 line
2.52.0
#299 lore raw

PATCH v18 1/29 uapi: update to v6.17 and add iommufd.h

In order to support VF tokens for cdev-based VFIO mode, kernel v6.17 is required. Update internal headers to version v6.17 and include iommufd.h.

---
 kernel/linux/uapi/linux/iommufd.h | 1292 +++++++++++++++++++++++++++++
 kernel/linux/uapi/linux/vduse.h   |    2 +-
 kernel/linux/uapi/linux/vfio.h    |   12 +-
 kernel/linux/uapi/version         |    2 +-
 4 files changed, 1305 insertions(+), 3 deletions(-)
 create mode 100644 kernel/linux/uapi/linux/iommufd.h
kernel/linux/uapi/linux/iommufd.h new file +1292 -0
new file mode 100644
index 00000000000..2105a039551
@@ -0,0 +1,1292 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES.
+ */
+#ifndef _IOMMUFD_H
+#define _IOMMUFD_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#define IOMMUFD_TYPE (';')
+
+/**
+ * DOC: General ioctl format
+ *
+ * The ioctl interface follows a general format to allow for extensibility. Each
+ * ioctl is passed in a structure pointer as the argument providing the size of
+ * the structure in the first u32. The kernel checks that any structure space
+ * beyond what it understands is 0. This allows userspace to use the backward
+ * compatible portion while consistently using the newer, larger, structures.
+ *
+ * ioctls use a standard meaning for common errnos:
+ *
+ *  - ENOTTY: The IOCTL number itself is not supported at all
+ *  - E2BIG: The IOCTL number is supported, but the provided structure has
+ *    non-zero in a part the kernel does not understand.
+ *  - EOPNOTSUPP: The IOCTL number is supported, and the structure is
+ *    understood, however a known field has a value the kernel does not
+ *    understand or support.
+ *  - EINVAL: Everything about the IOCTL was understood, but a field is not
+ *    correct.
+ *  - ENOENT: An ID or IOVA provided does not exist.
+ *  - ENOMEM: Out of memory.
+ *  - EOVERFLOW: Mathematics overflowed.
+ *
+ * As well as additional errnos, within specific ioctls.
+ */
+enum {
+	IOMMUFD_CMD_BASE = 0x80,
+	IOMMUFD_CMD_DESTROY = IOMMUFD_CMD_BASE,
+	IOMMUFD_CMD_IOAS_ALLOC = 0x81,
+	IOMMUFD_CMD_IOAS_ALLOW_IOVAS = 0x82,
+	IOMMUFD_CMD_IOAS_COPY = 0x83,
+	IOMMUFD_CMD_IOAS_IOVA_RANGES = 0x84,
+	IOMMUFD_CMD_IOAS_MAP = 0x85,
+	IOMMUFD_CMD_IOAS_UNMAP = 0x86,
+	IOMMUFD_CMD_OPTION = 0x87,
+	IOMMUFD_CMD_VFIO_IOAS = 0x88,
+	IOMMUFD_CMD_HWPT_ALLOC = 0x89,
+	IOMMUFD_CMD_GET_HW_INFO = 0x8a,
+	IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING = 0x8b,
+	IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP = 0x8c,
+	IOMMUFD_CMD_HWPT_INVALIDATE = 0x8d,
+	IOMMUFD_CMD_FAULT_QUEUE_ALLOC = 0x8e,
+	IOMMUFD_CMD_IOAS_MAP_FILE = 0x8f,
+	IOMMUFD_CMD_VIOMMU_ALLOC = 0x90,
+	IOMMUFD_CMD_VDEVICE_ALLOC = 0x91,
+	IOMMUFD_CMD_IOAS_CHANGE_PROCESS = 0x92,
+	IOMMUFD_CMD_VEVENTQ_ALLOC = 0x93,
+	IOMMUFD_CMD_HW_QUEUE_ALLOC = 0x94,
+};
+
+/**
+ * struct iommu_destroy - ioctl(IOMMU_DESTROY)
+ * @size: sizeof(struct iommu_destroy)
+ * @id: iommufd object ID to destroy. Can be any destroyable object type.
+ *
+ * Destroy any object held within iommufd.
+ */
+struct iommu_destroy {
+	__u32 size;
+	__u32 id;
+};
+#define IOMMU_DESTROY _IO(IOMMUFD_TYPE, IOMMUFD_CMD_DESTROY)
+
+/**
+ * struct iommu_ioas_alloc - ioctl(IOMMU_IOAS_ALLOC)
+ * @size: sizeof(struct iommu_ioas_alloc)
+ * @flags: Must be 0
+ * @out_ioas_id: Output IOAS ID for the allocated object
+ *
+ * Allocate an IO Address Space (IOAS) which holds an IO Virtual Address (IOVA)
+ * to memory mapping.
+ */
+struct iommu_ioas_alloc {
+	__u32 size;
+	__u32 flags;
+	__u32 out_ioas_id;
+};
+#define IOMMU_IOAS_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_ALLOC)
+
+/**
+ * struct iommu_iova_range - ioctl(IOMMU_IOVA_RANGE)
+ * @start: First IOVA
+ * @last: Inclusive last IOVA
+ *
+ * An interval in IOVA space.
+ */
+struct iommu_iova_range {
+	__aligned_u64 start;
+	__aligned_u64 last;
+};
+
+/**
+ * struct iommu_ioas_iova_ranges - ioctl(IOMMU_IOAS_IOVA_RANGES)
+ * @size: sizeof(struct iommu_ioas_iova_ranges)
+ * @ioas_id: IOAS ID to read ranges from
+ * @num_iovas: Input/Output total number of ranges in the IOAS
+ * @__reserved: Must be 0
+ * @allowed_iovas: Pointer to the output array of struct iommu_iova_range
+ * @out_iova_alignment: Minimum alignment required for mapping IOVA
+ *
+ * Query an IOAS for ranges of allowed IOVAs. Mapping IOVA outside these ranges
+ * is not allowed. num_iovas will be set to the total number of iovas and
+ * the allowed_iovas[] will be filled in as space permits.
+ *
+ * The allowed ranges are dependent on the HW path the DMA operation takes, and
+ * can change during the lifetime of the IOAS. A fresh empty IOAS will have a
+ * full range, and each attached device will narrow the ranges based on that
+ * device's HW restrictions. Detaching a device can widen the ranges. Userspace
+ * should query ranges after every attach/detach to know what IOVAs are valid
+ * for mapping.
+ *
+ * On input num_iovas is the length of the allowed_iovas array. On output it is
+ * the total number of iovas filled in. The ioctl will return -EMSGSIZE and set
+ * num_iovas to the required value if num_iovas is too small. In this case the
+ * caller should allocate a larger output array and re-issue the ioctl.
+ *
+ * out_iova_alignment returns the minimum IOVA alignment that can be given
+ * to IOMMU_IOAS_MAP/COPY. IOVA's must satisfy::
+ *
+ *   starting_iova % out_iova_alignment == 0
+ *   (starting_iova + length) % out_iova_alignment == 0
+ *
+ * out_iova_alignment can be 1 indicating any IOVA is allowed. It cannot
+ * be higher than the system PAGE_SIZE.
+ */
+struct iommu_ioas_iova_ranges {
+	__u32 size;
+	__u32 ioas_id;
+	__u32 num_iovas;
+	__u32 __reserved;
+	__aligned_u64 allowed_iovas;
+	__aligned_u64 out_iova_alignment;
+};
+#define IOMMU_IOAS_IOVA_RANGES _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_IOVA_RANGES)
+
+/**
+ * struct iommu_ioas_allow_iovas - ioctl(IOMMU_IOAS_ALLOW_IOVAS)
+ * @size: sizeof(struct iommu_ioas_allow_iovas)
+ * @ioas_id: IOAS ID to allow IOVAs from
+ * @num_iovas: Input/Output total number of ranges in the IOAS
+ * @__reserved: Must be 0
+ * @allowed_iovas: Pointer to array of struct iommu_iova_range
+ *
+ * Ensure a range of IOVAs are always available for allocation. If this call
+ * succeeds then IOMMU_IOAS_IOVA_RANGES will never return a list of IOVA ranges
+ * that are narrower than the ranges provided here. This call will fail if
+ * IOMMU_IOAS_IOVA_RANGES is currently narrower than the given ranges.
+ *
+ * When an IOAS is first created the IOVA_RANGES will be maximally sized, and as
+ * devices are attached the IOVA will narrow based on the device restrictions.
+ * When an allowed range is specified any narrowing will be refused, ie device
+ * attachment can fail if the device requires limiting within the allowed range.
+ *
+ * Automatic IOVA allocation is also impacted by this call. MAP will only
+ * allocate within the allowed IOVAs if they are present.
+ *
+ * This call replaces the entire allowed list with the given list.
+ */
+struct iommu_ioas_allow_iovas {
+	__u32 size;
+	__u32 ioas_id;
+	__u32 num_iovas;
+	__u32 __reserved;
+	__aligned_u64 allowed_iovas;
+};
+#define IOMMU_IOAS_ALLOW_IOVAS _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_ALLOW_IOVAS)
+
+/**
+ * enum iommufd_ioas_map_flags - Flags for map and copy
+ * @IOMMU_IOAS_MAP_FIXED_IOVA: If clear the kernel will compute an appropriate
+ *                             IOVA to place the mapping at
+ * @IOMMU_IOAS_MAP_WRITEABLE: DMA is allowed to write to this mapping
+ * @IOMMU_IOAS_MAP_READABLE: DMA is allowed to read from this mapping
+ */
+enum iommufd_ioas_map_flags {
+	IOMMU_IOAS_MAP_FIXED_IOVA = 1 << 0,
+	IOMMU_IOAS_MAP_WRITEABLE = 1 << 1,
+	IOMMU_IOAS_MAP_READABLE = 1 << 2,
+};
+
+/**
+ * struct iommu_ioas_map - ioctl(IOMMU_IOAS_MAP)
+ * @size: sizeof(struct iommu_ioas_map)
+ * @flags: Combination of enum iommufd_ioas_map_flags
+ * @ioas_id: IOAS ID to change the mapping of
+ * @__reserved: Must be 0
+ * @user_va: Userspace pointer to start mapping from
+ * @length: Number of bytes to map
+ * @iova: IOVA the mapping was placed at. If IOMMU_IOAS_MAP_FIXED_IOVA is set
+ *        then this must be provided as input.
+ *
+ * Set an IOVA mapping from a user pointer. If FIXED_IOVA is specified then the
+ * mapping will be established at iova, otherwise a suitable location based on
+ * the reserved and allowed lists will be automatically selected and returned in
+ * iova.
+ *
+ * If IOMMU_IOAS_MAP_FIXED_IOVA is specified then the iova range must currently
+ * be unused, existing IOVA cannot be replaced.
+ */
+struct iommu_ioas_map {
+	__u32 size;
+	__u32 flags;
+	__u32 ioas_id;
+	__u32 __reserved;
+	__aligned_u64 user_va;
+	__aligned_u64 length;
+	__aligned_u64 iova;
+};
+#define IOMMU_IOAS_MAP _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_MAP)
+
+/**
+ * struct iommu_ioas_map_file - ioctl(IOMMU_IOAS_MAP_FILE)
+ * @size: sizeof(struct iommu_ioas_map_file)
+ * @flags: same as for iommu_ioas_map
+ * @ioas_id: same as for iommu_ioas_map
+ * @fd: the memfd to map
+ * @start: byte offset from start of file to map from
+ * @length: same as for iommu_ioas_map
+ * @iova: same as for iommu_ioas_map
+ *
+ * Set an IOVA mapping from a memfd file.  All other arguments and semantics
+ * match those of IOMMU_IOAS_MAP.
+ */
+struct iommu_ioas_map_file {
+	__u32 size;
+	__u32 flags;
+	__u32 ioas_id;
+	__s32 fd;
+	__aligned_u64 start;
+	__aligned_u64 length;
+	__aligned_u64 iova;
+};
+#define IOMMU_IOAS_MAP_FILE _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_MAP_FILE)
+
+/**
+ * struct iommu_ioas_copy - ioctl(IOMMU_IOAS_COPY)
+ * @size: sizeof(struct iommu_ioas_copy)
+ * @flags: Combination of enum iommufd_ioas_map_flags
+ * @dst_ioas_id: IOAS ID to change the mapping of
+ * @src_ioas_id: IOAS ID to copy from
+ * @length: Number of bytes to copy and map
+ * @dst_iova: IOVA the mapping was placed at. If IOMMU_IOAS_MAP_FIXED_IOVA is
+ *            set then this must be provided as input.
+ * @src_iova: IOVA to start the copy
+ *
+ * Copy an already existing mapping from src_ioas_id and establish it in
+ * dst_ioas_id. The src iova/length must exactly match a range used with
+ * IOMMU_IOAS_MAP.
+ *
+ * This may be used to efficiently clone a subset of an IOAS to another, or as a
+ * kind of 'cache' to speed up mapping. Copy has an efficiency advantage over
+ * establishing equivalent new mappings, as internal resources are shared, and
+ * the kernel will pin the user memory only once.
+ */
+struct iommu_ioas_copy {
+	__u32 size;
+	__u32 flags;
+	__u32 dst_ioas_id;
+	__u32 src_ioas_id;
+	__aligned_u64 length;
+	__aligned_u64 dst_iova;
+	__aligned_u64 src_iova;
+};
+#define IOMMU_IOAS_COPY _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_COPY)
+
+/**
+ * struct iommu_ioas_unmap - ioctl(IOMMU_IOAS_UNMAP)
+ * @size: sizeof(struct iommu_ioas_unmap)
+ * @ioas_id: IOAS ID to change the mapping of
+ * @iova: IOVA to start the unmapping at
+ * @length: Number of bytes to unmap, and return back the bytes unmapped
+ *
+ * Unmap an IOVA range. The iova/length must be a superset of a previously
+ * mapped range used with IOMMU_IOAS_MAP or IOMMU_IOAS_COPY. Splitting or
+ * truncating ranges is not allowed. The values 0 to U64_MAX will unmap
+ * everything.
+ */
+struct iommu_ioas_unmap {
+	__u32 size;
+	__u32 ioas_id;
+	__aligned_u64 iova;
+	__aligned_u64 length;
+};
+#define IOMMU_IOAS_UNMAP _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_UNMAP)
+
+/**
+ * enum iommufd_option - ioctl(IOMMU_OPTION_RLIMIT_MODE) and
+ *                       ioctl(IOMMU_OPTION_HUGE_PAGES)
+ * @IOMMU_OPTION_RLIMIT_MODE:
+ *    Change how RLIMIT_MEMLOCK accounting works. The caller must have privilege
+ *    to invoke this. Value 0 (default) is user based accounting, 1 uses process
+ *    based accounting. Global option, object_id must be 0
+ * @IOMMU_OPTION_HUGE_PAGES:
+ *    Value 1 (default) allows contiguous pages to be combined when generating
+ *    iommu mappings. Value 0 disables combining, everything is mapped to
+ *    PAGE_SIZE. This can be useful for benchmarking.  This is a per-IOAS
+ *    option, the object_id must be the IOAS ID.
+ */
+enum iommufd_option {
+	IOMMU_OPTION_RLIMIT_MODE = 0,
+	IOMMU_OPTION_HUGE_PAGES = 1,
+};
+
+/**
+ * enum iommufd_option_ops - ioctl(IOMMU_OPTION_OP_SET) and
+ *                           ioctl(IOMMU_OPTION_OP_GET)
+ * @IOMMU_OPTION_OP_SET: Set the option's value
+ * @IOMMU_OPTION_OP_GET: Get the option's value
+ */
+enum iommufd_option_ops {
+	IOMMU_OPTION_OP_SET = 0,
+	IOMMU_OPTION_OP_GET = 1,
+};
+
+/**
+ * struct iommu_option - iommu option multiplexer
+ * @size: sizeof(struct iommu_option)
+ * @option_id: One of enum iommufd_option
+ * @op: One of enum iommufd_option_ops
+ * @__reserved: Must be 0
+ * @object_id: ID of the object if required
+ * @val64: Option value to set or value returned on get
+ *
+ * Change a simple option value. This multiplexor allows controlling options
+ * on objects. IOMMU_OPTION_OP_SET will load an option and IOMMU_OPTION_OP_GET
+ * will return the current value.
+ */
+struct iommu_option {
+	__u32 size;
+	__u32 option_id;
+	__u16 op;
+	__u16 __reserved;
+	__u32 object_id;
+	__aligned_u64 val64;
+};
+#define IOMMU_OPTION _IO(IOMMUFD_TYPE, IOMMUFD_CMD_OPTION)
+
+/**
+ * enum iommufd_vfio_ioas_op - IOMMU_VFIO_IOAS_* ioctls
+ * @IOMMU_VFIO_IOAS_GET: Get the current compatibility IOAS
+ * @IOMMU_VFIO_IOAS_SET: Change the current compatibility IOAS
+ * @IOMMU_VFIO_IOAS_CLEAR: Disable VFIO compatibility
+ */
+enum iommufd_vfio_ioas_op {
+	IOMMU_VFIO_IOAS_GET = 0,
+	IOMMU_VFIO_IOAS_SET = 1,
+	IOMMU_VFIO_IOAS_CLEAR = 2,
+};
+
+/**
+ * struct iommu_vfio_ioas - ioctl(IOMMU_VFIO_IOAS)
+ * @size: sizeof(struct iommu_vfio_ioas)
+ * @ioas_id: For IOMMU_VFIO_IOAS_SET the input IOAS ID to set
+ *           For IOMMU_VFIO_IOAS_GET will output the IOAS ID
+ * @op: One of enum iommufd_vfio_ioas_op
+ * @__reserved: Must be 0
+ *
+ * The VFIO compatibility support uses a single ioas because VFIO APIs do not
+ * support the ID field. Set or Get the IOAS that VFIO compatibility will use.
+ * When VFIO_GROUP_SET_CONTAINER is used on an iommufd it will get the
+ * compatibility ioas, either by taking what is already set, or auto creating
+ * one. From then on VFIO will continue to use that ioas and is not effected by
+ * this ioctl. SET or CLEAR does not destroy any auto-created IOAS.
+ */
+struct iommu_vfio_ioas {
+	__u32 size;
+	__u32 ioas_id;
+	__u16 op;
+	__u16 __reserved;
+};
+#define IOMMU_VFIO_IOAS _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VFIO_IOAS)
+
+/**
+ * enum iommufd_hwpt_alloc_flags - Flags for HWPT allocation
+ * @IOMMU_HWPT_ALLOC_NEST_PARENT: If set, allocate a HWPT that can serve as
+ *                                the parent HWPT in a nesting configuration.
+ * @IOMMU_HWPT_ALLOC_DIRTY_TRACKING: Dirty tracking support for device IOMMU is
+ *                                   enforced on device attachment
+ * @IOMMU_HWPT_FAULT_ID_VALID: The fault_id field of hwpt allocation data is
+ *                             valid.
+ * @IOMMU_HWPT_ALLOC_PASID: Requests a domain that can be used with PASID. The
+ *                          domain can be attached to any PASID on the device.
+ *                          Any domain attached to the non-PASID part of the
+ *                          device must also be flagged, otherwise attaching a
+ *                          PASID will blocked.
+ *                          For the user that wants to attach PASID, ioas is
+ *                          not recommended for both the non-PASID part
+ *                          and PASID part of the device.
+ *                          If IOMMU does not support PASID it will return
+ *                          error (-EOPNOTSUPP).
+ */
+enum iommufd_hwpt_alloc_flags {
+	IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0,
+	IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1,
+	IOMMU_HWPT_FAULT_ID_VALID = 1 << 2,
+	IOMMU_HWPT_ALLOC_PASID = 1 << 3,
+};
+
+/**
+ * enum iommu_hwpt_vtd_s1_flags - Intel VT-d stage-1 page table
+ *                                entry attributes
+ * @IOMMU_VTD_S1_SRE: Supervisor request
+ * @IOMMU_VTD_S1_EAFE: Extended access enable
+ * @IOMMU_VTD_S1_WPE: Write protect enable
+ */
+enum iommu_hwpt_vtd_s1_flags {
+	IOMMU_VTD_S1_SRE = 1 << 0,
+	IOMMU_VTD_S1_EAFE = 1 << 1,
+	IOMMU_VTD_S1_WPE = 1 << 2,
+};
+
+/**
+ * struct iommu_hwpt_vtd_s1 - Intel VT-d stage-1 page table
+ *                            info (IOMMU_HWPT_DATA_VTD_S1)
+ * @flags: Combination of enum iommu_hwpt_vtd_s1_flags
+ * @pgtbl_addr: The base address of the stage-1 page table.
+ * @addr_width: The address width of the stage-1 page table
+ * @__reserved: Must be 0
+ */
+struct iommu_hwpt_vtd_s1 {
+	__aligned_u64 flags;
+	__aligned_u64 pgtbl_addr;
+	__u32 addr_width;
+	__u32 __reserved;
+};
+
+/**
+ * struct iommu_hwpt_arm_smmuv3 - ARM SMMUv3 nested STE
+ *                                (IOMMU_HWPT_DATA_ARM_SMMUV3)
+ *
+ * @ste: The first two double words of the user space Stream Table Entry for
+ *       the translation. Must be little-endian.
+ *       Allowed fields: (Refer to "5.2 Stream Table Entry" in SMMUv3 HW Spec)
+ *       - word-0: V, Cfg, S1Fmt, S1ContextPtr, S1CDMax
+ *       - word-1: EATS, S1DSS, S1CIR, S1COR, S1CSH, S1STALLD
+ *
+ * -EIO will be returned if @ste is not legal or contains any non-allowed field.
+ * Cfg can be used to select a S1, Bypass or Abort configuration. A Bypass
+ * nested domain will translate the same as the nesting parent. The S1 will
+ * install a Context Descriptor Table pointing at userspace memory translated
+ * by the nesting parent.
+ */
+struct iommu_hwpt_arm_smmuv3 {
+	__aligned_le64 ste[2];
+};
+
+/**
+ * enum iommu_hwpt_data_type - IOMMU HWPT Data Type
+ * @IOMMU_HWPT_DATA_NONE: no data
+ * @IOMMU_HWPT_DATA_VTD_S1: Intel VT-d stage-1 page table
+ * @IOMMU_HWPT_DATA_ARM_SMMUV3: ARM SMMUv3 Context Descriptor Table
+ */
+enum iommu_hwpt_data_type {
+	IOMMU_HWPT_DATA_NONE = 0,
+	IOMMU_HWPT_DATA_VTD_S1 = 1,
+	IOMMU_HWPT_DATA_ARM_SMMUV3 = 2,
+};
+
+/**
+ * struct iommu_hwpt_alloc - ioctl(IOMMU_HWPT_ALLOC)
+ * @size: sizeof(struct iommu_hwpt_alloc)
+ * @flags: Combination of enum iommufd_hwpt_alloc_flags
+ * @dev_id: The device to allocate this HWPT for
+ * @pt_id: The IOAS or HWPT or vIOMMU to connect this HWPT to
+ * @out_hwpt_id: The ID of the new HWPT
+ * @__reserved: Must be 0
+ * @data_type: One of enum iommu_hwpt_data_type
+ * @data_len: Length of the type specific data
+ * @data_uptr: User pointer to the type specific data
+ * @fault_id: The ID of IOMMUFD_FAULT object. Valid only if flags field of
+ *            IOMMU_HWPT_FAULT_ID_VALID is set.
+ * @__reserved2: Padding to 64-bit alignment. Must be 0.
+ *
+ * Explicitly allocate a hardware page table object. This is the same object
+ * type that is returned by iommufd_device_attach() and represents the
+ * underlying iommu driver's iommu_domain kernel object.
+ *
+ * A kernel-managed HWPT will be created with the mappings from the given
+ * IOAS via the @pt_id. The @data_type for this allocation must be set to
+ * IOMMU_HWPT_DATA_NONE. The HWPT can be allocated as a parent HWPT for a
+ * nesting configuration by passing IOMMU_HWPT_ALLOC_NEST_PARENT via @flags.
+ *
+ * A user-managed nested HWPT will be created from a given vIOMMU (wrapping a
+ * parent HWPT) or a parent HWPT via @pt_id, in which the parent HWPT must be
+ * allocated previously via the same ioctl from a given IOAS (@pt_id). In this
+ * case, the @data_type must be set to a pre-defined type corresponding to an
+ * I/O page table type supported by the underlying IOMMU hardware. The device
+ * via @dev_id and the vIOMMU via @pt_id must be associated to the same IOMMU
+ * instance.
+ *
+ * If the @data_type is set to IOMMU_HWPT_DATA_NONE, @data_len and
+ * @data_uptr should be zero. Otherwise, both @data_len and @data_uptr
+ * must be given.
+ */
+struct iommu_hwpt_alloc {
+	__u32 size;
+	__u32 flags;
+	__u32 dev_id;
+	__u32 pt_id;
+	__u32 out_hwpt_id;
+	__u32 __reserved;
+	__u32 data_type;
+	__u32 data_len;
+	__aligned_u64 data_uptr;
+	__u32 fault_id;
+	__u32 __reserved2;
+};
+#define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
+
+/**
+ * enum iommu_hw_info_vtd_flags - Flags for VT-d hw_info
+ * @IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17: If set, disallow read-only mappings
+ *                                         on a nested_parent domain.
+ *                                         https://www.intel.com/content/www/us/en/content-details/772415/content-details.html
+ */
+enum iommu_hw_info_vtd_flags {
+	IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17 = 1 << 0,
+};
+
+/**
+ * struct iommu_hw_info_vtd - Intel VT-d hardware information
+ *
+ * @flags: Combination of enum iommu_hw_info_vtd_flags
+ * @__reserved: Must be 0
+ *
+ * @cap_reg: Value of Intel VT-d capability register defined in VT-d spec
+ *           section 11.4.2 Capability Register.
+ * @ecap_reg: Value of Intel VT-d capability register defined in VT-d spec
+ *            section 11.4.3 Extended Capability Register.
+ *
+ * User needs to understand the Intel VT-d specification to decode the
+ * register value.
+ */
+struct iommu_hw_info_vtd {
+	__u32 flags;
+	__u32 __reserved;
+	__aligned_u64 cap_reg;
+	__aligned_u64 ecap_reg;
+};
+
+/**
+ * struct iommu_hw_info_arm_smmuv3 - ARM SMMUv3 hardware information
+ *                                   (IOMMU_HW_INFO_TYPE_ARM_SMMUV3)
+ *
+ * @flags: Must be set to 0
+ * @__reserved: Must be 0
+ * @idr: Implemented features for ARM SMMU Non-secure programming interface
+ * @iidr: Information about the implementation and implementer of ARM SMMU,
+ *        and architecture version supported
+ * @aidr: ARM SMMU architecture version
+ *
+ * For the details of @idr, @iidr and @aidr, please refer to the chapters
+ * from 6.3.1 to 6.3.6 in the SMMUv3 Spec.
+ *
+ * This reports the raw HW capability, and not all bits are meaningful to be
+ * read by userspace. Only the following fields should be used:
+ *
+ * idr[0]: ST_LEVEL, TERM_MODEL, STALL_MODEL, TTENDIAN , CD2L, ASID16, TTF
+ * idr[1]: SIDSIZE, SSIDSIZE
+ * idr[3]: BBML, RIL
+ * idr[5]: VAX, GRAN64K, GRAN16K, GRAN4K
+ *
+ * - S1P should be assumed to be true if a NESTED HWPT can be created
+ * - VFIO/iommufd only support platforms with COHACC, it should be assumed to be
+ *   true.
+ * - ATS is a per-device property. If the VMM describes any devices as ATS
+ *   capable in ACPI/DT it should set the corresponding idr.
+ *
+ * This list may expand in future (eg E0PD, AIE, PBHA, D128, DS etc). It is
+ * important that VMMs do not read bits outside the list to allow for
+ * compatibility with future kernels. Several features in the SMMUv3
+ * architecture are not currently supported by the kernel for nesting: HTTU,
+ * BTM, MPAM and others.
+ */
+struct iommu_hw_info_arm_smmuv3 {
+	__u32 flags;
+	__u32 __reserved;
+	__u32 idr[6];
+	__u32 iidr;
+	__u32 aidr;
+};
+
+/**
+ * struct iommu_hw_info_tegra241_cmdqv - NVIDIA Tegra241 CMDQV Hardware
+ *         Information (IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV)
+ *
+ * @flags: Must be 0
+ * @version: Version number for the CMDQ-V HW for PARAM bits[03:00]
+ * @log2vcmdqs: Log2 of the total number of VCMDQs for PARAM bits[07:04]
+ * @log2vsids: Log2 of the total number of SID replacements for PARAM bits[15:12]
+ * @__reserved: Must be 0
+ *
+ * VMM can use these fields directly in its emulated global PARAM register. Note
+ * that only one Virtual Interface (VINTF) should be exposed to a VM, i.e. PARAM
+ * bits[11:08] should be set to 0 for log2 of the total number of VINTFs.
+ */
+struct iommu_hw_info_tegra241_cmdqv {
+	__u32 flags;
+	__u8 version;
+	__u8 log2vcmdqs;
+	__u8 log2vsids;
+	__u8 __reserved;
+};
+
+/**
+ * enum iommu_hw_info_type - IOMMU Hardware Info Types
+ * @IOMMU_HW_INFO_TYPE_NONE: Output by the drivers that do not report hardware
+ *                           info
+ * @IOMMU_HW_INFO_TYPE_DEFAULT: Input to request for a default type
+ * @IOMMU_HW_INFO_TYPE_INTEL_VTD: Intel VT-d iommu info type
+ * @IOMMU_HW_INFO_TYPE_ARM_SMMUV3: ARM SMMUv3 iommu info type
+ * @IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV: NVIDIA Tegra241 CMDQV (extension for ARM
+ *                                     SMMUv3) info type
+ */
+enum iommu_hw_info_type {
+	IOMMU_HW_INFO_TYPE_NONE = 0,
+	IOMMU_HW_INFO_TYPE_DEFAULT = 0,
+	IOMMU_HW_INFO_TYPE_INTEL_VTD = 1,
+	IOMMU_HW_INFO_TYPE_ARM_SMMUV3 = 2,
+	IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV = 3,
+};
+
+/**
+ * enum iommufd_hw_capabilities
+ * @IOMMU_HW_CAP_DIRTY_TRACKING: IOMMU hardware support for dirty tracking
+ *                               If available, it means the following APIs
+ *                               are supported:
+ *
+ *                                   IOMMU_HWPT_GET_DIRTY_BITMAP
+ *                                   IOMMU_HWPT_SET_DIRTY_TRACKING
+ *
+ * @IOMMU_HW_CAP_PCI_PASID_EXEC: Execute Permission Supported, user ignores it
+ *                               when the struct
+ *                               iommu_hw_info::out_max_pasid_log2 is zero.
+ * @IOMMU_HW_CAP_PCI_PASID_PRIV: Privileged Mode Supported, user ignores it
+ *                               when the struct
+ *                               iommu_hw_info::out_max_pasid_log2 is zero.
+ */
+enum iommufd_hw_capabilities {
+	IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0,
+	IOMMU_HW_CAP_PCI_PASID_EXEC = 1 << 1,
+	IOMMU_HW_CAP_PCI_PASID_PRIV = 1 << 2,
+};
+
+/**
+ * enum iommufd_hw_info_flags - Flags for iommu_hw_info
+ * @IOMMU_HW_INFO_FLAG_INPUT_TYPE: If set, @in_data_type carries an input type
+ *                                 for user space to request for a specific info
+ */
+enum iommufd_hw_info_flags {
+	IOMMU_HW_INFO_FLAG_INPUT_TYPE = 1 << 0,
+};
+
+/**
+ * struct iommu_hw_info - ioctl(IOMMU_GET_HW_INFO)
+ * @size: sizeof(struct iommu_hw_info)
+ * @flags: Must be 0
+ * @dev_id: The device bound to the iommufd
+ * @data_len: Input the length of a user buffer in bytes. Output the length of
+ *            data that kernel supports
+ * @data_uptr: User pointer to a user-space buffer used by the kernel to fill
+ *             the iommu type specific hardware information data
+ * @in_data_type: This shares the same field with @out_data_type, making it be
+ *                a bidirectional field. When IOMMU_HW_INFO_FLAG_INPUT_TYPE is
+ *                set, an input type carried via this @in_data_type field will
+ *                be valid, requesting for the info data to the given type. If
+ *                IOMMU_HW_INFO_FLAG_INPUT_TYPE is unset, any input value will
+ *                be seen as IOMMU_HW_INFO_TYPE_DEFAULT
+ * @out_data_type: Output the iommu hardware info type as defined in the enum
+ *                 iommu_hw_info_type.
+ * @out_capabilities: Output the generic iommu capability info type as defined
+ *                    in the enum iommu_hw_capabilities.
+ * @out_max_pasid_log2: Output the width of PASIDs. 0 means no PASID support.
+ *                      PCI devices turn to out_capabilities to check if the
+ *                      specific capabilities is supported or not.
+ * @__reserved: Must be 0
+ *
+ * Query an iommu type specific hardware information data from an iommu behind
+ * a given device that has been bound to iommufd. This hardware info data will
+ * be used to sync capabilities between the virtual iommu and the physical
+ * iommu, e.g. a nested translation setup needs to check the hardware info, so
+ * a guest stage-1 page table can be compatible with the physical iommu.
+ *
+ * To capture an iommu type specific hardware information data, @data_uptr and
+ * its length @data_len must be provided. Trailing bytes will be zeroed if the
+ * user buffer is larger than the data that kernel has. Otherwise, kernel only
+ * fills the buffer using the given length in @data_len. If the ioctl succeeds,
+ * @data_len will be updated to the length that kernel actually supports,
+ * @out_data_type will be filled to decode the data filled in the buffer
+ * pointed by @data_uptr. Input @data_len == zero is allowed.
+ */
+struct iommu_hw_info {
+	__u32 size;
+	__u32 flags;
+	__u32 dev_id;
+	__u32 data_len;
+	__aligned_u64 data_uptr;
+	union {
+		__u32 in_data_type;
+		__u32 out_data_type;
+	};
+	__u8 out_max_pasid_log2;
+	__u8 __reserved[3];
+	__aligned_u64 out_capabilities;
+};
+#define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO)
+
+/*
+ * enum iommufd_hwpt_set_dirty_tracking_flags - Flags for steering dirty
+ *                                              tracking
+ * @IOMMU_HWPT_DIRTY_TRACKING_ENABLE: Enable dirty tracking
+ */
+enum iommufd_hwpt_set_dirty_tracking_flags {
+	IOMMU_HWPT_DIRTY_TRACKING_ENABLE = 1,
+};
+
+/**
+ * struct iommu_hwpt_set_dirty_tracking - ioctl(IOMMU_HWPT_SET_DIRTY_TRACKING)
+ * @size: sizeof(struct iommu_hwpt_set_dirty_tracking)
+ * @flags: Combination of enum iommufd_hwpt_set_dirty_tracking_flags
+ * @hwpt_id: HW pagetable ID that represents the IOMMU domain
+ * @__reserved: Must be 0
+ *
+ * Toggle dirty tracking on an HW pagetable.
+ */
+struct iommu_hwpt_set_dirty_tracking {
+	__u32 size;
+	__u32 flags;
+	__u32 hwpt_id;
+	__u32 __reserved;
+};
+#define IOMMU_HWPT_SET_DIRTY_TRACKING _IO(IOMMUFD_TYPE, \
+					  IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING)
+
+/**
+ * enum iommufd_hwpt_get_dirty_bitmap_flags - Flags for getting dirty bits
+ * @IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR: Just read the PTEs without clearing
+ *                                        any dirty bits metadata. This flag
+ *                                        can be passed in the expectation
+ *                                        where the next operation is an unmap
+ *                                        of the same IOVA range.
+ *
+ */
+enum iommufd_hwpt_get_dirty_bitmap_flags {
+	IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR = 1,
+};
+
+/**
+ * struct iommu_hwpt_get_dirty_bitmap - ioctl(IOMMU_HWPT_GET_DIRTY_BITMAP)
+ * @size: sizeof(struct iommu_hwpt_get_dirty_bitmap)
+ * @hwpt_id: HW pagetable ID that represents the IOMMU domain
+ * @flags: Combination of enum iommufd_hwpt_get_dirty_bitmap_flags
+ * @__reserved: Must be 0
+ * @iova: base IOVA of the bitmap first bit
+ * @length: IOVA range size
+ * @page_size: page size granularity of each bit in the bitmap
+ * @data: bitmap where to set the dirty bits. The bitmap bits each
+ *        represent a page_size which you deviate from an arbitrary iova.
+ *
+ * Checking a given IOVA is dirty:
+ *
+ *  data[(iova / page_size) / 64] & (1ULL << ((iova / page_size) % 64))
+ *
+ * Walk the IOMMU pagetables for a given IOVA range to return a bitmap
+ * with the dirty IOVAs. In doing so it will also by default clear any
+ * dirty bit metadata set in the IOPTE.
+ */
+struct iommu_hwpt_get_dirty_bitmap {
+	__u32 size;
+	__u32 hwpt_id;
+	__u32 flags;
+	__u32 __reserved;
+	__aligned_u64 iova;
+	__aligned_u64 length;
+	__aligned_u64 page_size;
+	__aligned_u64 data;
+};
+#define IOMMU_HWPT_GET_DIRTY_BITMAP _IO(IOMMUFD_TYPE, \
+					IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP)
+
+/**
+ * enum iommu_hwpt_invalidate_data_type - IOMMU HWPT Cache Invalidation
+ *                                        Data Type
+ * @IOMMU_HWPT_INVALIDATE_DATA_VTD_S1: Invalidation data for VTD_S1
+ * @IOMMU_VIOMMU_INVALIDATE_DATA_ARM_SMMUV3: Invalidation data for ARM SMMUv3
+ */
+enum iommu_hwpt_invalidate_data_type {
+	IOMMU_HWPT_INVALIDATE_DATA_VTD_S1 = 0,
+	IOMMU_VIOMMU_INVALIDATE_DATA_ARM_SMMUV3 = 1,
+};
+
+/**
+ * enum iommu_hwpt_vtd_s1_invalidate_flags - Flags for Intel VT-d
+ *                                           stage-1 cache invalidation
+ * @IOMMU_VTD_INV_FLAGS_LEAF: Indicates whether the invalidation applies
+ *                            to all-levels page structure cache or just
+ *                            the leaf PTE cache.
+ */
+enum iommu_hwpt_vtd_s1_invalidate_flags {
+	IOMMU_VTD_INV_FLAGS_LEAF = 1 << 0,
+};
+
+/**
+ * struct iommu_hwpt_vtd_s1_invalidate - Intel VT-d cache invalidation
+ *                                       (IOMMU_HWPT_INVALIDATE_DATA_VTD_S1)
+ * @addr: The start address of the range to be invalidated. It needs to
+ *        be 4KB aligned.
+ * @npages: Number of contiguous 4K pages to be invalidated.
+ * @flags: Combination of enum iommu_hwpt_vtd_s1_invalidate_flags
+ * @__reserved: Must be 0
+ *
+ * The Intel VT-d specific invalidation data for user-managed stage-1 cache
+ * invalidation in nested translation. Userspace uses this structure to
+ * tell the impacted cache scope after modifying the stage-1 page table.
+ *
+ * Invalidating all the caches related to the page table by setting @addr
+ * to be 0 and @npages to be U64_MAX.
+ *
+ * The device TLB will be invalidated automatically if ATS is enabled.
+ */
+struct iommu_hwpt_vtd_s1_invalidate {
+	__aligned_u64 addr;
+	__aligned_u64 npages;
+	__u32 flags;
+	__u32 __reserved;
+};
+
+/**
+ * struct iommu_viommu_arm_smmuv3_invalidate - ARM SMMUv3 cache invalidation
+ *         (IOMMU_VIOMMU_INVALIDATE_DATA_ARM_SMMUV3)
+ * @cmd: 128-bit cache invalidation command that runs in SMMU CMDQ.
+ *       Must be little-endian.
+ *
+ * Supported command list only when passing in a vIOMMU via @hwpt_id:
+ *     CMDQ_OP_TLBI_NSNH_ALL
+ *     CMDQ_OP_TLBI_NH_VA
+ *     CMDQ_OP_TLBI_NH_VAA
+ *     CMDQ_OP_TLBI_NH_ALL
+ *     CMDQ_OP_TLBI_NH_ASID
+ *     CMDQ_OP_ATC_INV
+ *     CMDQ_OP_CFGI_CD
+ *     CMDQ_OP_CFGI_CD_ALL
+ *
+ * -EIO will be returned if the command is not supported.
+ */
+struct iommu_viommu_arm_smmuv3_invalidate {
+	__aligned_le64 cmd[2];
+};
+
+/**
+ * struct iommu_hwpt_invalidate - ioctl(IOMMU_HWPT_INVALIDATE)
+ * @size: sizeof(struct iommu_hwpt_invalidate)
+ * @hwpt_id: ID of a nested HWPT or a vIOMMU, for cache invalidation
+ * @data_uptr: User pointer to an array of driver-specific cache invalidation
+ *             data.
+ * @data_type: One of enum iommu_hwpt_invalidate_data_type, defining the data
+ *             type of all the entries in the invalidation request array. It
+ *             should be a type supported by the hwpt pointed by @hwpt_id.
+ * @entry_len: Length (in bytes) of a request entry in the request array
+ * @entry_num: Input the number of cache invalidation requests in the array.
+ *             Output the number of requests successfully handled by kernel.
+ * @__reserved: Must be 0.
+ *
+ * Invalidate iommu cache for user-managed page table or vIOMMU. Modifications
+ * on a user-managed page table should be followed by this operation, if a HWPT
+ * is passed in via @hwpt_id. Other caches, such as device cache or descriptor
+ * cache can be flushed if a vIOMMU is passed in via the @hwpt_id field.
+ *
+ * Each ioctl can support one or more cache invalidation requests in the array
+ * that has a total size of @entry_len * @entry_num.
+ *
+ * An empty invalidation request array by setting @entry_num==0 is allowed, and
+ * @entry_len and @data_uptr would be ignored in this case. This can be used to
+ * check if the given @data_type is supported or not by kernel.
+ */
+struct iommu_hwpt_invalidate {
+	__u32 size;
+	__u32 hwpt_id;
+	__aligned_u64 data_uptr;
+	__u32 data_type;
+	__u32 entry_len;
+	__u32 entry_num;
+	__u32 __reserved;
+};
+#define IOMMU_HWPT_INVALIDATE _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_INVALIDATE)
+
+/**
+ * enum iommu_hwpt_pgfault_flags - flags for struct iommu_hwpt_pgfault
+ * @IOMMU_PGFAULT_FLAGS_PASID_VALID: The pasid field of the fault data is
+ *                                   valid.
+ * @IOMMU_PGFAULT_FLAGS_LAST_PAGE: It's the last fault of a fault group.
+ */
+enum iommu_hwpt_pgfault_flags {
+	IOMMU_PGFAULT_FLAGS_PASID_VALID		= (1 << 0),
+	IOMMU_PGFAULT_FLAGS_LAST_PAGE		= (1 << 1),
+};
+
+/**
+ * enum iommu_hwpt_pgfault_perm - perm bits for struct iommu_hwpt_pgfault
+ * @IOMMU_PGFAULT_PERM_READ: request for read permission
+ * @IOMMU_PGFAULT_PERM_WRITE: request for write permission
+ * @IOMMU_PGFAULT_PERM_EXEC: (PCIE 10.4.1) request with a PASID that has the
+ *                           Execute Requested bit set in PASID TLP Prefix.
+ * @IOMMU_PGFAULT_PERM_PRIV: (PCIE 10.4.1) request with a PASID that has the
+ *                           Privileged Mode Requested bit set in PASID TLP
+ *                           Prefix.
+ */
+enum iommu_hwpt_pgfault_perm {
+	IOMMU_PGFAULT_PERM_READ			= (1 << 0),
+	IOMMU_PGFAULT_PERM_WRITE		= (1 << 1),
+	IOMMU_PGFAULT_PERM_EXEC			= (1 << 2),
+	IOMMU_PGFAULT_PERM_PRIV			= (1 << 3),
+};
+
+/**
+ * struct iommu_hwpt_pgfault - iommu page fault data
+ * @flags: Combination of enum iommu_hwpt_pgfault_flags
+ * @dev_id: id of the originated device
+ * @pasid: Process Address Space ID
+ * @grpid: Page Request Group Index
+ * @perm: Combination of enum iommu_hwpt_pgfault_perm
+ * @__reserved: Must be 0.
+ * @addr: Fault address
+ * @length: a hint of how much data the requestor is expecting to fetch. For
+ *          example, if the PRI initiator knows it is going to do a 10MB
+ *          transfer, it could fill in 10MB and the OS could pre-fault in
+ *          10MB of IOVA. It's default to 0 if there's no such hint.
+ * @cookie: kernel-managed cookie identifying a group of fault messages. The
+ *          cookie number encoded in the last page fault of the group should
+ *          be echoed back in the response message.
+ */
+struct iommu_hwpt_pgfault {
+	__u32 flags;
+	__u32 dev_id;
+	__u32 pasid;
+	__u32 grpid;
+	__u32 perm;
+	__u32 __reserved;
+	__aligned_u64 addr;
+	__u32 length;
+	__u32 cookie;
+};
+
+/**
+ * enum iommufd_page_response_code - Return status of fault handlers
+ * @IOMMUFD_PAGE_RESP_SUCCESS: Fault has been handled and the page tables
+ *                             populated, retry the access. This is the
+ *                             "Success" defined in PCI 10.4.2.1.
+ * @IOMMUFD_PAGE_RESP_INVALID: Could not handle this fault, don't retry the
+ *                             access. This is the "Invalid Request" in PCI
+ *                             10.4.2.1.
+ */
+enum iommufd_page_response_code {
+	IOMMUFD_PAGE_RESP_SUCCESS = 0,
+	IOMMUFD_PAGE_RESP_INVALID = 1,
+};
+
+/**
+ * struct iommu_hwpt_page_response - IOMMU page fault response
+ * @cookie: The kernel-managed cookie reported in the fault message.
+ * @code: One of response code in enum iommufd_page_response_code.
+ */
+struct iommu_hwpt_page_response {
+	__u32 cookie;
+	__u32 code;
+};
+
+/**
+ * struct iommu_fault_alloc - ioctl(IOMMU_FAULT_QUEUE_ALLOC)
+ * @size: sizeof(struct iommu_fault_alloc)
+ * @flags: Must be 0
+ * @out_fault_id: The ID of the new FAULT
+ * @out_fault_fd: The fd of the new FAULT
+ *
+ * Explicitly allocate a fault handling object.
+ */
+struct iommu_fault_alloc {
+	__u32 size;
+	__u32 flags;
+	__u32 out_fault_id;
+	__u32 out_fault_fd;
+};
+#define IOMMU_FAULT_QUEUE_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_FAULT_QUEUE_ALLOC)
+
+/**
+ * enum iommu_viommu_type - Virtual IOMMU Type
+ * @IOMMU_VIOMMU_TYPE_DEFAULT: Reserved for future use
+ * @IOMMU_VIOMMU_TYPE_ARM_SMMUV3: ARM SMMUv3 driver specific type
+ * @IOMMU_VIOMMU_TYPE_TEGRA241_CMDQV: NVIDIA Tegra241 CMDQV (extension for ARM
+ *                                    SMMUv3) enabled ARM SMMUv3 type
+ */
+enum iommu_viommu_type {
+	IOMMU_VIOMMU_TYPE_DEFAULT = 0,
+	IOMMU_VIOMMU_TYPE_ARM_SMMUV3 = 1,
+	IOMMU_VIOMMU_TYPE_TEGRA241_CMDQV = 2,
+};
+
+/**
+ * struct iommu_viommu_tegra241_cmdqv - NVIDIA Tegra241 CMDQV Virtual Interface
+ *                                      (IOMMU_VIOMMU_TYPE_TEGRA241_CMDQV)
+ * @out_vintf_mmap_offset: mmap offset argument for VINTF's page0
+ * @out_vintf_mmap_length: mmap length argument for VINTF's page0
+ *
+ * Both @out_vintf_mmap_offset and @out_vintf_mmap_length are reported by kernel
+ * for user space to mmap the VINTF page0 from the host physical address space
+ * to the guest physical address space so that a guest kernel can directly R/W
+ * access to the VINTF page0 in order to control its virtual command queues.
+ */
+struct iommu_viommu_tegra241_cmdqv {
+	__aligned_u64 out_vintf_mmap_offset;
+	__aligned_u64 out_vintf_mmap_length;
+};
+
+/**
+ * struct iommu_viommu_alloc - ioctl(IOMMU_VIOMMU_ALLOC)
+ * @size: sizeof(struct iommu_viommu_alloc)
+ * @flags: Must be 0
+ * @type: Type of the virtual IOMMU. Must be defined in enum iommu_viommu_type
+ * @dev_id: The device's physical IOMMU will be used to back the virtual IOMMU
+ * @hwpt_id: ID of a nesting parent HWPT to associate to
+ * @out_viommu_id: Output virtual IOMMU ID for the allocated object
+ * @data_len: Length of the type specific data
+ * @__reserved: Must be 0
+ * @data_uptr: User pointer to a driver-specific virtual IOMMU data
+ *
+ * Allocate a virtual IOMMU object, representing the underlying physical IOMMU's
+ * virtualization support that is a security-isolated slice of the real IOMMU HW
+ * that is unique to a specific VM. Operations global to the IOMMU are connected
+ * to the vIOMMU, such as:
+ * - Security namespace for guest owned ID, e.g. guest-controlled cache tags
+ * - Non-device-affiliated event reporting, e.g. invalidation queue errors
+ * - Access to a sharable nesting parent pagetable across physical IOMMUs
+ * - Virtualization of various platforms IDs, e.g. RIDs and others
+ * - Delivery of paravirtualized invalidation
+ * - Direct assigned invalidation queues
+ * - Direct assigned interrupts
+ */
+struct iommu_viommu_alloc {
+	__u32 size;
+	__u32 flags;
+	__u32 type;
+	__u32 dev_id;
+	__u32 hwpt_id;
+	__u32 out_viommu_id;
+	__u32 data_len;
+	__u32 __reserved;
+	__aligned_u64 data_uptr;
+};
+#define IOMMU_VIOMMU_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VIOMMU_ALLOC)
+
+/**
+ * struct iommu_vdevice_alloc - ioctl(IOMMU_VDEVICE_ALLOC)
+ * @size: sizeof(struct iommu_vdevice_alloc)
+ * @viommu_id: vIOMMU ID to associate with the virtual device
+ * @dev_id: The physical device to allocate a virtual instance on the vIOMMU
+ * @out_vdevice_id: Object handle for the vDevice. Pass to IOMMU_DESTORY
+ * @virt_id: Virtual device ID per vIOMMU, e.g. vSID of ARM SMMUv3, vDeviceID
+ *           of AMD IOMMU, and vRID of Intel VT-d
+ *
+ * Allocate a virtual device instance (for a physical device) against a vIOMMU.
+ * This instance holds the device's information (related to its vIOMMU) in a VM.
+ * User should use IOMMU_DESTROY to destroy the virtual device before
+ * destroying the physical device (by closing vfio_cdev fd). Otherwise the
+ * virtual device would be forcibly destroyed on physical device destruction,
+ * its vdevice_id would be permanently leaked (unremovable & unreusable) until
+ * iommu fd closed.
+ */
+struct iommu_vdevice_alloc {
+	__u32 size;
+	__u32 viommu_id;
+	__u32 dev_id;
+	__u32 out_vdevice_id;
+	__aligned_u64 virt_id;
+};
+#define IOMMU_VDEVICE_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VDEVICE_ALLOC)
+
+/**
+ * struct iommu_ioas_change_process - ioctl(VFIO_IOAS_CHANGE_PROCESS)
+ * @size: sizeof(struct iommu_ioas_change_process)
+ * @__reserved: Must be 0
+ *
+ * This transfers pinned memory counts for every memory map in every IOAS
+ * in the context to the current process.  This only supports maps created
+ * with IOMMU_IOAS_MAP_FILE, and returns EINVAL if other maps are present.
+ * If the ioctl returns a failure status, then nothing is changed.
+ *
+ * This API is useful for transferring operation of a device from one process
+ * to another, such as during userland live update.
+ */
+struct iommu_ioas_change_process {
+	__u32 size;
+	__u32 __reserved;
+};
+
+#define IOMMU_IOAS_CHANGE_PROCESS \
+	_IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_CHANGE_PROCESS)
+
+/**
+ * enum iommu_veventq_flag - flag for struct iommufd_vevent_header
+ * @IOMMU_VEVENTQ_FLAG_LOST_EVENTS: vEVENTQ has lost vEVENTs
+ */
+enum iommu_veventq_flag {
+	IOMMU_VEVENTQ_FLAG_LOST_EVENTS = (1U << 0),
+};
+
+/**
+ * struct iommufd_vevent_header - Virtual Event Header for a vEVENTQ Status
+ * @flags: Combination of enum iommu_veventq_flag
+ * @sequence: The sequence index of a vEVENT in the vEVENTQ, with a range of
+ *            [0, INT_MAX] where the following index of INT_MAX is 0
+ *
+ * Each iommufd_vevent_header reports a sequence index of the following vEVENT:
+ *
+ * +----------------------+-------+----------------------+-------+---+-------+
+ * | header0 {sequence=0} | data0 | header1 {sequence=1} | data1 |...| dataN |
+ * +----------------------+-------+----------------------+-------+---+-------+
+ *
+ * And this sequence index is expected to be monotonic to the sequence index of
+ * the previous vEVENT. If two adjacent sequence indexes has a delta larger than
+ * 1, it means that delta - 1 number of vEVENTs has lost, e.g. two lost vEVENTs:
+ *
+ * +-----+----------------------+-------+----------------------+-------+-----+
+ * | ... | header3 {sequence=3} | data3 | header6 {sequence=6} | data6 | ... |
+ * +-----+----------------------+-------+----------------------+-------+-----+
+ *
+ * If a vEVENT lost at the tail of the vEVENTQ and there is no following vEVENT
+ * providing the next sequence index, an IOMMU_VEVENTQ_FLAG_LOST_EVENTS header
+ * would be added to the tail, and no data would follow this header:
+ *
+ * +--+----------------------+-------+-----------------------------------------+
+ * |..| header3 {sequence=3} | data3 | header4 {flags=LOST_EVENTS, sequence=4} |
+ * +--+----------------------+-------+-----------------------------------------+
+ */
+struct iommufd_vevent_header {
+	__u32 flags;
+	__u32 sequence;
+};
+
+/**
+ * enum iommu_veventq_type - Virtual Event Queue Type
+ * @IOMMU_VEVENTQ_TYPE_DEFAULT: Reserved for future use
+ * @IOMMU_VEVENTQ_TYPE_ARM_SMMUV3: ARM SMMUv3 Virtual Event Queue
+ * @IOMMU_VEVENTQ_TYPE_TEGRA241_CMDQV: NVIDIA Tegra241 CMDQV Extension IRQ
+ */
+enum iommu_veventq_type {
+	IOMMU_VEVENTQ_TYPE_DEFAULT = 0,
+	IOMMU_VEVENTQ_TYPE_ARM_SMMUV3 = 1,
+	IOMMU_VEVENTQ_TYPE_TEGRA241_CMDQV = 2,
+};
+
+/**
+ * struct iommu_vevent_arm_smmuv3 - ARM SMMUv3 Virtual Event
+ *                                  (IOMMU_VEVENTQ_TYPE_ARM_SMMUV3)
+ * @evt: 256-bit ARM SMMUv3 Event record, little-endian.
+ *       Reported event records: (Refer to "7.3 Event records" in SMMUv3 HW Spec)
+ *       - 0x04 C_BAD_STE
+ *       - 0x06 F_STREAM_DISABLED
+ *       - 0x08 C_BAD_SUBSTREAMID
+ *       - 0x0a C_BAD_CD
+ *       - 0x10 F_TRANSLATION
+ *       - 0x11 F_ADDR_SIZE
+ *       - 0x12 F_ACCESS
+ *       - 0x13 F_PERMISSION
+ *
+ * StreamID field reports a virtual device ID. To receive a virtual event for a
+ * device, a vDEVICE must be allocated via IOMMU_VDEVICE_ALLOC.
+ */
+struct iommu_vevent_arm_smmuv3 {
+	__aligned_le64 evt[4];
+};
+
+/**
+ * struct iommu_vevent_tegra241_cmdqv - Tegra241 CMDQV IRQ
+ *                                      (IOMMU_VEVENTQ_TYPE_TEGRA241_CMDQV)
+ * @lvcmdq_err_map: 128-bit logical vcmdq error map, little-endian.
+ *                  (Refer to register LVCMDQ_ERR_MAPs per VINTF )
+ *
+ * The 128-bit register value from HW exclusively reflect the error bits for a
+ * Virtual Interface represented by a vIOMMU object. Read and report directly.
+ */
+struct iommu_vevent_tegra241_cmdqv {
+	__aligned_le64 lvcmdq_err_map[2];
+};
+
+/**
+ * struct iommu_veventq_alloc - ioctl(IOMMU_VEVENTQ_ALLOC)
+ * @size: sizeof(struct iommu_veventq_alloc)
+ * @flags: Must be 0
+ * @viommu_id: virtual IOMMU ID to associate the vEVENTQ with
+ * @type: Type of the vEVENTQ. Must be defined in enum iommu_veventq_type
+ * @veventq_depth: Maximum number of events in the vEVENTQ
+ * @out_veventq_id: The ID of the new vEVENTQ
+ * @out_veventq_fd: The fd of the new vEVENTQ. User space must close the
+ *                  successfully returned fd after using it
+ * @__reserved: Must be 0
+ *
+ * Explicitly allocate a virtual event queue interface for a vIOMMU. A vIOMMU
+ * can have multiple FDs for different types, but is confined to one per @type.
+ * User space should open the @out_veventq_fd to read vEVENTs out of a vEVENTQ,
+ * if there are vEVENTs available. A vEVENTQ will lose events due to overflow,
+ * if the number of the vEVENTs hits @veventq_depth.
+ *
+ * Each vEVENT in a vEVENTQ encloses a struct iommufd_vevent_header followed by
+ * a type-specific data structure, in a normal case:
+ *
+ * +-+---------+-------+---------+-------+-----+---------+-------+-+
+ * | | header0 | data0 | header1 | data1 | ... | headerN | dataN | |
+ * +-+---------+-------+---------+-------+-----+---------+-------+-+
+ *
+ * unless a tailing IOMMU_VEVENTQ_FLAG_LOST_EVENTS header is logged (refer to
+ * struct iommufd_vevent_header).
+ */
+struct iommu_veventq_alloc {
+	__u32 size;
+	__u32 flags;
+	__u32 viommu_id;
+	__u32 type;
+	__u32 veventq_depth;
+	__u32 out_veventq_id;
+	__u32 out_veventq_fd;
+	__u32 __reserved;
+};
+#define IOMMU_VEVENTQ_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VEVENTQ_ALLOC)
+
+/**
+ * enum iommu_hw_queue_type - HW Queue Type
+ * @IOMMU_HW_QUEUE_TYPE_DEFAULT: Reserved for future use
+ * @IOMMU_HW_QUEUE_TYPE_TEGRA241_CMDQV: NVIDIA Tegra241 CMDQV (extension for ARM
+ *                                      SMMUv3) Virtual Command Queue (VCMDQ)
+ */
+enum iommu_hw_queue_type {
+	IOMMU_HW_QUEUE_TYPE_DEFAULT = 0,
+	/*
+	 * TEGRA241_CMDQV requirements (otherwise, allocation will fail)
+	 * - alloc starts from the lowest @index=0 in ascending order
+	 * - destroy starts from the last allocated @index in descending order
+	 * - @base_addr must be aligned to @length in bytes and mapped in IOAS
+	 * - @length must be a power of 2, with a minimum 32 bytes and a maximum
+	 *   2 ^ idr[1].CMDQS * 16 bytes (use GET_HW_INFO call to read idr[1]
+	 *   from struct iommu_hw_info_arm_smmuv3)
+	 * - suggest to back the queue memory with contiguous physical pages or
+	 *   a single huge page with alignment of the queue size, and limit the
+	 *   emulated vSMMU's IDR1.CMDQS to log2(huge page size / 16 bytes)
+	 */
+	IOMMU_HW_QUEUE_TYPE_TEGRA241_CMDQV = 1,
+};
+
+/**
+ * struct iommu_hw_queue_alloc - ioctl(IOMMU_HW_QUEUE_ALLOC)
+ * @size: sizeof(struct iommu_hw_queue_alloc)
+ * @flags: Must be 0
+ * @viommu_id: Virtual IOMMU ID to associate the HW queue with
+ * @type: One of enum iommu_hw_queue_type
+ * @index: The logical index to the HW queue per virtual IOMMU for a multi-queue
+ *         model
+ * @out_hw_queue_id: The ID of the new HW queue
+ * @nesting_parent_iova: Base address of the queue memory in the guest physical
+ *                       address space
+ * @length: Length of the queue memory
+ *
+ * Allocate a HW queue object for a vIOMMU-specific HW-accelerated queue, which
+ * allows HW to access a guest queue memory described using @nesting_parent_iova
+ * and @length.
+ *
+ * A vIOMMU can allocate multiple queues, but it must use a different @index per
+ * type to separate each allocation, e.g::
+ *
+ *     Type1 HW queue0, Type1 HW queue1, Type2 HW queue0, ...
+ */
+struct iommu_hw_queue_alloc {
+	__u32 size;
+	__u32 flags;
+	__u32 viommu_id;
+	__u32 type;
+	__u32 index;
+	__u32 out_hw_queue_id;
+	__aligned_u64 nesting_parent_iova;
+	__aligned_u64 length;
+};
+#define IOMMU_HW_QUEUE_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HW_QUEUE_ALLOC)
+#endif
kernel/linux/uapi/linux/vduse.h +1 -1
index f46269af349..da6ac89af18 100644
@@ -237,7 +237,7 @@ struct vduse_iova_umem {
  * struct vduse_iova_info - information of one IOVA region
  * @start: start of the IOVA region
  * @last: last of the IOVA region
- * @capability: capability of the IOVA regsion
+ * @capability: capability of the IOVA region
  * @reserved: for future use, needs to be initialized to zero
  *
  * Structure used by VDUSE_IOTLB_GET_INFO ioctl to get information of
kernel/linux/uapi/linux/vfio.h +11 -1
index 79bf8c0cc5e..4d96d1fc12f 100644
@@ -905,10 +905,12 @@ struct vfio_device_feature {
  * VFIO_DEVICE_BIND_IOMMUFD - _IOR(VFIO_TYPE, VFIO_BASE + 18,
  *				   struct vfio_device_bind_iommufd)
  * @argsz:	 User filled size of this data.
- * @flags:	 Must be 0.
+ * @flags:	 Must be 0 or a bit flags of VFIO_DEVICE_BIND_*
  * @iommufd:	 iommufd to bind.
  * @out_devid:	 The device id generated by this bind. devid is a handle for
  *		 this device/iommufd bond and can be used in IOMMUFD commands.
+ * @token_uuid_ptr: Valid if VFIO_DEVICE_BIND_FLAG_TOKEN. Points to a 16 byte
+ *                  UUID in the same format as VFIO_DEVICE_FEATURE_PCI_VF_TOKEN.
  *
  * Bind a vfio_device to the specified iommufd.
  *
@@ -917,13 +919,21 @@ struct vfio_device_feature {
  *
  * Unbind is automatically conducted when device fd is closed.
  *
+ * A token is sometimes required to open the device, unless this is known to be
+ * needed VFIO_DEVICE_BIND_FLAG_TOKEN should not be set and token_uuid_ptr is
+ * ignored. The only case today is a PF/VF relationship where the VF bind must
+ * be provided the same token as VFIO_DEVICE_FEATURE_PCI_VF_TOKEN provided to
+ * the PF.
+ *
  * Return: 0 on success, -errno on failure.
  */
 struct vfio_device_bind_iommufd {
 	__u32		argsz;
 	__u32		flags;
+#define VFIO_DEVICE_BIND_FLAG_TOKEN (1 << 0)
 	__s32		iommufd;
 	__u32		out_devid;
+	__aligned_u64	token_uuid_ptr;
 };
 
 #define VFIO_DEVICE_BIND_IOMMUFD	_IO(VFIO_TYPE, VFIO_BASE + 18)
kernel/linux/uapi/version +1 -1
index 966a9983019..d9e789dade4 100644
@@ -1 +1 @@
-v6.16
+v6.17
Signature · 1 line
2.52.0
#300 lore raw

PATCH v18 2/29 vfio: make all functions internal

In reply to Anatoly Burakov

The VFIO API is an externally exported API because the original intent was to offer DMA mapping facilities to applications. However, practical usage of this API seems to be centered around drivers, so keeping this API exported to applications only creates needless API/ABI stability surface that has no added value.

Make the entire VFIO API internal-only and visible only to drivers.

---
 doc/api/doxy-api-index.md              |  3 +-
 doc/guides/rel_notes/deprecation.rst   |  6 ----
 doc/guides/rel_notes/release_26_11.rst |  8 +++++
 lib/eal/freebsd/eal.c                  | 30 ++++++++--------
 lib/eal/include/meson.build            |  2 +-
 lib/eal/include/rte_vfio.h             | 47 ++++++++++++++++++++++----
 lib/eal/linux/eal_vfio.c               | 32 +++++++++---------
 lib/eal/windows/eal.c                  |  4 +--
 8 files changed, 84 insertions(+), 48 deletions(-)
doc/api/doxy-api-index.md +1 -2
index 16827a602b5..62390f7be30 100644
@@ -37,8 +37,7 @@ The public API headers are grouped by topics:
   [latency](@ref rte_latencystats.h),
   [devargs](@ref rte_devargs.h),
   [PCI](@ref rte_pci.h),
-  [vdev](@ref rte_bus_vdev.h),
-  [vfio](@ref rte_vfio.h)
+  [vdev](@ref rte_bus_vdev.h)
 
 - **device specific**:
   [softnic](@ref rte_eth_softnic.h),
doc/guides/rel_notes/deprecation.rst +0 -6
index 81e90a699c1..f44f01a6e31 100644
@@ -29,12 +29,6 @@ Deprecation Notices
   Use the ``-S <service-corelist>`` parameter instead
   to specify the cores to be used for background services in DPDK.
 
-* eal: The entire VFIO API (``rte_vfio_*``) will be made internal only,
-  and will only be available to EAL and drivers.
-  Group-based API (``rte_vfio_*_group_*``) will be removed
-  and replaced with unified container device assignment API.
-  This change will be made in 26.11 release.
-
 * vdpa: The vDPA driver API will no longer offer ``get_vfio_group_fd``
   as part of its internal API. All drivers will be adjusted
   to use the new unified VFIO container device assignment API.
doc/guides/rel_notes/release_26_11.rst +8 -0
index e7921048a6b..a308742461e 100644
@@ -391,6 +391,10 @@ API Changes
     and ``rte_eth_err_handle_mode``
   * all remaining ``rte_flow`` item, action and async operation structures
 
+* vfio: The entire VFIO API (``rte_vfio_*``) was made internal.
+  These functions are now available only to EAL and drivers,
+  and are no longer part of the public API.
+
 
 ABI Changes
 -----------
@@ -407,6 +411,10 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =======================================================
 
+* vfio: The entire VFIO API (``rte_vfio_*``) was made internal.
+  These functions are now available only to EAL and drivers,
+  and are no longer part of the public ABI.
+
 
 Known Issues
 ------------
lib/eal/freebsd/eal.c +15 -15
index 8b1ba5b99ba..0fe54a9dd7c 100644
@@ -819,7 +819,7 @@ rte_eal_vfio_get_vf_token(__rte_unused rte_uuid_t vf_token)
 {
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_setup_device)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_setup_device)
 int rte_vfio_setup_device(__rte_unused const char *sysfs_base,
 		      __rte_unused const char *dev_addr,
 		      __rte_unused int *vfio_dev_fd,
@@ -829,7 +829,7 @@ int rte_vfio_setup_device(__rte_unused const char *sysfs_base,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_release_device)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_release_device)
 int rte_vfio_release_device(__rte_unused const char *sysfs_base,
 			__rte_unused const char *dev_addr,
 			__rte_unused int fd)
@@ -838,33 +838,33 @@ int rte_vfio_release_device(__rte_unused const char *sysfs_base,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_enable)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_enable)
 int rte_vfio_enable(__rte_unused const char *modname)
 {
 	rte_errno = ENOTSUP;
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_is_enabled)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_is_enabled)
 int rte_vfio_is_enabled(__rte_unused const char *modname)
 {
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_noiommu_is_enabled)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_noiommu_is_enabled)
 int rte_vfio_noiommu_is_enabled(void)
 {
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_clear_group)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_clear_group)
 int rte_vfio_clear_group(__rte_unused int vfio_group_fd)
 {
 	rte_errno = ENOTSUP;
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_num)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_group_num)
 int
 rte_vfio_get_group_num(__rte_unused const char *sysfs_base,
 		       __rte_unused const char *dev_addr,
@@ -874,7 +874,7 @@ rte_vfio_get_group_num(__rte_unused const char *sysfs_base,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_container_fd)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_container_fd)
 int
 rte_vfio_get_container_fd(void)
 {
@@ -882,7 +882,7 @@ rte_vfio_get_container_fd(void)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_fd)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_group_fd)
 int
 rte_vfio_get_group_fd(__rte_unused int iommu_group_num)
 {
@@ -890,7 +890,7 @@ rte_vfio_get_group_fd(__rte_unused int iommu_group_num)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_create)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_create)
 int
 rte_vfio_container_create(void)
 {
@@ -898,7 +898,7 @@ rte_vfio_container_create(void)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_destroy)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_destroy)
 int
 rte_vfio_container_destroy(__rte_unused int container_fd)
 {
@@ -906,7 +906,7 @@ rte_vfio_container_destroy(__rte_unused int container_fd)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_bind)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_group_bind)
 int
 rte_vfio_container_group_bind(__rte_unused int container_fd,
 		__rte_unused int iommu_group_num)
@@ -915,7 +915,7 @@ rte_vfio_container_group_bind(__rte_unused int container_fd,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_unbind)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_group_unbind)
 int
 rte_vfio_container_group_unbind(__rte_unused int container_fd,
 		__rte_unused int iommu_group_num)
@@ -924,7 +924,7 @@ rte_vfio_container_group_unbind(__rte_unused int container_fd,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_map)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_map)
 int
 rte_vfio_container_dma_map(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
@@ -935,7 +935,7 @@ rte_vfio_container_dma_map(__rte_unused int container_fd,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_unmap)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_unmap)
 int
 rte_vfio_container_dma_unmap(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
lib/eal/include/meson.build +1 -1
index aef5824e5f6..92821439182 100644
@@ -55,12 +55,12 @@ headers += files(
         'rte_trace_point_register.h',
         'rte_uuid.h',
         'rte_version.h',
-        'rte_vfio.h',
 )
 
 driver_sdk_headers = files(
         'bus_driver.h',
         'dev_driver.h',
+        'rte_vfio.h',
 )
 
 # special case install the generic headers, since they go in a subdir
lib/eal/include/rte_vfio.h +41 -6

214 lines not on this page · raw message

lib/eal/linux/eal_vfio.c +16 -16
index f1050ffa60a..33fa04feaf7 100644
@@ -532,7 +532,7 @@ get_vfio_cfg_by_container_fd(int container_fd)
 	return NULL;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_fd)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_group_fd)
 int
 rte_vfio_get_group_fd(int iommu_group_num)
 {
@@ -731,7 +731,7 @@ vfio_sync_default_container(void)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_clear_group)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_clear_group)
 int
 rte_vfio_clear_group(int vfio_group_fd)
 {
@@ -755,7 +755,7 @@ rte_vfio_clear_group(int vfio_group_fd)
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_setup_device)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_setup_device)
 int
 rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 		int *vfio_dev_fd, struct vfio_device_info *device_info)
@@ -1009,7 +1009,7 @@ rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_release_device)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_release_device)
 int
 rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
 		    int vfio_dev_fd)
@@ -1098,7 +1098,7 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
 	return ret;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_enable)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_enable)
 int
 rte_vfio_enable(const char *modname)
 {
@@ -1175,7 +1175,7 @@ rte_vfio_enable(const char *modname)
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_is_enabled)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_is_enabled)
 int
 rte_vfio_is_enabled(const char *modname)
 {
@@ -1215,7 +1215,7 @@ vfio_set_iommu_type(int vfio_container_fd)
 	return NULL;
 }
 
-RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_vfio_get_device_info, 24.03)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_device_info)
 int
 rte_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
 		int *vfio_dev_fd, struct vfio_device_info *device_info)
@@ -1349,7 +1349,7 @@ vfio_open_container_fd(bool mp_request)
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_container_fd)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_container_fd)
 int
 rte_vfio_get_container_fd(void)
 {
@@ -1363,7 +1363,7 @@ rte_vfio_get_container_fd(void)
 	return default_vfio_cfg->vfio_container_fd;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_num)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_get_group_num)
 int
 rte_vfio_get_group_num(const char *sysfs_base,
 		const char *dev_addr, int *iommu_group_num)
@@ -2034,7 +2034,7 @@ container_dma_unmap(struct vfio_config *vfio_cfg, uint64_t vaddr, uint64_t iova,
 	return ret;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_noiommu_is_enabled)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_noiommu_is_enabled)
 int
 rte_vfio_noiommu_is_enabled(void)
 {
@@ -2067,7 +2067,7 @@ rte_vfio_noiommu_is_enabled(void)
 	return c == 'Y';
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_create)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_create)
 int
 rte_vfio_container_create(void)
 {
@@ -2094,7 +2094,7 @@ rte_vfio_container_create(void)
 	return vfio_cfgs[i].vfio_container_fd;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_destroy)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_destroy)
 int
 rte_vfio_container_destroy(int container_fd)
 {
@@ -2120,7 +2120,7 @@ rte_vfio_container_destroy(int container_fd)
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_bind)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_group_bind)
 int
 rte_vfio_container_group_bind(int container_fd, int iommu_group_num)
 {
@@ -2135,7 +2135,7 @@ rte_vfio_container_group_bind(int container_fd, int iommu_group_num)
 	return vfio_get_group_fd(vfio_cfg, iommu_group_num);
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_unbind)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_group_unbind)
 int
 rte_vfio_container_group_unbind(int container_fd, int iommu_group_num)
 {
@@ -2176,7 +2176,7 @@ rte_vfio_container_group_unbind(int container_fd, int iommu_group_num)
 	return 0;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_map)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_map)
 int
 rte_vfio_container_dma_map(int container_fd, uint64_t vaddr, uint64_t iova,
 		uint64_t len)
@@ -2197,7 +2197,7 @@ rte_vfio_container_dma_map(int container_fd, uint64_t vaddr, uint64_t iova,
 	return container_dma_map(vfio_cfg, vaddr, iova, len);
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_unmap)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_unmap)
 int
 rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova,
 		uint64_t len)
lib/eal/windows/eal.c +2 -2
index 6dacae72353..de7a89a8291 100644
@@ -453,7 +453,7 @@ eal_asprintf(char **buffer, const char *format, ...)
 	return ret;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_map)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_map)
 int
 rte_vfio_container_dma_map(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
@@ -464,7 +464,7 @@ rte_vfio_container_dma_map(__rte_unused int container_fd,
 	return -1;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_unmap)
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_unmap)
 int
 rte_vfio_container_dma_unmap(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
Signature · 1 line
2.52.0
#301 lore raw

PATCH v18 3/29 bus/fslmc: decouple from EAL VFIO

In reply to Anatoly Burakov

FSLMC bus has its own VFIO implementation which is completely separate from one in EAL or rte_vfio. Yet, it references a couple of macros and uses a struct definition. Fully decoupling them is not a huge lift, so do that.

---
 drivers/bus/fslmc/fslmc_vfio.c | 50 +++++++++++++++++++++-------------
 drivers/bus/fslmc/meson.build  |  1 -
 2 files changed, 31 insertions(+), 20 deletions(-)
drivers/bus/fslmc/fslmc_vfio.c +31 -19
index 412b70e5ae7..8d39895bacf 100644
@@ -35,7 +35,6 @@
 #include <dev_driver.h>
 #include <rte_eal_memconfig.h>
 #include <rte_vfio.h>
-#include <eal_vfio.h>
 
 #include "private.h"
 #include "fslmc_vfio.h"
@@ -73,8 +72,21 @@ struct fslmc_dmaseg_list fslmc_iosegs =
 static uint64_t fslmc_mem_va2iova = RTE_BAD_IOVA;
 static int fslmc_mem_map_num;
 
+#define FSLMC_VFIO_SOCKET_OK 0x0
+#define FSLMC_VFIO_SOCKET_NO_FD 0x1
+#define FSLMC_VFIO_SOCKET_ERR 0xFF
+
+struct fslmc_vfio_mp_param {
+	int req;
+	int result;
+	union {
+		int group_num;
+		int iommu_type_id;
+	};
+};
+
 struct fslmc_mem_param {
-	struct vfio_mp_param mp_param;
+	struct fslmc_vfio_mp_param mp_param;
 	struct fslmc_dmaseg_list memsegs;
 	struct fslmc_dmaseg_list iosegs;
 	uint64_t mem_va2iova;
@@ -386,7 +398,7 @@ fslmc_vfio_open_group_fd(const char *group_name)
 	struct rte_mp_msg mp_req, *mp_rep;
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
-	struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param;
+	struct fslmc_vfio_mp_param *p = (struct fslmc_vfio_mp_param *)mp_req.param;
 	int iommu_group_num, ret;
 
 	vfio_group_fd = fslmc_vfio_group_fd_by_name(group_name);
@@ -417,10 +429,10 @@ fslmc_vfio_open_group_fd(const char *group_name)
 	if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
 	    mp_reply.nb_received == 1) {
 		mp_rep = &mp_reply.msgs[0];
-		p = (struct vfio_mp_param *)mp_rep->param;
-		if (p->result == SOCKET_OK && mp_rep->num_fds == 1)
+		p = (struct fslmc_vfio_mp_param *)mp_rep->param;
+		if (p->result == FSLMC_VFIO_SOCKET_OK && mp_rep->num_fds == 1)
 			vfio_group_fd = mp_rep->fds[0];
-		else if (p->result == SOCKET_NO_FD)
+		else if (p->result == FSLMC_VFIO_SOCKET_NO_FD)
 			DPAA2_BUS_ERR("Bad VFIO group fd");
 	}
 
@@ -490,7 +502,7 @@ fslmc_vfio_open_container_fd(void)
 	struct rte_mp_msg mp_req, *mp_rep;
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
-	struct vfio_mp_param *p = (void *)mp_req.param;
+	struct fslmc_vfio_mp_param *p = (void *)mp_req.param;
 
 	if (fslmc_vfio_container_fd() > 0)
 		return fslmc_vfio_container_fd();
@@ -551,7 +563,7 @@ fslmc_vfio_open_container_fd(void)
 
 	mp_rep = &mp_reply.msgs[0];
 	p = (void *)mp_rep->param;
-	if (p->result == SOCKET_OK && mp_rep->num_fds == 1) {
+	if (p->result == FSLMC_VFIO_SOCKET_OK && mp_rep->num_fds == 1) {
 		vfio_container_fd = mp_rep->fds[0];
 		free(mp_reply.msgs);
 	}
@@ -594,8 +606,8 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 	int fd = -1;
 	int ret;
 	struct rte_mp_msg reply;
-	struct vfio_mp_param *r = (void *)reply.param;
-	const struct vfio_mp_param *m = (const void *)msg->param;
+	struct fslmc_vfio_mp_param *r = (void *)reply.param;
+	const struct fslmc_vfio_mp_param *m = (const void *)msg->param;
 	struct fslmc_mem_param *map;
 
 	if (msg->len_param != sizeof(*m)) {
@@ -612,13 +624,13 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 		r->group_num = m->group_num;
 		fd = fslmc_vfio_group_fd_by_id(m->group_num);
 		if (fd < 0) {
-			r->result = SOCKET_ERR;
+			r->result = FSLMC_VFIO_SOCKET_ERR;
 		} else if (!fd) {
 			/* if group exists but isn't bound to VFIO driver */
-			r->result = SOCKET_NO_FD;
+			r->result = FSLMC_VFIO_SOCKET_NO_FD;
 		} else {
 			/* if group exists and is bound to VFIO driver */
-			r->result = SOCKET_OK;
+			r->result = FSLMC_VFIO_SOCKET_OK;
 			reply.num_fds = 1;
 			reply.fds[0] = fd;
 		}
@@ -628,9 +640,9 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 		r->req = FSLMC_VFIO_SOCKET_REQ_CONTAINER;
 		fd = fslmc_vfio_container_fd();
 		if (fd <= 0) {
-			r->result = SOCKET_ERR;
+			r->result = FSLMC_VFIO_SOCKET_ERR;
 		} else {
-			r->result = SOCKET_OK;
+			r->result = FSLMC_VFIO_SOCKET_OK;
 			reply.num_fds = 1;
 			reply.fds[0] = fd;
 		}
@@ -640,7 +652,7 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 		map = (void *)reply.param;
 		r = &map->mp_param;
 		r->req = FSLMC_VFIO_SOCKET_REQ_MEM;
-		r->result = SOCKET_OK;
+		r->result = FSLMC_VFIO_SOCKET_OK;
 		map->memsegs = fslmc_memsegs;
 		map->iosegs = fslmc_iosegs;
 		map->mem_va2iova = fslmc_mem_va2iova;
@@ -666,19 +678,19 @@ fslmc_vfio_mp_sync_mem_req(void)
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
 	int ret = 0;
-	struct vfio_mp_param *mp_param;
+	struct fslmc_vfio_mp_param *mp_param;
 	struct fslmc_mem_param *mem_rsp;
 
 	mp_param = (void *)mp_req.param;
 	memset(&mp_req, 0, sizeof(struct rte_mp_msg));
 	mp_param->req = FSLMC_VFIO_SOCKET_REQ_MEM;
 	rte_strscpy(mp_req.name, FSLMC_VFIO_MP, sizeof(mp_req.name));
-	mp_req.len_param = sizeof(struct vfio_mp_param);
+	mp_req.len_param = sizeof(struct fslmc_vfio_mp_param);
 	if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
 		mp_reply.nb_received == 1) {
 		mp_rep = &mp_reply.msgs[0];
 		mem_rsp = (struct fslmc_mem_param *)mp_rep->param;
-		if (mem_rsp->mp_param.result == SOCKET_OK) {
+		if (mem_rsp->mp_param.result == FSLMC_VFIO_SOCKET_OK) {
 			fslmc_memsegs = mem_rsp->memsegs;
 			fslmc_mem_va2iova = mem_rsp->mem_va2iova;
 			fslmc_mem_map_num = mem_rsp->mem_map_num;
drivers/bus/fslmc/meson.build +0 -1
index 50d9e91a37f..55f9d2e8081 100644
@@ -30,4 +30,3 @@ sources = files(
 )
 
 includes += include_directories('mc', 'qbman/include', 'portal')
-includes += include_directories('../../../lib/eal/linux')
Signature · 1 line
2.52.0
#302 lore raw

PATCH v18 4/29 vfio: decouple EAL from VFIO internals

In reply to Anatoly Burakov

Currently, the multiprocess cleanup for VFIO is called via an internal-only API, and this is the only thing eal_vfio.h is used for in EAL. In order to make eal_vfio.h truly VFIO-internal, export a cleanup function from rte_vfio API instead, and call that. This allows us to remove all EAL references to eal_vfio.h in non-VFIO related files.

---
 lib/eal/freebsd/eal.c      | 6 ++++++
 lib/eal/include/rte_vfio.h | 9 +++++++++
 lib/eal/linux/eal.c        | 3 +--
 lib/eal/linux/eal_vfio.c   | 7 +++++++
 lib/eal/windows/eal.c      | 6 ++++++
 5 files changed, 29 insertions(+), 2 deletions(-)
lib/eal/freebsd/eal.c +6 -0
index 0fe54a9dd7c..991ca450640 100644
@@ -845,6 +845,12 @@ int rte_vfio_enable(__rte_unused const char *modname)
 	return -1;
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
+void
+rte_vfio_cleanup(void)
+{
+}
+
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_is_enabled)
 int rte_vfio_is_enabled(__rte_unused const char *modname)
 {
lib/eal/include/rte_vfio.h +9 -0
index 0ddeb08f94a..e76181c83cc 100644
@@ -109,6 +109,15 @@ int rte_vfio_release_device(const char *sysfs_base, const char *dev_addr, int fd
 __rte_internal
 int rte_vfio_enable(const char *modname);
 
+/**
+ * @internal
+ * Cleanup VFIO resources.
+ *
+ * This function is only relevant to Linux.
+ */
+__rte_internal
+void rte_vfio_cleanup(void);
+
 /**
  * @internal
  * Check whether a VFIO-related kmod is enabled.
lib/eal/linux/eal.c +1 -2
index fc2e9b8c0e8..5577bab24a2 100644
@@ -54,7 +54,6 @@
 #include "eal_memcfg.h"
 #include "eal_trace.h"
 #include "eal_options.h"
-#include "eal_vfio.h"
 #include "hotplug_mp.h"
 #include "log_internal.h"
 
@@ -986,7 +985,7 @@ rte_eal_cleanup(void)
 
 	rte_service_finalize();
 	eal_bus_cleanup();
-	vfio_mp_sync_cleanup();
+	rte_vfio_cleanup();
 	rte_mp_channel_cleanup();
 	rte_eal_alarm_cleanup();
 	rte_trace_save();
lib/eal/linux/eal_vfio.c +7 -0
index 33fa04feaf7..6c77076bc3e 100644
@@ -2217,3 +2217,10 @@ rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova,
 
 	return container_dma_unmap(vfio_cfg, vaddr, iova, len);
 }
+
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
+void
+rte_vfio_cleanup(void)
+{
+	vfio_mp_sync_cleanup();
+}
lib/eal/windows/eal.c +6 -0
index de7a89a8291..b8771d4d858 100644
@@ -152,6 +152,12 @@ rte_eal_cleanup(void)
 	return 0;
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
+void
+rte_vfio_cleanup(void)
+{
+}
+
 /* Launch threads, called at application init(). */
 RTE_EXPORT_SYMBOL(rte_eal_init)
 int
Signature · 1 line
2.52.0
#303 lore raw

PATCH v18 5/29 vhost: check DMA capability only once

In reply to Anatoly Burakov

Currently, vhost async copy feature will check if VFIO supports DMA mapping on every attempt to add/remove memory region or set memory table. This is not necessary, so instead check this once at new vhost connection, and store that value for future use.

---
 lib/vhost/socket.c     |  5 ++++-
 lib/vhost/vhost.h      |  1 +
 lib/vhost/vhost_user.c | 10 +++++-----
 3 files changed, 10 insertions(+), 6 deletions(-)
lib/vhost/socket.c +4 -1
index 0943b3e9bb6..a8f58c95e83 100644
@@ -17,6 +17,7 @@
 #include <eal_export.h>
 #include <rte_thread.h>
 #include <rte_log.h>
+#include <rte_vfio.h>
 
 #include "fd_man.h"
 #include "vduse.h"
@@ -242,8 +243,10 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 	if (vsocket->async_copy) {
 		dev = get_device(vid);
 
-		if (dev)
+		if (dev != NULL) {
 			dev->async_copy = 1;
+			dev->dma_map_available = rte_vfio_is_enabled("vfio");
+		}
 	}
 
 	VHOST_CONFIG_LOG(vsocket->path, INFO, "new device, handle is %d", vid);
lib/vhost/vhost.h +1 -0
index bb4708aed5e..75736eed3b5 100644
@@ -499,6 +499,7 @@ struct __rte_cache_aligned virtio_net {
 	RTE_ATOMIC(int16_t)	broadcast_rarp;
 	uint32_t		nr_vring;
 	int			async_copy;
+	bool			dma_map_available;
 
 	int			extbuf;
 	int			linearbuf;
lib/vhost/vhost_user.c +5 -5
index 020c993b299..2d91722fcc0 100644
@@ -267,7 +267,7 @@ free_all_mem_regions(struct virtio_net *dev)
 	if (!dev || !dev->mem)
 		return;
 
-	if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+	if (dev->async_copy && dev->dma_map_available)
 		async_dma_map(dev, false);
 
 	for (i = 0; i < VHOST_MEMORY_MAX_NREGIONS; i++) {
@@ -1564,7 +1564,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev,
 		dev->mem->nregions++;
 	}
 
-	if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+	if (dev->async_copy && dev->dma_map_available)
 		async_dma_map(dev, true);
 
 	if (vhost_user_postcopy_register(dev, main_fd, ctx) < 0)
@@ -1750,7 +1750,7 @@ vhost_user_add_mem_reg(struct virtio_net **pdev,
 
 	dev->mem->nregions++;
 
-	if (dev->async_copy && rte_vfio_is_enabled("vfio")) {
+	if (dev->async_copy && dev->dma_map_available) {
 		if (async_dma_map_region(dev, reg, true) < 0)
 			goto free_new_region_no_dma;
 	}
@@ -1791,7 +1791,7 @@ vhost_user_add_mem_reg(struct virtio_net **pdev,
 	return RTE_VHOST_MSG_RESULT_OK;
 
 free_new_region:
-	if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+	if (dev->async_copy && dev->dma_map_available)
 		async_dma_map_region(dev, reg, false);
 free_new_region_no_dma:
 	remove_guest_pages(dev, reg);
@@ -1827,7 +1827,7 @@ vhost_user_rem_mem_reg(struct virtio_net **pdev,
 		if (region->userspace_addr == current_region->guest_user_addr
 			&& region->guest_phys_addr == current_region->guest_phys_addr
 			&& region->memory_size == current_region->size) {
-			if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+			if (dev->async_copy && dev->dma_map_available)
 				async_dma_map_region(dev, current_region, false);
 			if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))
 				vhost_user_iotlb_cache_remove(dev,
Signature · 1 line
2.52.0
#304 lore raw

PATCH v18 6/29 vfio: do proper teardown on VFIO cleanup

In reply to Anatoly Burakov

Currently, VFIO cleanup only unregisters multiprocess callback, but does not destroy containers, groups, and user mem maps. Do all of that on VFIO cleanup. We don't actually need a per-config enabled flag, as container fd should be enough to determine whether the config is active.

While we're at it, also harden the API against repeated initialization and attempts at using the API without having VFIO initialized.

---
 lib/eal/linux/eal_vfio.c | 154 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 149 insertions(+), 5 deletions(-)
lib/eal/linux/eal_vfio.c +149 -5
index 6c77076bc3e..8959a161530 100644
@@ -46,7 +46,6 @@ struct user_mem_maps {
 };
 
 struct vfio_config {
-	int vfio_enabled;
 	int vfio_container_fd;
 	int vfio_active_groups;
 	const struct vfio_iommu_type *vfio_iommu_type;
@@ -58,6 +57,9 @@ struct vfio_config {
 static struct vfio_config vfio_cfgs[RTE_MAX_VFIO_CONTAINERS];
 static struct vfio_config *default_vfio_cfg = &vfio_cfgs[0];
 
+/* whether VFIO is enabled (usable) in this process */
+static bool vfio_enabled;
+
 static int vfio_type1_dma_map(int);
 static int vfio_type1_dma_mem_map(int, uint64_t, uint64_t, uint64_t, int);
 static int vfio_spapr_dma_map(int);
@@ -538,6 +540,11 @@ rte_vfio_get_group_fd(int iommu_group_num)
 {
 	struct vfio_config *vfio_cfg;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	/* get the vfio_config it belongs to */
 	vfio_cfg = get_vfio_cfg_by_group_num(iommu_group_num);
 	vfio_cfg = vfio_cfg ? vfio_cfg : default_vfio_cfg;
@@ -686,7 +693,7 @@ vfio_sync_default_container(void)
 		return -1;
 
 	/* default container fd should have been opened in rte_vfio_enable() */
-	if (!default_vfio_cfg->vfio_enabled ||
+	if (!vfio_enabled ||
 			default_vfio_cfg->vfio_container_fd < 0) {
 		EAL_LOG(ERR, "VFIO support is not initialized");
 		return -1;
@@ -738,6 +745,11 @@ rte_vfio_clear_group(int vfio_group_fd)
 	int i;
 	struct vfio_config *vfio_cfg;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	vfio_cfg = get_vfio_cfg_by_group_fd(vfio_group_fd);
 	if (vfio_cfg == NULL) {
 		EAL_LOG(ERR, "Invalid VFIO group fd!");
@@ -773,6 +785,11 @@ rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	/* get group number */
 	ret = rte_vfio_get_group_num(sysfs_base, dev_addr, &iommu_group_num);
 	if (ret == 0) {
@@ -1019,6 +1036,11 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
 	int iommu_group_num;
 	int ret;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	/* we don't want any DMA mapping messages to come while we're detaching
 	 * VFIO device, because this might be the last device and we might need
 	 * to unregister the callback.
@@ -1111,6 +1133,9 @@ rte_vfio_enable(const char *modname)
 
 	rte_spinlock_recursive_t lock = RTE_SPINLOCK_RECURSIVE_INITIALIZER;
 
+	if (vfio_enabled)
+		return 0;
+
 	for (i = 0; i < RTE_DIM(vfio_cfgs); i++) {
 		vfio_cfgs[i].vfio_container_fd = -1;
 		vfio_cfgs[i].vfio_active_groups = 0;
@@ -1167,7 +1192,7 @@ rte_vfio_enable(const char *modname)
 	/* check if we have VFIO driver enabled */
 	if (default_vfio_cfg->vfio_container_fd != -1) {
 		EAL_LOG(INFO, "VFIO support initialized");
-		default_vfio_cfg->vfio_enabled = 1;
+		vfio_enabled = true;
 	} else {
 		EAL_LOG(NOTICE, "VFIO support could not be initialized");
 	}
@@ -1180,12 +1205,15 @@ int
 rte_vfio_is_enabled(const char *modname)
 {
 	const int mod_available = rte_eal_check_module(modname) > 0;
-	return default_vfio_cfg->vfio_enabled && mod_available;
+	return vfio_enabled && mod_available;
 }
 
 int
 vfio_get_iommu_type(void)
 {
+	if (!vfio_enabled)
+		return -1;
+
 	if (default_vfio_cfg->vfio_iommu_type == NULL)
 		return -1;
 
@@ -1222,6 +1250,11 @@ rte_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
 {
 	int ret;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	if (device_info == NULL || *vfio_dev_fd < 0)
 		return -1;
 
@@ -1357,7 +1390,7 @@ rte_vfio_get_container_fd(void)
 	 * The default container is set up during rte_vfio_enable().
 	 * This function does not create a new container.
 	 */
-	if (!default_vfio_cfg->vfio_enabled)
+	if (!vfio_enabled)
 		return -1;
 
 	return default_vfio_cfg->vfio_container_fd;
@@ -1373,6 +1406,11 @@ rte_vfio_get_group_num(const char *sysfs_base,
 	char *tok[16], *group_tok, *end;
 	int ret;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	memset(linkname, 0, sizeof(linkname));
 	memset(filename, 0, sizeof(filename));
 
@@ -2073,6 +2111,11 @@ rte_vfio_container_create(void)
 {
 	unsigned int i;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	/* Find an empty slot to store new vfio config */
 	for (i = 1; i < RTE_DIM(vfio_cfgs); i++) {
 		if (vfio_cfgs[i].vfio_container_fd == -1)
@@ -2101,6 +2144,16 @@ rte_vfio_container_destroy(int container_fd)
 	struct vfio_config *vfio_cfg;
 	unsigned int i;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
+	if (container_fd == RTE_VFIO_DEFAULT_CONTAINER_FD) {
+		EAL_LOG(ERR, "Cannot destroy default VFIO container");
+		return -1;
+	}
+
 	vfio_cfg = get_vfio_cfg_by_container_fd(container_fd);
 	if (vfio_cfg == NULL) {
 		EAL_LOG(ERR, "Invalid VFIO container fd");
@@ -2126,6 +2179,11 @@ rte_vfio_container_group_bind(int container_fd, int iommu_group_num)
 {
 	struct vfio_config *vfio_cfg;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	vfio_cfg = get_vfio_cfg_by_container_fd(container_fd);
 	if (vfio_cfg == NULL) {
 		EAL_LOG(ERR, "Invalid VFIO container fd");
@@ -2143,6 +2201,11 @@ rte_vfio_container_group_unbind(int container_fd, int iommu_group_num)
 	struct vfio_config *vfio_cfg;
 	unsigned int i;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	vfio_cfg = get_vfio_cfg_by_container_fd(container_fd);
 	if (vfio_cfg == NULL) {
 		EAL_LOG(ERR, "Invalid VFIO container fd");
@@ -2183,6 +2246,11 @@ rte_vfio_container_dma_map(int container_fd, uint64_t vaddr, uint64_t iova,
 {
 	struct vfio_config *vfio_cfg;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	if (len == 0) {
 		rte_errno = EINVAL;
 		return -1;
@@ -2204,6 +2272,11 @@ rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova,
 {
 	struct vfio_config *vfio_cfg;
 
+	if (!vfio_enabled) {
+		rte_errno = ENODEV;
+		return -1;
+	}
+
 	if (len == 0) {
 		rte_errno = EINVAL;
 		return -1;
@@ -2218,9 +2291,80 @@ rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr, uint64_t iova,
 	return container_dma_unmap(vfio_cfg, vaddr, iova, len);
 }
 
+static int
+vfio_cleanup_config(struct vfio_config *vfio_cfg)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(vfio_cfg->vfio_groups); i++) {
+		struct vfio_group *group = &vfio_cfg->vfio_groups[i];
+
+		if (group->group_num == -1)
+			continue;
+		if (group->devices != 0) {
+			EAL_LOG(ERR, "Cannot cleanup VFIO group %d with %d devices",
+				group->group_num, group->devices);
+			continue;
+		}
+		if (group->fd >= 0 && close(group->fd) < 0) {
+			EAL_LOG(ERR, "Cannot close VFIO group %d: %s",
+				group->group_num, strerror(errno));
+			continue;
+		}
+
+		group->group_num = -1;
+		group->fd = -1;
+		group->devices = 0;
+		vfio_cfg->vfio_active_groups--;
+	}
+
+	/* if there are still active groups, we cannot cleanup the container */
+	if (vfio_cfg->vfio_active_groups != 0) {
+		EAL_LOG(ERR, "Cannot cleanup VFIO container with %d active groups",
+			vfio_cfg->vfio_active_groups);
+		return -1;
+	}
+
+	if (vfio_cfg->vfio_container_fd >= 0 &&
+			close(vfio_cfg->vfio_container_fd) < 0) {
+		EAL_LOG(ERR, "Cannot close VFIO container: %s", strerror(errno));
+		return -1;
+	}
+
+	vfio_cfg->vfio_container_fd = -1;
+	vfio_cfg->vfio_iommu_type = NULL;
+
+	vfio_cfg->mem_maps.n_maps = 0;
+	memset(vfio_cfg->mem_maps.maps, 0, sizeof(vfio_cfg->mem_maps.maps));
+
+	return 0;
+}
+
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
 void
 rte_vfio_cleanup(void)
 {
+	unsigned int i;
+	bool stuck = false;
+
+	if (!vfio_enabled)
+		return;
+
 	vfio_mp_sync_cleanup();
+
+	/* mem events can only be unregistered from the primary process */
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		rte_mem_event_callback_unregister(VFIO_MEM_EVENT_CLB_NAME, NULL);
+
+	/* cleanup all initialized configs */
+	for (i = 0; i < RTE_DIM(vfio_cfgs); i++) {
+		if (vfio_cfgs[i].vfio_container_fd != -1)
+			stuck |= vfio_cleanup_config(&vfio_cfgs[i]) != 0;
+	}
+
+	/* failed to deinitialize some configs, so don't set VFIO as disabled */
+	if (stuck)
+		return;
+
+	vfio_enabled = false;
 }
Signature · 1 line
2.52.0
#305 lore raw

PATCH v18 7/29 eal: move kernel module check function into VFIO

In reply to Anatoly Burakov

EAL provides a "check if a kernel module is loaded" function, but the only consumer of that function is VFIO. Move it and make it internal to VFIO.

---
 lib/eal/common/eal_private.h | 14 ------------
 lib/eal/linux/eal.c          | 35 ------------------------------
 lib/eal/linux/eal_vfio.c     | 41 ++++++++++++++++++++++++++++++++++--
 3 files changed, 39 insertions(+), 51 deletions(-)
lib/eal/common/eal_private.h +0 -14
index 6340bab8be0..8507791ec26 100644
@@ -206,20 +206,6 @@ int rte_eal_alarm_init(void);
  */
 void rte_eal_alarm_cleanup(void);
 
-/**
- * Function is to check if the kernel module(like, vfio, vfio_iommu_type1,
- * etc.) loaded.
- *
- * @param module_name
- *	The module's name which need to be checked
- *
- * @return
- *	-1 means some error happens(NULL pointer or open failure)
- *	0  means the module not loaded
- *	1  means the module loaded
- */
-int rte_eal_check_module(const char *module_name);
-
 /**
  * Memory reservation flags.
  */
lib/eal/linux/eal.c +0 -35
index 5577bab24a2..1d0894e7eab 100644
@@ -17,9 +17,7 @@
 #include <fnmatch.h>
 #include <stddef.h>
 #include <errno.h>
-#include <limits.h>
 #include <sys/mman.h>
-#include <sys/stat.h>
 #if defined(RTE_ARCH_X86)
 #include <sys/io.h>
 #endif
@@ -1028,36 +1026,3 @@ rte_eal_vfio_get_vf_token(rte_uuid_t vf_token)
 	rte_uuid_copy(vf_token, cfg->vfio_vf_token);
 }
 
-int
-rte_eal_check_module(const char *module_name)
-{
-	char sysfs_mod_name[PATH_MAX];
-	struct stat st;
-	int n;
-
-	if (NULL == module_name)
-		return -1;
-
-	/* Check if there is sysfs mounted */
-	if (stat("/sys/module", &st) != 0) {
-		EAL_LOG(DEBUG, "sysfs is not mounted! error %i (%s)",
-			errno, strerror(errno));
-		return -1;
-	}
-
-	/* A module might be built-in, therefore try sysfs */
-	n = snprintf(sysfs_mod_name, PATH_MAX, "/sys/module/%s", module_name);
-	if (n < 0 || n > PATH_MAX) {
-		EAL_LOG(DEBUG, "Could not format module path");
-		return -1;
-	}
-
-	if (stat(sysfs_mod_name, &st) != 0) {
-		EAL_LOG(DEBUG, "Module %s not found! error %i (%s)",
-		        sysfs_mod_name, errno, strerror(errno));
-		return 0;
-	}
-
-	/* Module has been found */
-	return 1;
-}
lib/eal/linux/eal_vfio.c +39 -2

68 lines not on this page · raw message

Signature · 1 line
2.52.0
#306 lore raw

PATCH v18 8/29 vfio: remove modname parameter from init

In reply to Anatoly Burakov

All VFIO initialization always happens with "vfio" module, and now that the API is not public, having a way to override the module name seems redundant as there is not going to be a use case that calls into rte_vfio_enable that isn't coming from EAL init. So, remove the parameter, and hardcode the modname to "vfio" instead.

---
 drivers/bus/pci/linux/pci_vfio.c | 2 +-
 lib/eal/freebsd/eal.c            | 2 +-
 lib/eal/include/rte_vfio.h       | 7 ++-----
 lib/eal/linux/eal.c              | 2 +-
 lib/eal/linux/eal_vfio.c         | 4 ++--
 5 files changed, 7 insertions(+), 10 deletions(-)
drivers/bus/pci/linux/pci_vfio.c +1 -1
index bc5c5c24990..f3791cce982 100644
@@ -1303,7 +1303,7 @@ pci_vfio_is_enabled(void)
 	int status = rte_vfio_is_enabled("vfio_pci");
 
 	if (!status) {
-		rte_vfio_enable("vfio");
+		rte_vfio_enable();
 		status = rte_vfio_is_enabled("vfio_pci");
 	}
 	return status;
lib/eal/freebsd/eal.c +1 -1
index 991ca450640..5628d60d589 100644
@@ -839,7 +839,7 @@ int rte_vfio_release_device(__rte_unused const char *sysfs_base,
 }
 
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_enable)
-int rte_vfio_enable(__rte_unused const char *modname)
+int rte_vfio_enable(void)
 {
 	rte_errno = ENOTSUP;
 	return -1;
lib/eal/include/rte_vfio.h +2 -5
index e76181c83cc..b53ce56a8dc 100644
@@ -94,20 +94,17 @@ int rte_vfio_release_device(const char *sysfs_base, const char *dev_addr, int fd
 
 /**
  * @internal
- * Enable a VFIO-related kmod.
+ * Initialize VFIO.
  *
  * This function is only relevant to linux and will return
  * an error on BSD.
  *
- * @param modname
- *   kernel module name.
- *
  * @return
  *   0 on success.
  *   <0 on failure.
  */
 __rte_internal
-int rte_vfio_enable(const char *modname);
+int rte_vfio_enable(void);
 
 /**
  * @internal
lib/eal/linux/eal.c +1 -1
index 1d0894e7eab..3f92cc32ebd 100644
@@ -769,7 +769,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (rte_vfio_enable("vfio")) {
+	if (rte_vfio_enable()) {
 		rte_eal_init_alert("Cannot init VFIO");
 		rte_errno = EAGAIN;
 		goto err_out;
lib/eal/linux/eal_vfio.c +2 -2
index ce247362662..41bf401dec6 100644
@@ -1159,7 +1159,7 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
 
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_enable)
 int
-rte_vfio_enable(const char *modname)
+rte_vfio_enable(void)
 {
 	/* initialize group list */
 	unsigned int i, j;
@@ -1189,7 +1189,7 @@ rte_vfio_enable(const char *modname)
 	EAL_LOG(DEBUG, "Probing VFIO support...");
 
 	/* check if vfio module is loaded */
-	vfio_available = vfio_check_module(modname);
+	vfio_available = vfio_check_module("vfio");
 
 	/* return error directly */
 	if (vfio_available == -1) {
Signature · 1 line
2.52.0
#307 lore raw

PATCH v18 9/29 vfio: add module check API

In reply to Anatoly Burakov

Currently, there are a few users of VFIO API that depend on checking if a specific kernel module is loaded. This call is coupled with checking if VFIO is enabled (which should not be the case, as these are orthogonal), and depending on context different modules are checked with a string literal (which is suboptimal as well).

Provide a new API in VFIO to check for whether a specific VFIO-related kernel module is loaded, decouple it from "enabled" check, and adjust all callers accordingly.

---
 drivers/bus/pci/linux/pci_vfio.c | 11 ++++++-----
 lib/eal/freebsd/eal.c            |  8 +++++++-
 lib/eal/include/rte_vfio.h       | 34 +++++++++++++++++++++++++++-----
 lib/eal/linux/eal_vfio.c         | 27 +++++++++++++++++++------
 lib/vhost/socket.c               |  3 ++-
 5 files changed, 65 insertions(+), 18 deletions(-)
drivers/bus/pci/linux/pci_vfio.c +6 -5
index f3791cce982..ed713a005f6 100644
@@ -1300,11 +1300,12 @@ pci_vfio_mmio_write(const struct rte_pci_device *dev, int bar,
 int
 pci_vfio_is_enabled(void)
 {
-	int status = rte_vfio_is_enabled("vfio_pci");
+	int status;
 
-	if (!status) {
-		rte_vfio_enable();
-		status = rte_vfio_is_enabled("vfio_pci");
-	}
+	if (rte_vfio_enable() < 0)
+		return 0;
+
+	status = rte_vfio_is_enabled() &&
+		rte_vfio_module_is_loaded(RTE_VFIO_MODULE_VFIO_PCI);
 	return status;
 }
lib/eal/freebsd/eal.c +7 -1
index 5628d60d589..a2060978fe1 100644
@@ -851,8 +851,14 @@ rte_vfio_cleanup(void)
 {
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_module_is_loaded)
+int rte_vfio_module_is_loaded(__rte_unused enum rte_vfio_module module)
+{
+	return 0;
+}
+
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_is_enabled)
-int rte_vfio_is_enabled(__rte_unused const char *modname)
+int rte_vfio_is_enabled(void)
 {
 	return 0;
 }
lib/eal/include/rte_vfio.h +29 -5
index b53ce56a8dc..da003c33a56 100644
@@ -39,6 +39,17 @@ struct vfio_device_info;
 
 #define RTE_VFIO_DEFAULT_CONTAINER_FD (-1)
 
+/**
+ * @enum rte_vfio_module
+ * VFIO kernel modules.
+ *
+ * These values identify kernel modules used by VFIO.
+ */
+enum rte_vfio_module {
+	RTE_VFIO_MODULE_VFIO,     /**< Core VFIO module. */
+	RTE_VFIO_MODULE_VFIO_PCI, /**< VFIO PCI module. */
+};
+
 /**
  * @internal
  * Setup vfio_cfg for the device identified by its address.
@@ -117,19 +128,32 @@ void rte_vfio_cleanup(void);
 
 /**
  * @internal
- * Check whether a VFIO-related kmod is enabled.
+ * Check whether a VFIO module is loaded.
  *
  * This function is only relevant to Linux.
  *
- * @param modname
- *   kernel module name.
+ * @param module
+ *   VFIO module to check.
  *
  * @return
- *   1 if true.
+ *   1 if the requested module is loaded.
  *   0 otherwise.
  */
 __rte_internal
-int rte_vfio_is_enabled(const char *modname);
+int rte_vfio_module_is_loaded(enum rte_vfio_module module);
+
+/**
+ * @internal
+ * Check whether VFIO was initialized.
+ *
+ * This function is only relevant to Linux.
+ *
+ * @return
+ *   1 if VFIO was initialized.
+ *   0 otherwise.
+ */
+__rte_internal
+int rte_vfio_is_enabled(void);
 
 /**
  * @internal
lib/eal/linux/eal_vfio.c +21 -6
index 41bf401dec6..780c344bf70 100644
@@ -64,14 +64,23 @@ static struct vfio_config *default_vfio_cfg = &vfio_cfgs[0];
 static bool vfio_enabled;
 
 static int
-vfio_check_module(const char *module_name)
+vfio_check_module(enum rte_vfio_module module)
 {
+	const char *module_name;
 	char sysfs_mod_name[PATH_MAX];
 	struct stat st;
 	int n;
 
-	if (NULL == module_name)
+	switch (module) {
+	case RTE_VFIO_MODULE_VFIO:
+		module_name = "vfio";
+		break;
+	case RTE_VFIO_MODULE_VFIO_PCI:
+		module_name = "vfio_pci";
+		break;
+	default:
 		return -1;
+	}
 
 	/* Check if there is sysfs mounted */
 	if (stat("/sys/module", &st) != 0) {
@@ -1189,7 +1198,7 @@ rte_vfio_enable(void)
 	EAL_LOG(DEBUG, "Probing VFIO support...");
 
 	/* check if vfio module is loaded */
-	vfio_available = vfio_check_module("vfio");
+	vfio_available = vfio_check_module(RTE_VFIO_MODULE_VFIO);
 
 	/* return error directly */
 	if (vfio_available == -1) {
@@ -1237,12 +1246,18 @@ rte_vfio_enable(void)
 	return 0;
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_module_is_loaded)
+int
+rte_vfio_module_is_loaded(enum rte_vfio_module module)
+{
+	return vfio_check_module(module) > 0;
+}
+
 RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_is_enabled)
 int
-rte_vfio_is_enabled(const char *modname)
+rte_vfio_is_enabled(void)
 {
-	const int mod_available = vfio_check_module(modname) > 0;
-	return vfio_enabled && mod_available;
+	return vfio_enabled;
 }
 
 int
lib/vhost/socket.c +2 -1
index a8f58c95e83..1e38ea76474 100644
@@ -245,7 +245,8 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 
 		if (dev != NULL) {
 			dev->async_copy = 1;
-			dev->dma_map_available = rte_vfio_is_enabled("vfio");
+			dev->dma_map_available = rte_vfio_is_enabled() &&
+					rte_vfio_module_is_loaded(RTE_VFIO_MODULE_VFIO);
 		}
 	}
 
Signature · 1 line
2.52.0
#308 lore raw

PATCH v18 10/29 bus/pci: decouple PCI bus driver from VFIO

In reply to Anatoly Burakov

Currently, because the PCI bus driver will use VFIO API and the bus driver definitions are shared across OS's, this results in each PCI bus driver linking to VFIO API even though only Linux needs it.

To fix it, move OS-specific PCI bus driver definitions into their respective source files (so that each bus still shares common driver op implementations), and only call VFIO API on Linux with a custom DMA map op implementation. This allows us to remove all of the VFIO stubs from non-Linux EAL code.

---
 drivers/bus/pci/bsd/pci.c     |  24 ++++++
 drivers/bus/pci/linux/pci.c   |  55 +++++++++++++
 drivers/bus/pci/pci_common.c  |  64 +++-------------
 drivers/bus/pci/private.h     | 132 ++++++++++++++++++++++++++++++++
 drivers/bus/pci/windows/pci.c |  24 ++++++
 lib/eal/freebsd/eal.c         | 140 ----------------------------------
 lib/eal/windows/eal.c         |  29 -------
 7 files changed, 247 insertions(+), 221 deletions(-)
drivers/bus/pci/bsd/pci.c +24 -0
index c6df31d4869..22655b19f4d 100644
@@ -665,3 +665,27 @@ rte_pci_ioport_unmap(struct rte_pci_ioport *p)
 
 	return ret;
 }
+
+struct rte_bus rte_pci_bus = {
+	.allow_multi_probe = true,
+	.scan = rte_pci_scan,
+	.probe = rte_bus_generic_probe,
+	.free_device = pci_free_device,
+	.cleanup = rte_bus_generic_cleanup,
+	.find_device = rte_bus_generic_find_device,
+	.match = pci_bus_match,
+	.probe_device = pci_probe_device,
+	.unplug_device = pci_unplug_device,
+	.parse = pci_parse,
+	.dev_compare = pci_dev_compare,
+	.devargs_parse = rte_pci_devargs_parse,
+	.dma_map = pci_common_dma_map,
+	.dma_unmap = pci_common_dma_unmap,
+	.get_iommu_class = rte_pci_get_iommu_class,
+	.dev_iterate = rte_pci_dev_iterate,
+	.hot_unplug_handler = pci_hot_unplug_handler,
+	.sigbus_handler = pci_sigbus_handler,
+};
+
+RTE_REGISTER_BUS(pci, rte_pci_bus);
+RTE_LOG_REGISTER_DEFAULT(pci_bus_logtype, NOTICE);
drivers/bus/pci/linux/pci.c +55 -0

70 lines not on this page · raw message

drivers/bus/pci/pci_common.c +12 -52

143 lines not on this page · raw message

drivers/bus/pci/private.h +132 -0

136 lines not on this page · raw message

drivers/bus/pci/windows/pci.c +24 -0
index 7b51301d1e7..236336552cd 100644
@@ -512,3 +512,27 @@ rte_pci_scan(void)
 
 	return ret;
 }
+
+struct rte_bus rte_pci_bus = {
+	.allow_multi_probe = true,
+	.scan = rte_pci_scan,
+	.probe = rte_bus_generic_probe,
+	.free_device = pci_free_device,
+	.cleanup = rte_bus_generic_cleanup,
+	.find_device = rte_bus_generic_find_device,
+	.match = pci_bus_match,
+	.probe_device = pci_probe_device,
+	.unplug_device = pci_unplug_device,
+	.parse = pci_parse,
+	.dev_compare = pci_dev_compare,
+	.devargs_parse = rte_pci_devargs_parse,
+	.dma_map = pci_common_dma_map,
+	.dma_unmap = pci_common_dma_unmap,
+	.get_iommu_class = rte_pci_get_iommu_class,
+	.dev_iterate = rte_pci_dev_iterate,
+	.hot_unplug_handler = pci_hot_unplug_handler,
+	.sigbus_handler = pci_sigbus_handler,
+};
+
+RTE_REGISTER_BUS(pci, rte_pci_bus);
+RTE_LOG_REGISTER_DEFAULT(pci_bus_logtype, NOTICE);
lib/eal/freebsd/eal.c +0 -140

149 lines not on this page · raw message

lib/eal/windows/eal.c +0 -29
index b8771d4d858..cac8faa53db 100644
@@ -24,7 +24,6 @@
 #include <eal_options.h>
 #include <eal_private.h>
 #include <rte_service_component.h>
-#include <rte_vfio.h>
 
 #include "eal_firmware.h"
 #include "eal_hugepages.h"
@@ -152,12 +151,6 @@ rte_eal_cleanup(void)
 	return 0;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_cleanup)
-void
-rte_vfio_cleanup(void)
-{
-}
-
 /* Launch threads, called at application init(). */
 RTE_EXPORT_SYMBOL(rte_eal_init)
 int
@@ -459,28 +452,6 @@ eal_asprintf(char **buffer, const char *format, ...)
 	return ret;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_map)
-int
-rte_vfio_container_dma_map(__rte_unused int container_fd,
-			__rte_unused uint64_t vaddr,
-			__rte_unused uint64_t iova,
-			__rte_unused uint64_t len)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_INTERNAL_SYMBOL(rte_vfio_container_dma_unmap)
-int
-rte_vfio_container_dma_unmap(__rte_unused int container_fd,
-			__rte_unused uint64_t vaddr,
-			__rte_unused uint64_t iova,
-			__rte_unused uint64_t len)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
 RTE_EXPORT_INTERNAL_SYMBOL(rte_firmware_read)
 int
 rte_firmware_read(__rte_unused const char *name,
Signature · 1 line
2.52.0
#309 lore raw

PATCH v18 11/29 vfio: rename API to reflect internal status

In reply to Anatoly Burakov

Currently, even though VFIO API is internal-only, it is still named with an rte_ prefix, which implies public API. To reflect the fact that this API is no longer public, rename all symbols and macros from rte_/RTE_ to dev_/DEV_, and adjust all callers.

---
 doc/guides/rel_notes/release_26_11.rst     |   4 +-
 drivers/bus/cdx/cdx.c                      |   6 +-
 drivers/bus/cdx/cdx_vfio.c                 |  14 +--
 drivers/bus/fslmc/fslmc_bus.c              |   4 +-
 drivers/bus/fslmc/fslmc_vfio.c             |  12 +-
 drivers/bus/pci/linux/pci.c                |   8 +-
 drivers/bus/pci/linux/pci_vfio.c           |  38 +++---
 drivers/bus/platform/platform.c            |  10 +-
 drivers/crypto/bcmfs/bcmfs_vfio.c          |   8 +-
 drivers/net/hinic3/base/hinic3_hwdev.c     |   4 +-
 drivers/net/nbl/nbl_common/nbl_userdev.c   |  16 +--
 drivers/net/ntnic/ntnic_ethdev.c           |   4 +-
 drivers/net/ntnic/ntnic_vfio.c             |  22 ++--
 drivers/vdpa/ifc/ifcvf_vdpa.c              |  24 ++--
 drivers/vdpa/nfp/nfp_vdpa.c                |  24 ++--
 drivers/vdpa/sfc/sfc_vdpa.c                |  16 +--
 drivers/vdpa/sfc/sfc_vdpa_hw.c             |  12 +-
 lib/eal/include/{rte_vfio.h => dev_vfio.h} |  68 +++++------
 lib/eal/include/meson.build                |   2 +-
 lib/eal/linux/eal.c                        |   6 +-
 lib/eal/linux/eal_vfio.c                   | 134 ++++++++++-----------
 lib/eal/linux/eal_vfio_mp_sync.c           |   6 +-
 lib/vhost/socket.c                         |   6 +-
 lib/vhost/vhost_user.c                     |   6 +-
 24 files changed, 227 insertions(+), 227 deletions(-)
 rename lib/eal/include/{rte_vfio.h => dev_vfio.h} (81%)
doc/guides/rel_notes/release_26_11.rst +2 -2
index a308742461e..ebe7da31ceb 100644
@@ -392,8 +392,8 @@ API Changes
   * all remaining ``rte_flow`` item, action and async operation structures
 
 * vfio: The entire VFIO API (``rte_vfio_*``) was made internal.
-  These functions are now available only to EAL and drivers,
-  and are no longer part of the public API.
+  These functions were renamed to ``dev_vfio_*``, are now available
+  only to EAL and drivers, and are no longer part of public API.
 
 
 ABI Changes
drivers/bus/cdx/cdx.c +3 -3
index c0b46a41ade..ee8f24e67ee 100644
@@ -73,7 +73,7 @@
 #include <rte_devargs.h>
 #include <rte_kvargs.h>
 #include <rte_malloc.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include <eal_export.h>
 #include <eal_filesystem.h>
@@ -403,7 +403,7 @@ cdx_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 {
 	RTE_SET_USED(dev);
 
-	return rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD,
+	return dev_vfio_container_dma_map(DEV_VFIO_DEFAULT_CONTAINER_FD,
 					  (uintptr_t)addr, iova, len);
 }
 
@@ -412,7 +412,7 @@ cdx_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 {
 	RTE_SET_USED(dev);
 
-	return rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD,
+	return dev_vfio_container_dma_unmap(DEV_VFIO_DEFAULT_CONTAINER_FD,
 					    (uintptr_t)addr, iova, len);
 }
 
drivers/bus/cdx/cdx_vfio.c +7 -7
index 11fe3265d23..02a34d6f186 100644
@@ -23,7 +23,7 @@
 #include <eal_export.h>
 #include <rte_eal_paging.h>
 #include <rte_malloc.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "bus_cdx_driver.h"
 #include "cdx_logs.h"
@@ -121,7 +121,7 @@ cdx_vfio_unmap_resource_primary(struct rte_cdx_device *dev)
 	if (vfio_dev_fd < 0)
 		return -1;
 
-	ret = rte_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev->device.name,
+	ret = dev_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev->device.name,
 				      vfio_dev_fd);
 	if (ret < 0) {
 		CDX_BUS_ERR("Cannot release VFIO device");
@@ -155,7 +155,7 @@ cdx_vfio_unmap_resource_secondary(struct rte_cdx_device *dev)
 	if (vfio_dev_fd < 0)
 		return -1;
 
-	ret = rte_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev->device.name,
+	ret = dev_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev->device.name,
 				      vfio_dev_fd);
 	if (ret < 0) {
 		CDX_BUS_ERR("Cannot release VFIO device");
@@ -400,7 +400,7 @@ cdx_vfio_map_resource_primary(struct rte_cdx_device *dev)
 	if (rte_intr_fd_set(dev->intr_handle, -1))
 		return -1;
 
-	ret = rte_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
+	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
 				    &vfio_dev_fd, &device_info);
 	if (ret)
 		return ret;
@@ -477,7 +477,7 @@ cdx_vfio_map_resource_primary(struct rte_cdx_device *dev)
 	cdx_vfio_find_and_unmap_resource(vfio_res_list, dev);
 	rte_free(vfio_res);
 err_vfio_dev_fd:
-	rte_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, vfio_dev_fd);
+	dev_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, vfio_dev_fd);
 	return -1;
 }
 
@@ -509,7 +509,7 @@ cdx_vfio_map_resource_secondary(struct rte_cdx_device *dev)
 		return -1;
 	}
 
-	ret = rte_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
+	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
 					&vfio_dev_fd, &device_info);
 	if (ret)
 		return ret;
@@ -535,7 +535,7 @@ cdx_vfio_map_resource_secondary(struct rte_cdx_device *dev)
 
 	return 0;
 err_vfio_dev_fd:
-	rte_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, vfio_dev_fd);
+	dev_vfio_release_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, vfio_dev_fd);
 	return -1;
 }
 
drivers/bus/fslmc/fslmc_bus.c +2 -2
index 3626b123168..d55c414eada 100644
@@ -17,7 +17,7 @@
 #include <rte_memcpy.h>
 #include <ethdev_driver.h>
 #include <rte_mbuf_dyn.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "private.h"
 #include <fslmc_vfio.h>
@@ -500,7 +500,7 @@ rte_dpaa2_get_iommu_class(void)
 		return RTE_IOVA_DC;
 
 	/* check if all devices on the bus support Virtual addressing or not */
-	if (fslmc_all_device_support_iova() != 0 && rte_vfio_noiommu_is_enabled() == 0)
+	if (fslmc_all_device_support_iova() != 0 && dev_vfio_noiommu_is_enabled() == 0)
 		return RTE_IOVA_VA;
 
 	return RTE_IOVA_PA;
drivers/bus/fslmc/fslmc_vfio.c +6 -6
index 8d39895bacf..153e6112dbf 100644
@@ -34,7 +34,7 @@
 #include <rte_kvargs.h>
 #include <dev_driver.h>
 #include <rte_eal_memconfig.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "private.h"
 #include "fslmc_vfio.h"
@@ -204,7 +204,7 @@ fslmc_vfio_add_group(int vfio_group_fd,
 	group->fd = vfio_group_fd;
 	group->groupid = iommu_group_num;
 	rte_strscpy(group->group_name, group_name, sizeof(group->group_name));
-	if (rte_vfio_noiommu_is_enabled() > 0)
+	if (dev_vfio_noiommu_is_enabled() > 0)
 		group->iommu_type = VFIO_NOIOMMU_IOMMU;
 	else
 		group->iommu_type = VFIO_TYPE1_IOMMU;
@@ -374,7 +374,7 @@ fslmc_get_group_id(const char *group_name,
 	int ret;
 
 	/* get group number */
-	ret = rte_vfio_get_group_num(SYSFS_FSL_MC_DEVICES,
+	ret = dev_vfio_get_group_num(SYSFS_FSL_MC_DEVICES,
 			group_name, groupid);
 	if (ret <= 0) {
 		DPAA2_BUS_ERR("Find %s IOMMU group", group_name);
@@ -411,7 +411,7 @@ fslmc_vfio_open_group_fd(const char *group_name)
 	/* if primary, try to open the group */
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
 		/* try regular group format */
-		snprintf(filename, sizeof(filename), RTE_VFIO_GROUP_FMT, iommu_group_num);
+		snprintf(filename, sizeof(filename), DEV_VFIO_GROUP_FMT, iommu_group_num);
 		vfio_group_fd = open(filename, O_RDWR);
 
 		goto add_vfio_group;
@@ -509,10 +509,10 @@ fslmc_vfio_open_container_fd(void)
 
 	/* if we're in a primary process, try to open the container */
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
-		vfio_container_fd = open(RTE_VFIO_CONTAINER_PATH, O_RDWR);
+		vfio_container_fd = open(DEV_VFIO_CONTAINER_PATH, O_RDWR);
 		if (vfio_container_fd < 0) {
 			DPAA2_BUS_ERR("Open VFIO container(%s), err(%d)",
-				RTE_VFIO_CONTAINER_PATH, vfio_container_fd);
+				DEV_VFIO_CONTAINER_PATH, vfio_container_fd);
 			ret = vfio_container_fd;
 			goto err_exit;
 		}
drivers/bus/pci/linux/pci.c +4 -4
index 008e08e71fe..233223fbe5b 100644
@@ -12,7 +12,7 @@
 #include <rte_malloc.h>
 #include <rte_devargs.h>
 #include <rte_memcpy.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include <eal_export.h>
 #include "eal_filesystem.h"
@@ -29,7 +29,7 @@ pci_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 	if (pdrv->dma_map != NULL)
 		return pci_common_dma_map(dev, addr, iova, len);
 	if (pdev->kdrv == RTE_PCI_KDRV_VFIO)
-		return rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD,
+		return dev_vfio_container_dma_map(DEV_VFIO_DEFAULT_CONTAINER_FD,
 				(uintptr_t)addr, iova, len);
 	rte_errno = ENOTSUP;
 	return -1;
@@ -44,7 +44,7 @@ pci_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 	if (pdrv->dma_unmap != NULL)
 		return pci_common_dma_unmap(dev, addr, iova, len);
 	if (pdev->kdrv == RTE_PCI_KDRV_VFIO)
-		return rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD,
+		return dev_vfio_container_dma_unmap(DEV_VFIO_DEFAULT_CONTAINER_FD,
 				(uintptr_t)addr, iova, len);
 	rte_errno = ENOTSUP;
 	return -1;
@@ -627,7 +627,7 @@ pci_device_iova_mode(const struct rte_pci_driver *pdrv,
 		static int is_vfio_noiommu_enabled = -1;
 
 		if (is_vfio_noiommu_enabled == -1) {
-			if (rte_vfio_noiommu_is_enabled() == 1)
+			if (dev_vfio_noiommu_is_enabled() == 1)
 				is_vfio_noiommu_enabled = 1;
 			else
 				is_vfio_noiommu_enabled = 0;
drivers/bus/pci/linux/pci_vfio.c +19 -19
index ed713a005f6..e0e94e6ee2c 100644
@@ -18,7 +18,7 @@
 #include <rte_bus_pci.h>
 #include <rte_eal_paging.h>
 #include <rte_malloc.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_eal.h>
 #include <bus_driver.h>
 #include <rte_spinlock.h>
@@ -29,10 +29,10 @@
 #include "pci_init.h"
 #include "private.h"
 
-static struct rte_tailq_elem rte_vfio_tailq = {
+static struct rte_tailq_elem dev_vfio_tailq = {
 	.name = "VFIO_RESOURCE_LIST",
 };
-EAL_REGISTER_TAILQ(rte_vfio_tailq)
+EAL_REGISTER_TAILQ(dev_vfio_tailq)
 
 static int
 pci_vfio_get_region(const struct rte_pci_device *dev, int index,
@@ -418,7 +418,7 @@ pci_vfio_is_ioport_bar(const struct rte_pci_device *dev, int vfio_dev_fd,
 }
 
 static int
-pci_rte_vfio_setup_device(struct rte_pci_device *dev, int vfio_dev_fd)
+pci_vfio_setup_device(struct rte_pci_device *dev, int vfio_dev_fd)
 {
 	if (pci_vfio_setup_interrupts(dev, vfio_dev_fd) != 0) {
 		PCI_LOG(ERR, "Error setting up interrupts!");
@@ -738,7 +738,7 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 	int i, j, ret;
 	struct mapped_pci_resource *vfio_res = NULL;
 	struct mapped_pci_res_list *vfio_res_list =
-		RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+		RTE_TAILQ_CAST(dev_vfio_tailq.head, mapped_pci_res_list);
 
 	struct pci_map *maps;
 
@@ -752,7 +752,7 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 	snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,
 			loc->domain, loc->bus, loc->devid, loc->function);
 
-	ret = rte_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
+	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
 					&vfio_dev_fd, &device_info);
 	if (ret)
 		return ret;
@@ -897,7 +897,7 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 		free(reg);
 	}
 
-	if (pci_rte_vfio_setup_device(dev, vfio_dev_fd) < 0) {
+	if (pci_vfio_setup_device(dev, vfio_dev_fd) < 0) {
 		PCI_LOG(ERR, "%s setup device failed", pci_addr);
 		goto err_map;
 	}
@@ -920,7 +920,7 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 err_vfio_res:
 	rte_free(vfio_res);
 err_vfio_dev_fd:
-	rte_vfio_release_device(rte_pci_get_sysfs_path(),
+	dev_vfio_release_device(rte_pci_get_sysfs_path(),
 			pci_addr, vfio_dev_fd);
 	return -1;
 }
@@ -935,7 +935,7 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 	int j, ret, i = 0;
 	struct mapped_pci_resource *vfio_res = NULL;
 	struct mapped_pci_res_list *vfio_res_list =
-		RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+		RTE_TAILQ_CAST(dev_vfio_tailq.head, mapped_pci_res_list);
 
 	struct pci_map *maps;
 
@@ -961,7 +961,7 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 		return -1;
 	}
 
-	ret = rte_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
+	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
 					&vfio_dev_fd, &device_info);
 	if (ret)
 		return ret;
@@ -1006,7 +1006,7 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 			pci_unmap_resource(maps[j].addr, maps[j].size);
 	}
 err_vfio_dev:
-	rte_vfio_release_device(rte_pci_get_sysfs_path(),
+	dev_vfio_release_device(rte_pci_get_sysfs_path(),
 			pci_addr, vfio_dev_fd);
 	return -1;
 }
@@ -1101,7 +1101,7 @@ pci_vfio_unmap_resource_primary(struct rte_pci_device *dev)
 		return -1;
 	}
 
-	ret = rte_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
+	ret = dev_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
 				      vfio_dev_fd);
 	if (ret < 0) {
 		PCI_LOG(ERR, "Cannot release VFIO device");
@@ -1109,7 +1109,7 @@ pci_vfio_unmap_resource_primary(struct rte_pci_device *dev)
 	}
 
 	vfio_res_list =
-		RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+		RTE_TAILQ_CAST(dev_vfio_tailq.head, mapped_pci_res_list);
 	vfio_res = find_and_unmap_vfio_resource(vfio_res_list, dev, pci_addr);
 
 	/* if we haven't found our tailq entry, something's wrong */
@@ -1140,7 +1140,7 @@ pci_vfio_unmap_resource_secondary(struct rte_pci_device *dev)
 	if (vfio_dev_fd < 0)
 		return -1;
 
-	ret = rte_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
+	ret = dev_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
 				      vfio_dev_fd);
 	if (ret < 0) {
 		PCI_LOG(ERR, "Cannot release VFIO device");
@@ -1148,7 +1148,7 @@ pci_vfio_unmap_resource_secondary(struct rte_pci_device *dev)
 	}
 
 	vfio_res_list =
-		RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);
+		RTE_TAILQ_CAST(dev_vfio_tailq.head, mapped_pci_res_list);
 	vfio_res = find_and_unmap_vfio_resource(vfio_res_list, dev, pci_addr);
 
 	/* if we haven't found our tailq entry, something's wrong */
@@ -1195,7 +1195,7 @@ pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,
 		if (vfio_dev_fd < 0) {
 			return -1;
 		} else if (vfio_dev_fd == 0) {
-			if (rte_vfio_get_device_info(rte_pci_get_sysfs_path(), pci_addr,
+			if (dev_vfio_get_device_info(rte_pci_get_sysfs_path(), pci_addr,
 				&vfio_dev_fd, &device_info) != 0)
 				return -1;
 			/* save vfio_dev_fd so it can be used during release */
@@ -1302,10 +1302,10 @@ pci_vfio_is_enabled(void)
 {
 	int status;
 
-	if (rte_vfio_enable() < 0)
+	if (dev_vfio_enable() < 0)
 		return 0;
 
-	status = rte_vfio_is_enabled() &&
-		rte_vfio_module_is_loaded(RTE_VFIO_MODULE_VFIO_PCI);
+	status = dev_vfio_is_enabled() &&
+		dev_vfio_module_is_loaded(DEV_VFIO_MODULE_VFIO_PCI);
 	return status;
 }
drivers/bus/platform/platform.c +5 -5
index 90d865a8df9..9d7df9be803 100644
@@ -23,7 +23,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_string_fns.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "private.h"
 
@@ -282,7 +282,7 @@ static void
 device_cleanup(struct rte_platform_device *pdev)
 {
 	device_unmap_resources(pdev);
-	rte_vfio_release_device(PLATFORM_BUS_DEVICES_PATH, pdev->name, pdev->dev_fd);
+	dev_vfio_release_device(PLATFORM_BUS_DEVICES_PATH, pdev->name, pdev->dev_fd);
 }
 
 static int
@@ -292,7 +292,7 @@ device_setup(struct rte_platform_device *pdev)
 	const char *name = pdev->name;
 	int ret;
 
-	ret = rte_vfio_setup_device(PLATFORM_BUS_DEVICES_PATH, name, &pdev->dev_fd, &dev_info);
+	ret = dev_vfio_setup_device(PLATFORM_BUS_DEVICES_PATH, name, &pdev->dev_fd, &dev_info);
 	if (ret) {
 		PLATFORM_LOG_LINE(ERR, "failed to setup %s", name);
 		return -ENODEV;
@@ -458,7 +458,7 @@ platform_bus_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t l
 	if (pdrv->dma_map != NULL)
 		return pdrv->dma_map(pdev, addr, iova, len);
 
-	return rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD, (uint64_t)addr, iova, len);
+	return dev_vfio_container_dma_map(DEV_VFIO_DEFAULT_CONTAINER_FD, (uint64_t)addr, iova, len);
 }
 
 static int
@@ -470,7 +470,7 @@ platform_bus_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t
 	if (pdrv->dma_unmap != NULL)
 		return pdrv->dma_unmap(pdev, addr, iova, len);
 
-	return rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD, (uint64_t)addr, iova,
+	return dev_vfio_container_dma_unmap(DEV_VFIO_DEFAULT_CONTAINER_FD, (uint64_t)addr, iova,
 					    len);
 }
 
drivers/crypto/bcmfs/bcmfs_vfio.c +4 -4
index e7f7ed994c3..053af0d227b 100644
@@ -9,7 +9,7 @@
 #include <sys/mman.h>
 #include <sys/ioctl.h>
 
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "bcmfs_device.h"
 #include "bcmfs_logs.h"
@@ -25,7 +25,7 @@ vfio_map_dev_obj(const char *path, const char *dev_obj,
 	struct vfio_device_info d_info = { .argsz = sizeof(d_info) };
 	struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
 
-	ret = rte_vfio_setup_device(path, dev_obj, dev_fd, &d_info);
+	ret = dev_vfio_setup_device(path, dev_obj, dev_fd, &d_info);
 	if (ret) {
 		BCMFS_LOG(ERR, "VFIO Setting for device failed");
 		return ret;
@@ -51,7 +51,7 @@ vfio_map_dev_obj(const char *path, const char *dev_obj,
 	return 0;
 
 map_failed:
-	rte_vfio_release_device(path, dev_obj, *dev_fd);
+	dev_vfio_release_device(path, dev_obj, *dev_fd);
 
 	return ret;
 }
@@ -87,7 +87,7 @@ bcmfs_release_vfio(struct bcmfs_device *dev)
 	/* unmap the addr */
 	munmap(dev->mmap_addr, dev->mmap_size);
 	/* release the device */
-	ret = rte_vfio_release_device(dev->dirname, dev->name,
+	ret = dev_vfio_release_device(dev->dirname, dev->name,
 				      dev->vfio_dev_fd);
 	if (ret < 0) {
 		BCMFS_LOG(ERR, "cannot release device");
drivers/net/hinic3/base/hinic3_hwdev.c +2 -2
index d09a8f7e7d7..6a6cf447528 100644
@@ -2,7 +2,7 @@
  * Copyright(c) 2025 Huawei Technologies Co., Ltd
  */
 
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "hinic3_compat.h"
 #include "hinic3_cmd.h"
@@ -78,7 +78,7 @@ hinic3_is_vfio_iommu_enable(const struct rte_eth_dev *eth_dev)
 {
 	struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
 
-	return pci_dev->kdrv == RTE_PCI_KDRV_VFIO && rte_vfio_noiommu_is_enabled() != 1;
+	return pci_dev->kdrv == RTE_PCI_KDRV_VFIO && dev_vfio_noiommu_is_enabled() != 1;
 }
 
 int
drivers/net/nbl/nbl_common/nbl_userdev.c +8 -8
index ec6840d60ea..f1522772f5b 100644
@@ -4,7 +4,7 @@
 
 #include "nbl_userdev.h"
 #include <uapi/linux/vfio.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #define NBL_USERDEV_EVENT_CLB_NAME	"nbl_userspace_mem_event_clb"
 #define NBL_USERDEV_BAR0_SIZE		65536
@@ -405,7 +405,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	snprintf(pathname, sizeof(pathname),
 		 "%s/%s/", rte_pci_get_sysfs_path(), dev_name);
 
-	ret = rte_vfio_get_group_num(pathname, dev_name, &common->iommu_group_num);
+	ret = dev_vfio_get_group_num(pathname, dev_name, &common->iommu_group_num);
 	if (ret <= 0) {
 		NBL_LOG(ERR, "nbl vfio group number failed");
 		return -1;
@@ -414,7 +414,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	NBL_LOG(DEBUG, "nbl vfio group number %d", common->iommu_group_num);
 	/* vfio_container */
 	if (nbl_default_container < 0) {
-		container = rte_vfio_container_create();
+		container = dev_vfio_container_create();
 		container_create = 1;
 
 		if (container < 0) {
@@ -424,7 +424,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	}
 
 	NBL_LOG(DEBUG, "nbl vfio container %d", container);
-	vfio_group_fd = rte_vfio_container_group_bind(container, common->iommu_group_num);
+	vfio_group_fd = dev_vfio_container_group_bind(container, common->iommu_group_num);
 	if (vfio_group_fd < 0) {
 		NBL_LOG(ERR, "nbl vfio group bind failed, %d", vfio_group_fd);
 		goto free_container;
@@ -535,10 +535,10 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	}
 free_group:
 	close(vfio_group_fd);
-	rte_vfio_clear_group(vfio_group_fd);
+	dev_vfio_clear_group(vfio_group_fd);
 free_container:
 	if (container_create)
-		rte_vfio_container_destroy(container);
+		dev_vfio_container_destroy(container);
 	return -1;
 }
 
@@ -550,7 +550,7 @@ static int nbl_mdev_unmap_device(struct nbl_adapter *adapter)
 	rte_mcfg_mem_read_lock();
 	TAILQ_REMOVE(&nbl_adapter_list, adapter, next);
 	close(common->devfd);
-	vfio_group_fd = rte_vfio_container_group_bind(nbl_default_container,
+	vfio_group_fd = dev_vfio_container_group_bind(nbl_default_container,
 						      common->iommu_group_num);
 	NBL_LOG(DEBUG, "close vfio_group_fd %d", vfio_group_fd);
 	ret = ioctl(vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, &nbl_default_container);
@@ -558,7 +558,7 @@ static int nbl_mdev_unmap_device(struct nbl_adapter *adapter)
 		NBL_LOG(ERR, "unset container, error %i (%s) %d",
 			errno, strerror(errno), ret);
 	nbl_group_count--;
-	ret = rte_vfio_container_group_unbind(nbl_default_container, common->iommu_group_num);
+	ret = dev_vfio_container_group_unbind(nbl_default_container, common->iommu_group_num);
 	if (ret)
 		NBL_LOG(ERR, "vfio container group unbind failed %d", ret);
 	if (!nbl_group_count) {
drivers/net/ntnic/ntnic_ethdev.c +2 -2
index 7634ce6f4c5..d79c4fc1d54 100644
@@ -7,7 +7,7 @@
 
 #include <rte_eal.h>
 #include <rte_dev.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_ethdev.h>
 #include <rte_bus_pci.h>
 #include <ethdev_pci.h>
@@ -2729,7 +2729,7 @@ nthw_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			(pci_dev->device.devargs->data ? pci_dev->device.devargs->data : "NULL"));
 	}
 
-	const int n_rte_vfio_no_io_mmu_enabled = rte_vfio_noiommu_is_enabled();
+	const int n_rte_vfio_no_io_mmu_enabled = dev_vfio_noiommu_is_enabled();
 	NT_LOG(DBG, NTNIC, "vfio_no_iommu_enabled=%d", n_rte_vfio_no_io_mmu_enabled);
 
 	if (n_rte_vfio_no_io_mmu_enabled) {
drivers/net/ntnic/ntnic_vfio.c +11 -11
index 439468b3a26..8489a59859f 100644
@@ -6,7 +6,7 @@
 
 #include <rte_malloc.h>
 #include <rte_memory.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_dev.h>
 #include <rte_bus_pci.h>
 #include <rte_spinlock.h>
@@ -70,16 +70,16 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 	vfio->iova_addr = START_VF_IOVA;
 
 	rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
-	ret = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), devname, &iommu_group_num);
+	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), devname, &iommu_group_num);
 	if (ret <= 0)
 		return -1;
 
 	if (vf_num == 0) {
 		/* use default container for pf0 */
-		vfio->container_fd = RTE_VFIO_DEFAULT_CONTAINER_FD;
+		vfio->container_fd = DEV_VFIO_DEFAULT_CONTAINER_FD;
 
 	} else {
-		vfio->container_fd = rte_vfio_container_create();
+		vfio->container_fd = dev_vfio_container_create();
 
 		if (vfio->container_fd < 0) {
 			NT_LOG(ERR, NTNIC,
@@ -88,7 +88,7 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 		}
 	}
 
-	vfio->group_fd = rte_vfio_container_group_bind(vfio->container_fd, iommu_group_num);
+	vfio->group_fd = dev_vfio_container_group_bind(vfio->container_fd, iommu_group_num);
 
 	if (vfio->group_fd < 0) {
 		NT_LOG(ERR, NTNIC,
@@ -115,8 +115,8 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 
 err:
 
-	if (vfio->container_fd != RTE_VFIO_DEFAULT_CONTAINER_FD)
-		rte_vfio_container_destroy(vfio->container_fd);
+	if (vfio->container_fd != DEV_VFIO_DEFAULT_CONTAINER_FD)
+		dev_vfio_container_destroy(vfio->container_fd);
 
 	return -1;
 }
@@ -135,7 +135,7 @@ nthw_vfio_remove(int vf_num)
 		return -1;
 	}
 
-	rte_vfio_container_destroy(vfio->container_fd);
+	dev_vfio_container_destroy(vfio->container_fd);
 	return 0;
 }
 
@@ -169,14 +169,14 @@ nthw_vfio_dma_map(int vf_num, void *virt_addr, uint64_t *iova_addr, uint64_t siz
 		vf_num, virt_addr, rte_malloc_virt2iova(virt_addr), gp_virt_base, vfio->iova_addr,
 		size);
 
-	int res = rte_vfio_container_dma_map(vfio->container_fd, gp_virt_base, vfio->iova_addr,
+	int res = dev_vfio_container_dma_map(vfio->container_fd, gp_virt_base, vfio->iova_addr,
 			size);
 
 	NT_LOG(DBG, NTNIC, "VFIO MMAP res %i, container_fd %i, vf_num %i", res,
 		vfio->container_fd, vf_num);
 
 	if (res) {
-		NT_LOG(ERR, NTNIC, "rte_vfio_container_dma_map failed: res %d", res);
+		NT_LOG(ERR, NTNIC, "dev_vfio_container_dma_map failed: res %d", res);
 		return -1;
 	}
 
@@ -210,7 +210,7 @@ nthw_vfio_dma_unmap(int vf_num, void *virt_addr, uint64_t iova_addr, uint64_t si
 		return -1;
 	}
 
-	int res = rte_vfio_container_dma_unmap(vfio->container_fd, gp_virt_base, iova_addr, size);
+	int res = dev_vfio_container_dma_unmap(vfio->container_fd, gp_virt_base, iova_addr, size);
 
 	if (res != 0) {
 		NT_LOG(ERR, NTNIC,
drivers/vdpa/ifc/ifcvf_vdpa.c +12 -12
index f319d455ba6..36d06f1e3fb 100644
@@ -20,7 +20,7 @@
 #include <rte_vhost.h>
 #include <rte_vdpa.h>
 #include <vdpa_driver.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_spinlock.h>
 #include <rte_log.h>
 #include <rte_kvargs.h>
@@ -182,18 +182,18 @@ ifcvf_vfio_setup(struct ifcvf_internal *internal)
 	internal->vfio_container_fd = -1;
 
 	rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
-	ret = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), devname,
+	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), devname,
 			&iommu_group_num);
 	if (ret <= 0) {
 		DRV_LOG(ERR, "%s failed to get IOMMU group", devname);
 		return -1;
 	}
 
-	internal->vfio_container_fd = rte_vfio_container_create();
+	internal->vfio_container_fd = dev_vfio_container_create();
 	if (internal->vfio_container_fd < 0)
 		return -1;
 
-	internal->vfio_group_fd = rte_vfio_container_group_bind(
+	internal->vfio_group_fd = dev_vfio_container_group_bind(
 			internal->vfio_container_fd, iommu_group_num);
 	if (internal->vfio_group_fd < 0)
 		goto err;
@@ -216,7 +216,7 @@ ifcvf_vfio_setup(struct ifcvf_internal *internal)
 	return 0;
 
 err:
-	rte_vfio_container_destroy(internal->vfio_container_fd);
+	dev_vfio_container_destroy(internal->vfio_container_fd);
 	return -1;
 }
 
@@ -246,7 +246,7 @@ ifcvf_dma_map(struct ifcvf_internal *internal, bool do_map)
 			reg->host_user_addr, reg->guest_phys_addr, reg->size);
 
 		if (do_map) {
-			ret = rte_vfio_container_dma_map(vfio_container_fd,
+			ret = dev_vfio_container_dma_map(vfio_container_fd,
 				reg->host_user_addr, reg->guest_phys_addr,
 				reg->size);
 			if (ret < 0) {
@@ -254,7 +254,7 @@ ifcvf_dma_map(struct ifcvf_internal *internal, bool do_map)
 				goto exit;
 			}
 		} else {
-			ret = rte_vfio_container_dma_unmap(vfio_container_fd,
+			ret = dev_vfio_container_dma_unmap(vfio_container_fd,
 				reg->host_user_addr, reg->guest_phys_addr,
 				reg->size);
 			if (ret < 0) {
@@ -388,7 +388,7 @@ vdpa_ifcvf_stop(struct ifcvf_internal *internal)
 	if (RTE_VHOST_NEED_LOG(features)) {
 		ifcvf_disable_logging(hw);
 		rte_vhost_get_log_base(internal->vid, &log_base, &log_size);
-		rte_vfio_container_dma_unmap(internal->vfio_container_fd,
+		dev_vfio_container_dma_unmap(internal->vfio_container_fd,
 				log_base, IFCVF_LOG_BASE, log_size);
 		/*
 		 * IFCVF marks dirty memory pages for only packet buffer,
@@ -791,7 +791,7 @@ m_ifcvf_start(struct ifcvf_internal *internal)
 		vring_init(&internal->m_vring[i], vq.size, vring_buf,
 				rte_mem_page_size());
 
-		ret = rte_vfio_container_dma_map(internal->vfio_container_fd,
+		ret = dev_vfio_container_dma_map(internal->vfio_container_fd,
 			(uint64_t)(uintptr_t)vring_buf, m_vring_iova, size);
 		if (ret < 0) {
 			DRV_LOG(ERR, "mediated vring DMA map failed.");
@@ -900,7 +900,7 @@ m_ifcvf_stop(struct ifcvf_internal *internal)
 
 		size = RTE_ALIGN_CEIL(vring_size(vq.size, rte_mem_page_size()),
 				rte_mem_page_size());
-		rte_vfio_container_dma_unmap(internal->vfio_container_fd,
+		dev_vfio_container_dma_unmap(internal->vfio_container_fd,
 			(uint64_t)(uintptr_t)internal->m_vring[i].desc,
 			m_vring_iova, size);
 
@@ -1205,7 +1205,7 @@ ifcvf_set_features(int vid)
 		ifcvf_sw_fallback_switchover(internal);
 	} else {
 		rte_vhost_get_log_base(vid, &log_base, &log_size);
-		rte_vfio_container_dma_map(internal->vfio_container_fd,
+		dev_vfio_container_dma_map(internal->vfio_container_fd,
 				log_base, IFCVF_LOG_BASE, log_size);
 		ifcvf_enable_logging(&internal->hw, IFCVF_LOG_BASE, log_size);
 	}
@@ -1824,7 +1824,7 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 		DRV_LOG(ERR, "failed to update datapath %s", pci_dev->name);
 
 	rte_pci_unmap_device(internal->pdev);
-	rte_vfio_container_destroy(internal->vfio_container_fd);
+	dev_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
 	pthread_mutex_lock(&internal_list_lock);
drivers/vdpa/nfp/nfp_vdpa.c +12 -12
index 4c0ab3ff30d..94740e768d9 100644
@@ -12,7 +12,7 @@
 
 #include <nfp_common_pci.h>
 #include <nfp_dev.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_eal_paging.h>
 #include <rte_malloc.h>
 #include <vdpa_driver.h>
@@ -120,16 +120,16 @@ nfp_vdpa_vfio_setup(struct nfp_vdpa_dev *device)
 	struct rte_pci_device *pci_dev = device->pci_dev;
 
 	rte_pci_device_name(&pci_dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
-	ret = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
+	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
 			&device->iommu_group);
 	if (ret <= 0)
 		return -1;
 
-	device->vfio_container_fd = rte_vfio_container_create();
+	device->vfio_container_fd = dev_vfio_container_create();
 	if (device->vfio_container_fd < 0)
 		return -1;
 
-	device->vfio_group_fd = rte_vfio_container_group_bind(
+	device->vfio_group_fd = dev_vfio_container_group_bind(
 			device->vfio_container_fd, device->iommu_group);
 	if (device->vfio_group_fd < 0)
 		goto container_destroy;
@@ -146,9 +146,9 @@ nfp_vdpa_vfio_setup(struct nfp_vdpa_dev *device)
 	return 0;
 
 group_unbind:
-	rte_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
+	dev_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
 container_destroy:
-	rte_vfio_container_destroy(device->vfio_container_fd);
+	dev_vfio_container_destroy(device->vfio_container_fd);
 
 	return -1;
 }
@@ -157,8 +157,8 @@ static void
 nfp_vdpa_vfio_teardown(struct nfp_vdpa_dev *device)
 {
 	rte_pci_unmap_device(device->pci_dev);
-	rte_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
-	rte_vfio_container_destroy(device->vfio_container_fd);
+	dev_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
+	dev_vfio_container_destroy(device->vfio_container_fd);
 }
 
 static int
@@ -173,7 +173,7 @@ nfp_vdpa_dma_do_unmap(struct rte_vhost_memory *mem,
 	for (i = 0; i < times; i++) {
 		region = &mem->regions[i];
 
-		ret = rte_vfio_container_dma_unmap(vfio_container_fd,
+		ret = dev_vfio_container_dma_unmap(vfio_container_fd,
 				region->host_user_addr, region->guest_phys_addr,
 				region->size);
 		if (ret < 0) {
@@ -197,7 +197,7 @@ nfp_vdpa_dma_do_map(struct rte_vhost_memory *mem,
 	for (i = 0; i < times; i++) {
 		region = &mem->regions[i];
 
-		ret = rte_vfio_container_dma_map(vfio_container_fd,
+		ret = dev_vfio_container_dma_map(vfio_container_fd,
 				region->host_user_addr, region->guest_phys_addr,
 				region->size);
 		if (ret < 0) {
@@ -282,7 +282,7 @@ nfp_vdpa_relay_vring_free(struct nfp_vdpa_dev *device,
 
 		size = RTE_ALIGN_CEIL(vring_size(vring.size, rte_mem_page_size()),
 				rte_mem_page_size());
-		rte_vfio_container_dma_unmap(device->vfio_container_fd,
+		dev_vfio_container_dma_unmap(device->vfio_container_fd,
 				(uint64_t)(uintptr_t)device->hw.m_vring[i].desc,
 				m_vring_iova, size);
 
@@ -315,7 +315,7 @@ nfp_vdpa_relay_vring_alloc(struct nfp_vdpa_dev *device)
 
 		vring_init(&vdpa_hw->m_vring[i], vring.size, vring_buf, page_size);
 
-		ret = rte_vfio_container_dma_map(device->vfio_container_fd,
+		ret = dev_vfio_container_dma_map(device->vfio_container_fd,
 				(uint64_t)(uintptr_t)vring_buf, m_vring_iova, size);
 		if (ret != 0) {
 			DRV_VDPA_LOG(ERR, "vDPA vring relay dma map failed.");
drivers/vdpa/sfc/sfc_vdpa.c +8 -8
index eda111954fb..c65f716a15e 100644
@@ -12,7 +12,7 @@
 #include <rte_errno.h>
 #include <rte_kvargs.h>
 #include <rte_string_fns.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_vhost.h>
 
 #include "efx.h"
@@ -74,13 +74,13 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 
 	rte_pci_device_name(&dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
 
-	sva->vfio_container_fd = rte_vfio_container_create();
+	sva->vfio_container_fd = dev_vfio_container_create();
 	if (sva->vfio_container_fd < 0)	{
 		sfc_vdpa_err(sva, "failed to create VFIO container");
 		goto fail_container_create;
 	}
 
-	rc = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
+	rc = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
 				    &sva->iommu_group_num);
 	if (rc <= 0) {
 		sfc_vdpa_err(sva, "failed to get IOMMU group for %s : %s",
@@ -89,7 +89,7 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 	}
 
 	sva->vfio_group_fd =
-		rte_vfio_container_group_bind(sva->vfio_container_fd,
+		dev_vfio_container_group_bind(sva->vfio_container_fd,
 					      sva->iommu_group_num);
 	if (sva->vfio_group_fd < 0) {
 		sfc_vdpa_err(sva,
@@ -109,7 +109,7 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 	return 0;
 
 fail_pci_map_device:
-	if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
+	if (dev_vfio_container_group_unbind(sva->vfio_container_fd,
 					sva->iommu_group_num) != 0) {
 		sfc_vdpa_err(sva,
 			     "failed to unbind IOMMU group %d from container %d",
@@ -118,7 +118,7 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 
 fail_group_bind:
 fail_get_group_num:
-	if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
+	if (dev_vfio_container_destroy(sva->vfio_container_fd) != 0) {
 		sfc_vdpa_err(sva, "failed to destroy container %d",
 			     sva->vfio_container_fd);
 	}
@@ -132,14 +132,14 @@ sfc_vdpa_vfio_teardown(struct sfc_vdpa_adapter *sva)
 {
 	rte_pci_unmap_device(sva->pdev);
 
-	if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
+	if (dev_vfio_container_group_unbind(sva->vfio_container_fd,
 					    sva->iommu_group_num) != 0) {
 		sfc_vdpa_err(sva,
 			     "failed to unbind IOMMU group %d from container %d",
 			     sva->iommu_group_num, sva->vfio_container_fd);
 	}
 
-	if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
+	if (dev_vfio_container_destroy(sva->vfio_container_fd) != 0) {
 		sfc_vdpa_err(sva,
 			     "failed to destroy container %d",
 			     sva->vfio_container_fd);
drivers/vdpa/sfc/sfc_vdpa_hw.c +6 -6
index 7e43719f53a..65050b9640e 100644
@@ -6,7 +6,7 @@
 
 #include <rte_common.h>
 #include <rte_errno.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_vhost.h>
 
 #include "efx.h"
@@ -64,7 +64,7 @@ sfc_vdpa_dma_alloc(struct sfc_vdpa_adapter *sva, const char *name,
 	mcdi_iova = SFC_VDPA_DEFAULT_MCDI_IOVA;
 
 	for (;;) {
-		ret = rte_vfio_container_dma_map(sva->vfio_container_fd,
+		ret = dev_vfio_container_dma_map(sva->vfio_container_fd,
 						 (uint64_t)mz->addr, mcdi_iova,
 						 mcdi_buff_size);
 		if (ret == 0)
@@ -98,7 +98,7 @@ sfc_vdpa_dma_free(struct sfc_vdpa_adapter *sva, efsys_mem_t *esmp)
 
 	sfc_vdpa_log_init(sva, "name=%s", esmp->esm_mz->name);
 
-	ret = rte_vfio_container_dma_unmap(sva->vfio_container_fd,
+	ret = dev_vfio_container_dma_unmap(sva->vfio_container_fd,
 					   (uint64_t)esmp->esm_base,
 					   esmp->esm_addr, sva->mcdi_buff_size);
 	if (ret < 0)
@@ -140,7 +140,7 @@ sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *ops_data, bool do_map)
 		mem_reg = &vhost_mem->regions[i];
 
 		if (do_map) {
-			rc = rte_vfio_container_dma_map(vfio_container_fd,
+			rc = dev_vfio_container_dma_map(vfio_container_fd,
 						mem_reg->host_user_addr,
 						mem_reg->guest_phys_addr,
 						mem_reg->size);
@@ -151,7 +151,7 @@ sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *ops_data, bool do_map)
 				goto failed_vfio_dma_map;
 			}
 		} else {
-			rc = rte_vfio_container_dma_unmap(vfio_container_fd,
+			rc = dev_vfio_container_dma_unmap(vfio_container_fd,
 						mem_reg->host_user_addr,
 						mem_reg->guest_phys_addr,
 						mem_reg->size);
@@ -171,7 +171,7 @@ sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *ops_data, bool do_map)
 failed_vfio_dma_map:
 	for (j = 0; j < i; j++) {
 		mem_reg = &vhost_mem->regions[j];
-		rte_vfio_container_dma_unmap(vfio_container_fd,
+		dev_vfio_container_dma_unmap(vfio_container_fd,
 					     mem_reg->host_user_addr,
 					     mem_reg->guest_phys_addr,
 					     mem_reg->size);
lib/eal/include/dev_vfio.h renamed from lib/eal/include/rte_vfio.h +34 -34

220 lines not on this page · raw message

lib/eal/include/meson.build +1 -1
index 92821439182..8d3a6d5e000 100644
@@ -60,7 +60,7 @@ headers += files(
 driver_sdk_headers = files(
         'bus_driver.h',
         'dev_driver.h',
-        'rte_vfio.h',
+        'dev_vfio.h',
 )
 
 # special case install the generic headers, since they go in a subdir
lib/eal/linux/eal.c +3 -3
index 3f92cc32ebd..419cebc236b 100644
@@ -39,7 +39,7 @@
 #include <rte_bus.h>
 #include <rte_version.h>
 #include <malloc_heap.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include <telemetry_internal.h>
 #include <eal_export.h>
@@ -769,7 +769,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (rte_vfio_enable()) {
+	if (dev_vfio_enable()) {
 		rte_eal_init_alert("Cannot init VFIO");
 		rte_errno = EAGAIN;
 		goto err_out;
@@ -983,7 +983,7 @@ rte_eal_cleanup(void)
 
 	rte_service_finalize();
 	eal_bus_cleanup();
-	rte_vfio_cleanup();
+	dev_vfio_cleanup();
 	rte_mp_channel_cleanup();
 	rte_eal_alarm_cleanup();
 	rte_trace_save();
lib/eal/linux/eal_vfio.c +67 -67

426 lines not on this page · raw message

lib/eal/linux/eal_vfio_mp_sync.c +3 -3
index 22136f2e8bc..ae1c8b40b99 100644
@@ -8,7 +8,7 @@
 
 #include <rte_errno.h>
 #include <rte_log.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_eal.h>
 
 #include "eal_private.h"
@@ -34,7 +34,7 @@ vfio_mp_primary(const struct rte_mp_msg *msg, const void *peer)
 	case SOCKET_REQ_GROUP:
 		r->req = SOCKET_REQ_GROUP;
 		r->group_num = m->group_num;
-		fd = rte_vfio_get_group_fd(m->group_num);
+		fd = dev_vfio_get_group_fd(m->group_num);
 		if (fd < 0 && fd != -ENOENT)
 			r->result = SOCKET_ERR;
 		else if (fd == -ENOENT)
@@ -49,7 +49,7 @@ vfio_mp_primary(const struct rte_mp_msg *msg, const void *peer)
 		break;
 	case SOCKET_REQ_CONTAINER:
 		r->req = SOCKET_REQ_CONTAINER;
-		fd = rte_vfio_get_container_fd();
+		fd = dev_vfio_get_container_fd();
 		if (fd < 0)
 			r->result = SOCKET_ERR;
 		else {
lib/vhost/socket.c +3 -3
index 1e38ea76474..9b100f669d3 100644
@@ -17,7 +17,7 @@
 #include <eal_export.h>
 #include <rte_thread.h>
 #include <rte_log.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 
 #include "fd_man.h"
 #include "vduse.h"
@@ -245,8 +245,8 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 
 		if (dev != NULL) {
 			dev->async_copy = 1;
-			dev->dma_map_available = rte_vfio_is_enabled() &&
-					rte_vfio_module_is_loaded(RTE_VFIO_MODULE_VFIO);
+			dev->dma_map_available = dev_vfio_is_enabled() &&
+				dev_vfio_module_is_loaded(DEV_VFIO_MODULE_VFIO);
 		}
 	}
 
lib/vhost/vhost_user.c +3 -3
index 2d91722fcc0..813efbd67f6 100644
@@ -42,7 +42,7 @@
 #include <rte_common.h>
 #include <rte_malloc.h>
 #include <rte_log.h>
-#include <rte_vfio.h>
+#include <dev_vfio.h>
 #include <rte_errno.h>
 
 #include "iotlb.h"
@@ -191,7 +191,7 @@ async_dma_map_region(struct virtio_net *dev, struct rte_vhost_mem_region *reg, b
 			continue;
 
 		if (do_map) {
-			ret = rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD,
+			ret = dev_vfio_container_dma_map(DEV_VFIO_DEFAULT_CONTAINER_FD,
 					page->host_user_addr,
 					page->host_iova,
 					page->size);
@@ -216,7 +216,7 @@ async_dma_map_region(struct virtio_net *dev, struct rte_vhost_mem_region *reg, b
 				return -1;
 			}
 		} else {
-			ret = rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD,
+			ret = dev_vfio_container_dma_unmap(DEV_VFIO_DEFAULT_CONTAINER_FD,
 					page->host_user_addr,
 					page->host_iova,
 					page->size);
Signature · 1 line
2.52.0
#310 lore raw

PATCH v18 12/29 bus/pci: rename mismatching error labels

In reply to Anatoly Burakov

Currently, there are two VFIO map functions - primary and secondary - that use a very similar goto error pattern. However, the label names are confusing.

Specifically, for primary, we have three error labels: vfio_res (release VFIO resource), vfio_dev_fd (close the fd), and map (unmap all the mapped regions). For secondary, there is vfio_dev (close the fd), and vfio_dev_fd (unmap all mapped regions).

For consistency, align secondary process function's error labels to match semantics of how they work in primary process function.

---
 drivers/bus/pci/linux/pci_vfio.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/bus/pci/linux/pci_vfio.c +7 -7
index e0e94e6ee2c..3b967d62c89 100644
@@ -968,7 +968,7 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 
 	ret = pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info);
 	if (ret)
-		goto err_vfio_dev;
+		goto err_vfio_dev_fd;
 
 	/* map BARs */
 	maps = vfio_res->maps;
@@ -979,14 +979,14 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 			if (ret < 0) {
 				PCI_LOG(ERR, "%s sparse mapping BAR%i failed: %s",
 					pci_addr, i, strerror(errno));
-				goto err_vfio_dev_fd;
+				goto err_map;
 			}
 		} else {
 			ret = pci_vfio_mmap_bar(vfio_dev_fd, vfio_res, i, MAP_FIXED);
 			if (ret < 0) {
 				PCI_LOG(ERR, "%s mapping BAR%i failed: %s",
 					pci_addr, i, strerror(errno));
-				goto err_vfio_dev_fd;
+				goto err_map;
 			}
 		}
 
@@ -995,17 +995,17 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 
 	/* we need save vfio_dev_fd, so it can be used during release */
 	if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd))
-		goto err_vfio_dev_fd;
+		goto err_map;
 	if (rte_intr_dev_fd_set(dev->vfio_req_intr_handle, vfio_dev_fd))
-		goto err_vfio_dev_fd;
+		goto err_map;
 
 	return 0;
-err_vfio_dev_fd:
+err_map:
 	for (j = 0; j < i; j++) {
 		if (maps[j].addr)
 			pci_unmap_resource(maps[j].addr, maps[j].size);
 	}
-err_vfio_dev:
+err_vfio_dev_fd:
 	dev_vfio_release_device(rte_pci_get_sysfs_path(),
 			pci_addr, vfio_dev_fd);
 	return -1;
Signature · 1 line
2.52.0
#311 lore raw

PATCH v18 13/29 vfio: split get device info from setup

In reply to Anatoly Burakov

Currently, setup gets device info as part of setup, while the separate get device info API also calls setup if the fd is zero. Untangle these two APIs and make each do one thing, and adjust all existing callers.

---
 drivers/bus/cdx/cdx_vfio.c        | 12 ++++++++--
 drivers/bus/pci/linux/pci_vfio.c  | 18 ++++++++++----
 drivers/bus/platform/platform.c   |  9 ++++++-
 drivers/crypto/bcmfs/bcmfs_vfio.c |  8 ++++++-
 lib/eal/include/dev_vfio.h        | 23 +++++++-----------
 lib/eal/linux/eal_vfio.c          | 40 +++++++++----------------------
 6 files changed, 58 insertions(+), 52 deletions(-)
drivers/bus/cdx/cdx_vfio.c +10 -2
index 02a34d6f186..531e4ccc8d0 100644
@@ -401,10 +401,14 @@ cdx_vfio_map_resource_primary(struct rte_cdx_device *dev)
 		return -1;
 
 	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
-				    &vfio_dev_fd, &device_info);
+				    &vfio_dev_fd);
 	if (ret)
 		return ret;
 
+	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+	if (ret)
+		goto err_vfio_dev_fd;
+
 	/* allocate vfio_res and get region info */
 	vfio_res = rte_zmalloc("VFIO_RES", sizeof(*vfio_res), 0);
 	if (vfio_res == NULL) {
@@ -510,10 +514,14 @@ cdx_vfio_map_resource_secondary(struct rte_cdx_device *dev)
 	}
 
 	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
-					&vfio_dev_fd, &device_info);
+					&vfio_dev_fd);
 	if (ret)
 		return ret;
 
+	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+	if (ret)
+		goto err_vfio_dev_fd;
+
 	/* map MMIO regions */
 	maps = vfio_res->maps;
 
drivers/bus/pci/linux/pci_vfio.c +14 -4
index 3b967d62c89..a4bb288916b 100644
@@ -753,10 +753,14 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 			loc->domain, loc->bus, loc->devid, loc->function);
 
 	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-					&vfio_dev_fd, &device_info);
+					&vfio_dev_fd);
 	if (ret)
 		return ret;
 
+	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+	if (ret)
+		goto err_vfio_dev_fd;
+
 	if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd))
 		goto err_vfio_dev_fd;
 
@@ -962,10 +966,14 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 	}
 
 	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-					&vfio_dev_fd, &device_info);
+					&vfio_dev_fd);
 	if (ret)
 		return ret;
 
+	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
+	if (ret)
+		goto err_vfio_dev_fd;
+
 	ret = pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info);
 	if (ret)
 		goto err_vfio_dev_fd;
@@ -1195,12 +1203,14 @@ pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,
 		if (vfio_dev_fd < 0) {
 			return -1;
 		} else if (vfio_dev_fd == 0) {
-			if (dev_vfio_get_device_info(rte_pci_get_sysfs_path(), pci_addr,
-				&vfio_dev_fd, &device_info) != 0)
+			if (dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
+				&vfio_dev_fd) != 0)
 				return -1;
 			/* save vfio_dev_fd so it can be used during release */
 			if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd) != 0)
 				return -1;
+			if (dev_vfio_get_device_info(vfio_dev_fd, &device_info) != 0)
+				return -1;
 
 			if (pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info) != 0)
 				return -1;
drivers/bus/platform/platform.c +8 -1
index 9d7df9be803..950306e2d90 100644
@@ -292,12 +292,19 @@ device_setup(struct rte_platform_device *pdev)
 	const char *name = pdev->name;
 	int ret;
 
-	ret = dev_vfio_setup_device(PLATFORM_BUS_DEVICES_PATH, name, &pdev->dev_fd, &dev_info);
+	ret = dev_vfio_setup_device(PLATFORM_BUS_DEVICES_PATH, name, &pdev->dev_fd);
 	if (ret) {
 		PLATFORM_LOG_LINE(ERR, "failed to setup %s", name);
 		return -ENODEV;
 	}
 
+	ret = dev_vfio_get_device_info(pdev->dev_fd, &dev_info);
+	if (ret) {
+		PLATFORM_LOG_LINE(ERR, "failed to get device info for %s", name);
+		ret = -ENODEV;
+		goto out;
+	}
+
 	/* This is an extra check to confirm that platform device was initialized
 	 * by a kernel vfio-platform driver. On kernels that predate vfio-platform
 	 * driver this flag obviously does not exist. In such scenarios this
drivers/crypto/bcmfs/bcmfs_vfio.c +7 -1
index 053af0d227b..ad244d97569 100644
@@ -25,12 +25,18 @@ vfio_map_dev_obj(const char *path, const char *dev_obj,
 	struct vfio_device_info d_info = { .argsz = sizeof(d_info) };
 	struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
 
-	ret = dev_vfio_setup_device(path, dev_obj, dev_fd, &d_info);
+	ret = dev_vfio_setup_device(path, dev_obj, dev_fd);
 	if (ret) {
 		BCMFS_LOG(ERR, "VFIO Setting for device failed");
 		return ret;
 	}
 
+	ret = dev_vfio_get_device_info(*dev_fd, &d_info);
+	if (ret) {
+		BCMFS_LOG(ERR, "VFIO Getting device info failed");
+		goto map_failed;
+	}
+
 	/* getting device region info*/
 	ret = ioctl(*dev_fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info);
 	if (ret < 0) {
lib/eal/include/dev_vfio.h +8 -15
index 871bebb43b1..b7f91ca96b8 100644
@@ -66,10 +66,7 @@ enum dev_vfio_module {
  *   device location.
  *
  * @param vfio_dev_fd
- *   VFIO fd.
- *
- * @param device_info
- *   Device information.
+ *   Pointer to VFIO fd, will be set to the opened device fd on success.
  *
  * @return
  *   0 on success.
@@ -78,7 +75,7 @@ enum dev_vfio_module {
  */
 __rte_internal
 int dev_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
-		int *vfio_dev_fd, struct vfio_device_info *device_info);
+		int *vfio_dev_fd);
 
 /**
  * @internal
@@ -217,19 +214,16 @@ dev_vfio_get_group_num(const char *sysfs_base,
  * @internal
  * Get device information.
  *
+ * This function retrieves VFIO device information from an already opened
+ * device. The device must be opened with `dev_vfio_setup_device()` first.
+ *
  * This function is only relevant to Linux and will return an error on BSD.
  *
- * @param sysfs_base
- *   sysfs path prefix.
- *
- * @param dev_addr
- *   device location.
- *
  * @param vfio_dev_fd
- *   VFIO fd.
+ *   VFIO device fd (must be a valid, already opened fd).
  *
  * @param device_info
- *   Device information.
+ *   Pointer to device information structure to be filled.
  *
  * @return
  *   0 on success.
@@ -237,8 +231,7 @@ dev_vfio_get_group_num(const char *sysfs_base,
  */
 __rte_internal
 int
-dev_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
-		int *vfio_dev_fd, struct vfio_device_info *device_info);
+dev_vfio_get_device_info(int vfio_dev_fd, struct vfio_device_info *device_info);
 
 /**
  * @internal
lib/eal/linux/eal_vfio.c +11 -29
index 6ea040dd2e3..0acc423ce28 100644
@@ -816,7 +816,7 @@ dev_vfio_clear_group(int vfio_group_fd)
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_setup_device)
 int
 dev_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
-		int *vfio_dev_fd, struct vfio_device_info *device_info)
+		int *vfio_dev_fd)
 {
 	struct vfio_group_status group_status = {
 			.argsz = sizeof(group_status)
@@ -1038,7 +1038,7 @@ dev_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 		*vfio_dev_fd = ioctl(vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD,
 				     dev);
 		if (*vfio_dev_fd >= 0)
-			goto dev_get_info;
+			goto out;
 	}
 
 	/* get a file descriptor for the device */
@@ -1055,18 +1055,8 @@ dev_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 		return -1;
 	}
 
-	/* test and setup the device */
-dev_get_info:
-	ret = ioctl(*vfio_dev_fd, VFIO_DEVICE_GET_INFO, device_info);
-	if (ret) {
-		EAL_LOG(ERR, "%s cannot get device info, "
-				"error %i (%s)", dev_addr, errno,
-				strerror(errno));
-		close(*vfio_dev_fd);
-		close(vfio_group_fd);
-		dev_vfio_clear_group(vfio_group_fd);
-		return -1;
-	}
+	/* device is now set up */
+out:
 	vfio_group_device_get(vfio_group_fd);
 
 	return 0;
@@ -1297,8 +1287,7 @@ vfio_set_iommu_type(int vfio_container_fd)
 
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_get_device_info)
 int
-dev_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
-		int *vfio_dev_fd, struct vfio_device_info *device_info)
+dev_vfio_get_device_info(int vfio_dev_fd, struct vfio_device_info *device_info)
 {
 	int ret;
 
@@ -1307,21 +1296,14 @@ dev_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
 		return -1;
 	}
 
-	if (device_info == NULL || *vfio_dev_fd < 0)
+	if (device_info == NULL || vfio_dev_fd < 0)
 		return -1;
 
-	if (*vfio_dev_fd == 0) {
-		ret = dev_vfio_setup_device(sysfs_base, dev_addr,
-				vfio_dev_fd, device_info);
-		if (ret)
-			return -1;
-	} else {
-		ret = ioctl(*vfio_dev_fd, VFIO_DEVICE_GET_INFO, device_info);
-		if (ret) {
-			EAL_LOG(ERR, "%s cannot get device info, error %i (%s)",
-					dev_addr, errno, strerror(errno));
-			return -1;
-		}
+	ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_INFO, device_info);
+	if (ret) {
+		EAL_LOG(ERR, "Cannot get device info, error %i (%s)",
+				errno, strerror(errno));
+		return -1;
 	}
 
 	return 0;
Signature · 1 line
2.52.0
#312 lore raw

PATCH v18 14/29 vfio: add container device assignment API

In reply to Anatoly Burakov

Currently, VFIO has explicit group bind API's, but the way they're used is such that no one actually cares about VFIO groups, and the real goal of everyone using VFIO group bind API is to bind devices to particular VFIO container, such that when dev_vfio_setup_device call eventually comes, VFIO will pick up the correct container.

To remove dependency on group API's, add a new "container assign device" API call that will do the same thing, but will not depend on managing VFIO group fd's.

---
 lib/eal/include/dev_vfio.h | 26 ++++++++++++++++++++++++++
 lib/eal/linux/eal_vfio.c   | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)
lib/eal/include/dev_vfio.h +26 -0
index b7f91ca96b8..ba7773959cb 100644
@@ -301,6 +301,32 @@ __rte_internal
 int
 dev_vfio_container_destroy(int container_fd);
 
+/**
+ * @internal
+ *
+ * Assign a device to a VFIO container.
+ *
+ * Doing so will cause `dev_vfio_setup_device()` call to set up the device with
+ * the VFIO container specified in this assign operation.
+ *
+ * This function is only relevant on Linux.
+ *
+ * @param vfio_container_fd
+ *   VFIO container file descriptor.
+ * @param sysfs_base
+ *   Sysfs path prefix.
+ * @param dev_addr
+ *   Device identifier.
+ *
+ * @return
+ *   0 on success.
+ *   <0 on failure.
+ */
+__rte_internal
+int
+dev_vfio_container_assign_device(int vfio_container_fd, const char *sysfs_base,
+		const char *dev_addr);
+
 /**
  * @internal
  * Bind a IOMMU group to a container.
lib/eal/linux/eal_vfio.c +32 -0
index 0acc423ce28..e58f4b8a937 100644
@@ -2207,6 +2207,38 @@ dev_vfio_container_destroy(int container_fd)
 	return 0;
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_assign_device)
+int
+dev_vfio_container_assign_device(int vfio_container_fd, const char *sysfs_base,
+		const char *dev_addr)
+{
+	int iommu_group_num;
+	int ret;
+
+	ret = dev_vfio_get_group_num(sysfs_base, dev_addr, &iommu_group_num);
+	if (ret < 0) {
+		EAL_LOG(ERR, "Cannot get IOMMU group number for device %s",
+			dev_addr);
+		return -1;
+	} else if (ret == 0) {
+		EAL_LOG(ERR,
+			"Device %s is not assigned to any IOMMU group",
+			dev_addr);
+		return -1;
+	}
+
+	ret = dev_vfio_container_group_bind(vfio_container_fd,
+			iommu_group_num);
+	if (ret < 0) {
+		EAL_LOG(ERR,
+			"Cannot bind IOMMU group %d for device %s",
+			iommu_group_num, dev_addr);
+		return -1;
+	}
+
+	return 0;
+}
+
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_group_bind)
 int
 dev_vfio_container_group_bind(int container_fd, int iommu_group_num)
Signature · 1 line
2.52.0
#313 lore raw

PATCH v18 15/29 net/nbl: do not use VFIO group bind API

In reply to Anatoly Burakov

The NBL driver currently uses group bind API, but it is using it only to get group fd and nothing else. In context of NBL driver, this is the only usage of VFIO API's in the driver, and it is not necessary to use it for what NBL driver is trying to accomplish.

Use a direct open() call instead, store the group fd in common structure, and find group fd's opened earlier to prevent us from opening the same group fd twice.

---
 drivers/net/nbl/nbl_common/nbl_userdev.c  | 63 +++++++++++++++++------
 drivers/net/nbl/nbl_common/nbl_userdev.h  |  1 +
 drivers/net/nbl/nbl_include/nbl_include.h |  1 +
 3 files changed, 50 insertions(+), 15 deletions(-)
drivers/net/nbl/nbl_common/nbl_userdev.c +48 -15
index f1522772f5b..66ec8a69afd 100644
@@ -387,6 +387,28 @@ nbl_userdev_mem_event_callback(enum rte_mem_event type, const void *addr, size_t
 	}
 }
 
+static int
+nbl_open_group_fd(int iommu_group_num)
+{
+	char path[PATH_MAX];
+
+	snprintf(path, sizeof(path), DEV_VFIO_GROUP_FMT, iommu_group_num);
+	return open(path, O_RDWR);
+}
+
+static int
+nbl_find_group_fd(int iommu_group_num)
+{
+	struct nbl_adapter *adapter;
+
+	TAILQ_FOREACH(adapter, &nbl_adapter_list, next) {
+		if (adapter->common.iommu_group_num == iommu_group_num)
+			return adapter->common.groupfd;
+	}
+
+	return -1;
+}
+
 static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 {
 	const struct rte_pci_device *pci_dev = adapter->pci_dev;
@@ -400,6 +422,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	u64 dma_limit = NBL_USERDEV_DMA_LIMIT;
 	int ret, container_create = 0, container_set = 0;
 	int vfio_group_fd, container = nbl_default_container;
+	bool new_group = false;
 
 	rte_pci_device_name(&pci_dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
 	snprintf(pathname, sizeof(pathname),
@@ -424,11 +447,18 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 	}
 
 	NBL_LOG(DEBUG, "nbl vfio container %d", container);
-	vfio_group_fd = dev_vfio_container_group_bind(container, common->iommu_group_num);
+	rte_mcfg_mem_read_lock();
+	vfio_group_fd = nbl_find_group_fd(common->iommu_group_num);
+	rte_mcfg_mem_read_unlock();
+	if (vfio_group_fd < 0) {
+		vfio_group_fd = nbl_open_group_fd(common->iommu_group_num);
+		new_group = true;
+	}
 	if (vfio_group_fd < 0) {
 		NBL_LOG(ERR, "nbl vfio group bind failed, %d", vfio_group_fd);
 		goto free_container;
 	}
+	common->groupfd = vfio_group_fd;
 
 	/* check if the group is viable */
 	ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_STATUS, &group_status);
@@ -517,13 +547,13 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 close_fd:
 	close(common->devfd);
 unregister_mem_event:
-	if (nbl_group_count == 1) {
+	if (container_set && nbl_group_count == 1) {
 		rte_mcfg_mem_read_lock();
 		rte_mem_event_callback_unregister(NBL_USERDEV_EVENT_CLB_NAME, NULL);
 		rte_mcfg_mem_read_unlock();
 	}
 free_dma_map:
-	if (nbl_group_count == 1) {
+	if (container_set && nbl_group_count == 1) {
 		rte_mcfg_mem_read_lock();
 		nbl_userdev_dma_free();
 		rte_mcfg_mem_read_unlock();
@@ -534,8 +564,8 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 		nbl_group_count--;
 	}
 free_group:
-	close(vfio_group_fd);
-	dev_vfio_clear_group(vfio_group_fd);
+	if (new_group)
+		close(vfio_group_fd);
 free_container:
 	if (container_create)
 		dev_vfio_container_destroy(container);
@@ -546,21 +576,24 @@ static int nbl_mdev_unmap_device(struct nbl_adapter *adapter)
 {
 	struct nbl_common_info *common = &adapter->common;
 	int vfio_group_fd, ret;
+	bool last_group_user;
 
 	rte_mcfg_mem_read_lock();
 	TAILQ_REMOVE(&nbl_adapter_list, adapter, next);
 	close(common->devfd);
-	vfio_group_fd = dev_vfio_container_group_bind(nbl_default_container,
-						      common->iommu_group_num);
+	common->devfd = -1;
+	vfio_group_fd = common->groupfd;
+	last_group_user = nbl_find_group_fd(common->iommu_group_num) < 0;
 	NBL_LOG(DEBUG, "close vfio_group_fd %d", vfio_group_fd);
-	ret = ioctl(vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, &nbl_default_container);
-	if (ret)
-		NBL_LOG(ERR, "unset container, error %i (%s) %d",
-			errno, strerror(errno), ret);
-	nbl_group_count--;
-	ret = dev_vfio_container_group_unbind(nbl_default_container, common->iommu_group_num);
-	if (ret)
-		NBL_LOG(ERR, "vfio container group unbind failed %d", ret);
+	if (last_group_user) {
+		ret = ioctl(vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, &nbl_default_container);
+		if (ret)
+			NBL_LOG(ERR, "unset container, error %i (%s) %d",
+				errno, strerror(errno), ret);
+		nbl_group_count--;
+		close(vfio_group_fd);
+		common->groupfd = -1;
+	}
 	if (!nbl_group_count) {
 		rte_mem_event_callback_unregister(NBL_USERDEV_EVENT_CLB_NAME, NULL);
 		nbl_userdev_dma_free();
drivers/net/nbl/nbl_common/nbl_userdev.h +1 -0
index 2221e19c67c..1ebc86baf69 100644
@@ -11,6 +11,7 @@
 #define NBL_USERDEV_INIT_COMMON(common) do {		\
 	typeof(common) _comm = (common);		\
 	_comm->devfd = -1;				\
+	_comm->groupfd = -1;				\
 	_comm->eventfd = -1;				\
 	_comm->specific_dma = false;			\
 	_comm->dma_set_msb = false;			\
drivers/net/nbl/nbl_include/nbl_include.h +1 -0
index eeae6a33013..ba99b9f8e7a 100644
@@ -132,6 +132,7 @@ struct nbl_common_info {
 	u16 vsi_id;
 	u16 instance_id;
 	int devfd;
+	int groupfd;
 	int eventfd;
 	int ifindex;
 	int iommu_group_num;
Signature · 1 line
2.52.0
#314 lore raw

PATCH v18 16/29 net/ntnic: use container device assignment API

In reply to Anatoly Burakov

The NTNIC driver uses VFIO group bind/unbind functionality for container device assignment purposes. Use the new container device assignment API instead to provide clearer semantics.

---
 drivers/net/ntnic/ntnic_vfio.c | 30 +++++++++---------------------
 1 file changed, 9 insertions(+), 21 deletions(-)
drivers/net/ntnic/ntnic_vfio.c +9 -21
index 8489a59859f..cacd81643f1 100644
@@ -28,7 +28,6 @@ nt_vfio_vf_num(const struct rte_pci_device *pdev)
 /* Internal API */
 struct vfio_dev {
 	int container_fd;
-	int group_fd;
 	int dev_fd;
 	uint64_t iova_addr;
 };
@@ -50,7 +49,6 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 {
 	int ret;
 	char devname[RTE_DEV_NAME_MAX_LEN] = { 0 };
-	int iommu_group_num;
 	int vf_num;
 	struct vfio_dev *vfio;
 
@@ -66,14 +64,9 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 	}
 
 	vfio->dev_fd = -1;
-	vfio->group_fd = -1;
 	vfio->iova_addr = START_VF_IOVA;
 
 	rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
-	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), devname, &iommu_group_num);
-	if (ret <= 0)
-		return -1;
-
 	if (vf_num == 0) {
 		/* use default container for pf0 */
 		vfio->container_fd = DEV_VFIO_DEFAULT_CONTAINER_FD;
@@ -86,17 +79,14 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 				"VFIO device setup failed. VFIO container creation failed.");
 			return -1;
 		}
-	}
+		ret = dev_vfio_container_assign_device(vfio->container_fd,
+				rte_pci_get_sysfs_path(), devname);
+		if (ret < 0) {
+			NT_LOG(ERR, NTNIC,
+				"VFIO device setup failed. Assign device to container failed.");
+			goto err;
+		}
 
-	vfio->group_fd = dev_vfio_container_group_bind(vfio->container_fd, iommu_group_num);
-
-	if (vfio->group_fd < 0) {
-		NT_LOG(ERR, NTNIC,
-			"VFIO device setup failed. VFIO container group bind failed.");
-		goto err;
-	}
-
-	if (vf_num > 0) {
 		if (rte_pci_map_device(dev)) {
 			NT_LOG(ERR, NTNIC,
 				"Map VFIO device failed. is the vfio-pci driver loaded?");
@@ -106,10 +96,8 @@ nthw_vfio_setup(struct rte_pci_device *dev)
 
 	vfio->dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
 
-	NT_LOG(DBG, NTNIC,
-		"%s: VFIO id=%d, dev_fd=%d, container_fd=%d, group_fd=%d, iommu_group_num=%d",
-		dev->name, vf_num, vfio->dev_fd, vfio->container_fd, vfio->group_fd,
-		iommu_group_num);
+	NT_LOG(DBG, NTNIC, "%s: VFIO id=%d, dev_fd=%d, container_fd=%d",
+		dev->name, vf_num, vfio->dev_fd, vfio->container_fd);
 
 	return vf_num;
 
Signature · 1 line
2.52.0
#315 lore raw

PATCH v18 17/29 vdpa/ifc: use container device assignment API

In reply to Anatoly Burakov

The IFC vDPA driver uses VFIO group bind/unbind functionality for container device assignment purposes. Use the new container device assignment API instead to provide clearer semantics. Since group API is no longer used after these changes, remove its implementation.

---
 drivers/vdpa/ifc/ifcvf_vdpa.c | 34 +++-------------------------------
 1 file changed, 3 insertions(+), 31 deletions(-)
drivers/vdpa/ifc/ifcvf_vdpa.c +3 -31
index 36d06f1e3fb..04ed2052d34 100644
@@ -58,7 +58,6 @@ struct ifcvf_internal {
 	struct ifcvf_hw hw;
 	int configured;
 	int vfio_container_fd;
-	int vfio_group_fd;
 	int vfio_dev_fd;
 	rte_thread_t tid; /* thread for notify relay */
 	rte_thread_t intr_tid; /* thread for config space change interrupt relay */
@@ -174,28 +173,19 @@ ifcvf_vfio_setup(struct ifcvf_internal *internal)
 {
 	struct rte_pci_device *dev = internal->pdev;
 	char devname[RTE_DEV_NAME_MAX_LEN] = {0};
-	int iommu_group_num;
-	int i, ret;
+	int i;
 
 	internal->vfio_dev_fd = -1;
-	internal->vfio_group_fd = -1;
 	internal->vfio_container_fd = -1;
 
 	rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
-	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), devname,
-			&iommu_group_num);
-	if (ret <= 0) {
-		DRV_LOG(ERR, "%s failed to get IOMMU group", devname);
-		return -1;
-	}
 
 	internal->vfio_container_fd = dev_vfio_container_create();
 	if (internal->vfio_container_fd < 0)
 		return -1;
 
-	internal->vfio_group_fd = dev_vfio_container_group_bind(
-			internal->vfio_container_fd, iommu_group_num);
-	if (internal->vfio_group_fd < 0)
+	if (dev_vfio_container_assign_device(internal->vfio_container_fd,
+			rte_pci_get_sysfs_path(), devname) < 0)
 		goto err;
 
 	if (rte_pci_map_device(dev))
@@ -1213,22 +1203,6 @@ ifcvf_set_features(int vid)
 	return 0;
 }
 
-static int
-ifcvf_get_vfio_group_fd(int vid)
-{
-	struct rte_vdpa_device *vdev;
-	struct internal_list *list;
-
-	vdev = rte_vhost_get_vdpa_device(vid);
-	list = find_internal_resource_by_vdev(vdev);
-	if (list == NULL) {
-		DRV_LOG(ERR, "Invalid vDPA device: %p", vdev);
-		return -1;
-	}
-
-	return list->internal->vfio_group_fd;
-}
-
 static int
 ifcvf_get_vfio_device_fd(int vid)
 {
@@ -1474,7 +1448,6 @@ static struct rte_vdpa_dev_ops ifcvf_net_ops = {
 	.set_vring_state = ifcvf_set_vring_state,
 	.set_features = ifcvf_set_features,
 	.migration_done = NULL,
-	.get_vfio_group_fd = ifcvf_get_vfio_group_fd,
 	.get_vfio_device_fd = ifcvf_get_vfio_device_fd,
 	.get_notify_area = ifcvf_get_notify_area,
 	.get_dev_type = ifcvf_get_device_type,
@@ -1605,7 +1578,6 @@ static struct rte_vdpa_dev_ops ifcvf_blk_ops = {
 	.dev_close = ifcvf_dev_close,
 	.set_vring_state = ifcvf_set_vring_state,
 	.migration_done = NULL,
-	.get_vfio_group_fd = ifcvf_get_vfio_group_fd,
 	.get_vfio_device_fd = ifcvf_get_vfio_device_fd,
 	.get_notify_area = ifcvf_get_notify_area,
 	.get_config = ifcvf_blk_get_config,
Signature · 1 line
2.52.0
#316 lore raw

PATCH v18 18/29 vdpa/nfp: use container device assignment API

In reply to Anatoly Burakov

The NFP vDPA driver uses VFIO group bind/unbind functionality for container device assignment purposes. Use the new container device assignment API instead to provide clearer semantics. Since group API is no longer used after these changes, remove its implementation.

---
 drivers/vdpa/nfp/nfp_vdpa.c | 37 +++++--------------------------------
 1 file changed, 5 insertions(+), 32 deletions(-)
drivers/vdpa/nfp/nfp_vdpa.c +5 -32
index 94740e768d9..76d7d616a66 100644
@@ -36,9 +36,7 @@ struct nfp_vdpa_dev {
 	struct nfp_vdpa_hw hw;
 
 	int vfio_container_fd;
-	int vfio_group_fd;
 	int vfio_dev_fd;
-	int iommu_group;
 
 	rte_thread_t tid;    /**< Thread for notify relay */
 	int epoll_fd;
@@ -120,33 +118,26 @@ nfp_vdpa_vfio_setup(struct nfp_vdpa_dev *device)
 	struct rte_pci_device *pci_dev = device->pci_dev;
 
 	rte_pci_device_name(&pci_dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
-	ret = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
-			&device->iommu_group);
-	if (ret <= 0)
-		return -1;
 
 	device->vfio_container_fd = dev_vfio_container_create();
 	if (device->vfio_container_fd < 0)
 		return -1;
 
-	device->vfio_group_fd = dev_vfio_container_group_bind(
-			device->vfio_container_fd, device->iommu_group);
-	if (device->vfio_group_fd < 0)
+	ret = dev_vfio_container_assign_device(device->vfio_container_fd,
+			rte_pci_get_sysfs_path(), dev_name);
+	if (ret < 0)
 		goto container_destroy;
 
-	DRV_VDPA_LOG(DEBUG, "The container_fd=%d, group_fd=%d.",
-			device->vfio_container_fd, device->vfio_group_fd);
+	DRV_VDPA_LOG(DEBUG, "container_fd=%d", device->vfio_container_fd);
 
 	ret = rte_pci_map_device(pci_dev);
 	if (ret != 0)
-		goto group_unbind;
+		goto container_destroy;
 
 	device->vfio_dev_fd = rte_intr_dev_fd_get(pci_dev->intr_handle);
 
 	return 0;
 
-group_unbind:
-	dev_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
 container_destroy:
 	dev_vfio_container_destroy(device->vfio_container_fd);
 
@@ -157,7 +148,6 @@ static void
 nfp_vdpa_vfio_teardown(struct nfp_vdpa_dev *device)
 {
 	rte_pci_unmap_device(device->pci_dev);
-	dev_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
 	dev_vfio_container_destroy(device->vfio_container_fd);
 }
 
@@ -1023,22 +1013,6 @@ nfp_vdpa_dev_close(int vid)
 	return 0;
 }
 
-static int
-nfp_vdpa_get_vfio_group_fd(int vid)
-{
-	struct rte_vdpa_device *vdev;
-	struct nfp_vdpa_dev_node *node;
-
-	vdev = rte_vhost_get_vdpa_device(vid);
-	node = nfp_vdpa_find_node_by_vdev(vdev);
-	if (node == NULL) {
-		DRV_VDPA_LOG(ERR, "Invalid vDPA device: %p.", vdev);
-		return -ENODEV;
-	}
-
-	return node->device->vfio_group_fd;
-}
-
 static int
 nfp_vdpa_get_vfio_device_fd(int vid)
 {
@@ -1190,7 +1164,6 @@ struct rte_vdpa_dev_ops nfp_vdpa_ops = {
 	.dev_close = nfp_vdpa_dev_close,
 	.set_vring_state = nfp_vdpa_set_vring_state,
 	.set_features = nfp_vdpa_set_features,
-	.get_vfio_group_fd = nfp_vdpa_get_vfio_group_fd,
 	.get_vfio_device_fd = nfp_vdpa_get_vfio_device_fd,
 	.get_notify_area = nfp_vdpa_get_notify_area,
 };
Signature · 1 line
2.52.0
#317 lore raw

PATCH v18 19/29 vdpa/sfc: use container device assignment API

In reply to Anatoly Burakov

The SFC vDPA driver uses VFIO group bind/unbind functionality for container device assignment purposes. Use the new container device assignment API instead to provide clearer semantics.

---
 drivers/vdpa/sfc/sfc_vdpa.c | 39 +++++++------------------------------
 drivers/vdpa/sfc/sfc_vdpa.h |  2 --
 2 files changed, 7 insertions(+), 34 deletions(-)
drivers/vdpa/sfc/sfc_vdpa.c +7 -32
index c65f716a15e..bd5420cfa57 100644
@@ -80,22 +80,12 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 		goto fail_container_create;
 	}
 
-	rc = dev_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
-				    &sva->iommu_group_num);
-	if (rc <= 0) {
-		sfc_vdpa_err(sva, "failed to get IOMMU group for %s : %s",
-			     dev_name, rte_strerror(-rc));
-		goto fail_get_group_num;
-	}
-
-	sva->vfio_group_fd =
-		dev_vfio_container_group_bind(sva->vfio_container_fd,
-					      sva->iommu_group_num);
-	if (sva->vfio_group_fd < 0) {
-		sfc_vdpa_err(sva,
-			     "failed to bind IOMMU group %d to container %d",
-			     sva->iommu_group_num, sva->vfio_container_fd);
-		goto fail_group_bind;
+	rc = dev_vfio_container_assign_device(sva->vfio_container_fd,
+			rte_pci_get_sysfs_path(), dev_name);
+	if (rc < 0) {
+		sfc_vdpa_err(sva, "failed to assign device %s to container %d",
+			     dev_name, sva->vfio_container_fd);
+		goto fail_device_assign;
 	}
 
 	if (rte_pci_map_device(dev) != 0) {
@@ -109,15 +99,7 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 	return 0;
 
 fail_pci_map_device:
-	if (dev_vfio_container_group_unbind(sva->vfio_container_fd,
-					sva->iommu_group_num) != 0) {
-		sfc_vdpa_err(sva,
-			     "failed to unbind IOMMU group %d from container %d",
-			     sva->iommu_group_num, sva->vfio_container_fd);
-	}
-
-fail_group_bind:
-fail_get_group_num:
+fail_device_assign:
 	if (dev_vfio_container_destroy(sva->vfio_container_fd) != 0) {
 		sfc_vdpa_err(sva, "failed to destroy container %d",
 			     sva->vfio_container_fd);
@@ -132,13 +114,6 @@ sfc_vdpa_vfio_teardown(struct sfc_vdpa_adapter *sva)
 {
 	rte_pci_unmap_device(sva->pdev);
 
-	if (dev_vfio_container_group_unbind(sva->vfio_container_fd,
-					    sva->iommu_group_num) != 0) {
-		sfc_vdpa_err(sva,
-			     "failed to unbind IOMMU group %d from container %d",
-			     sva->iommu_group_num, sva->vfio_container_fd);
-	}
-
 	if (dev_vfio_container_destroy(sva->vfio_container_fd) != 0) {
 		sfc_vdpa_err(sva,
 			     "failed to destroy container %d",
drivers/vdpa/sfc/sfc_vdpa.h +0 -2
index 2b843e563df..99a81fd1b04 100644
@@ -70,10 +70,8 @@ struct sfc_vdpa_adapter {
 
 	sfc_vdpa_filter_t		filters;
 
-	int				vfio_group_fd;
 	int				vfio_dev_fd;
 	int				vfio_container_fd;
-	int				iommu_group_num;
 	struct sfc_vdpa_ops_data	*ops_data;
 };
 
Signature · 1 line
2.52.0
#318 lore raw

PATCH v18 20/29 vdpa/mlx5: remove group-related API

In reply to Anatoly Burakov

The mlx5 driver does not use the get_group_fd API provided by vDPA. This API is about to be removed, so remove its mention from mlx5.

---
 drivers/vdpa/mlx5/mlx5_vdpa.c | 1 -
 1 file changed, 1 deletion(-)
drivers/vdpa/mlx5/mlx5_vdpa.c +0 -1
index 11708e2005f..1bb5de51b64 100644
@@ -523,7 +523,6 @@ static struct rte_vdpa_dev_ops mlx5_vdpa_ops = {
 	.set_vring_state = mlx5_vdpa_set_vring_state,
 	.set_features = mlx5_vdpa_features_set,
 	.migration_done = NULL,
-	.get_vfio_group_fd = NULL,
 	.get_vfio_device_fd = mlx5_vdpa_get_device_fd,
 	.get_notify_area = mlx5_vdpa_get_notify_area,
 	.get_stats_names = mlx5_vdpa_get_stats_names,
Signature · 1 line
2.52.0
#319 lore raw

PATCH v18 21/29 vhost: remove group-related API from driver

In reply to Anatoly Burakov

The vDPA driver API has "get_vfio_group_fd" in its ops structure, but no driver is using it any more, as better API's were added and implemented. Remove this API from vDPA ops structure.

---
 doc/guides/prog_guide/vhost_lib.rst    | 4 ----
 doc/guides/rel_notes/deprecation.rst   | 4 ----
 doc/guides/rel_notes/release_26_11.rst | 3 +++
 lib/vhost/vdpa_driver.h                | 3 ---
 4 files changed, 3 insertions(+), 11 deletions(-)
doc/guides/prog_guide/vhost_lib.rst +0 -4
index 345a6217161..99355b8afdd 100644
@@ -471,10 +471,6 @@ Finally, a set of device ops is defined for device specific operations:
 
   Called to allow the device to respond to RARP sending.
 
-* ``get_vfio_group_fd``
-
-   Called to get the VFIO group fd of the device.
-
 * ``get_vfio_device_fd``
 
   Called to get the VFIO device fd of the device.
doc/guides/rel_notes/deprecation.rst +0 -4
index f44f01a6e31..ffa363b3479 100644
@@ -29,10 +29,6 @@ Deprecation Notices
   Use the ``-S <service-corelist>`` parameter instead
   to specify the cores to be used for background services in DPDK.
 
-* vdpa: The vDPA driver API will no longer offer ``get_vfio_group_fd``
-  as part of its internal API. All drivers will be adjusted
-  to use the new unified VFIO container device assignment API.
-
 * rte_atomicNN_xxx: These APIs do not take memory order parameter. This does
   not allow for writing optimized code for all the CPU architectures supported
   in DPDK. DPDK has adopted the atomic operations from
doc/guides/rel_notes/release_26_11.rst +3 -0
index ebe7da31ceb..b270f2fa2a3 100644
@@ -415,6 +415,9 @@ ABI Changes
   These functions are now available only to EAL and drivers,
   and are no longer part of the public ABI.
 
+* vdpa: Removed ``get_vfio_group_fd`` from ``struct rte_vdpa_dev_ops``.
+  vDPA drivers should now use the VFIO container device assignment API.
+
 
 Known Issues
 ------------
lib/vhost/vdpa_driver.h +0 -3
index 42392a0d142..c7b9be09fb8 100644
@@ -50,9 +50,6 @@ struct rte_vdpa_dev_ops {
 	/** Destination operations when migration done */
 	int (*migration_done)(int vid);
 
-	/** Get the vfio group fd */
-	int (*get_vfio_group_fd)(int vid);
-
 	/** Get the vfio device fd */
 	int (*get_vfio_device_fd)(int vid);
 
Signature · 1 line
2.52.0
#320 lore raw

PATCH v18 22/29 vfio: remove group-based API

In reply to Anatoly Burakov

All drivers have been adjusted to not use the VFIO group API directly and instead rely on container device assignment model, so the group API is no longer useful and can be removed.

---
 lib/eal/include/dev_vfio.h       | 72 --------------------------------
 lib/eal/linux/eal_vfio.c         | 47 ++++++++++-----------
 lib/eal/linux/eal_vfio.h         |  2 +
 lib/eal/linux/eal_vfio_mp_sync.c |  2 +-
 4 files changed, 26 insertions(+), 97 deletions(-)
lib/eal/include/dev_vfio.h +0 -72
index ba7773959cb..b2347141ef4 100644
@@ -166,24 +166,6 @@ int dev_vfio_is_enabled(void);
 __rte_internal
 int dev_vfio_noiommu_is_enabled(void);
 
-/**
- * @internal
- * Remove group fd from internal VFIO group fd array.
- *
- * This function is only relevant to linux and will return
- * an error on BSD.
- *
- * @param vfio_group_fd
- *   VFIO Group FD.
- *
- * @return
- *   0 on success.
- *   <0 on failure.
- */
-__rte_internal
-int
-dev_vfio_clear_group(int vfio_group_fd);
-
 /**
  * @internal
  * Parse IOMMU group number for a device.
@@ -248,24 +230,6 @@ __rte_internal
 int
 dev_vfio_get_container_fd(void);
 
-/**
- * @internal
- * Open VFIO group fd or get an existing one.
- *
- * This function is only relevant to linux and will return
- * an error on BSD.
- *
- * @param iommu_group_num
- *   iommu group number
- *
- * @return
- *  > 0 group fd
- *  < 0 for errors
- */
-__rte_internal
-int
-dev_vfio_get_group_fd(int iommu_group_num);
-
 /**
  * @internal
  * Create a new container for device binding.
@@ -327,42 +291,6 @@ int
 dev_vfio_container_assign_device(int vfio_container_fd, const char *sysfs_base,
 		const char *dev_addr);
 
-/**
- * @internal
- * Bind a IOMMU group to a container.
- *
- * @param container_fd
- *   the container's fd
- *
- * @param iommu_group_num
- *   the iommu group number to bind to container
- *
- * @return
- *   group fd if successful
- *   <0 if failed
- */
-__rte_internal
-int
-dev_vfio_container_group_bind(int container_fd, int iommu_group_num);
-
-/**
- * @internal
- * Unbind a IOMMU group from a container.
- *
- * @param container_fd
- *   the container fd of container
- *
- * @param iommu_group_num
- *   the iommu group number to delete from container
- *
- * @return
- *    0 if successful
- *   <0 if failed
- */
-__rte_internal
-int
-dev_vfio_container_group_unbind(int container_fd, int iommu_group_num);
-
 /**
  * @internal
  * Perform DMA mapping for devices in a container.
lib/eal/linux/eal_vfio.c +23 -24

151 lines not on this page · raw message

lib/eal/linux/eal_vfio.h +2 -0
index 89c4b5ba450..30389fb2742 100644
@@ -51,6 +51,8 @@ vfio_set_iommu_type(int vfio_container_fd);
 int
 vfio_get_iommu_type(void);
 
+int vfio_get_group_fd_by_num(int iommu_group_num);
+
 /* check if we have any supported extensions */
 int
 vfio_has_supported_extensions(int vfio_container_fd);
lib/eal/linux/eal_vfio_mp_sync.c +1 -1
index ae1c8b40b99..66341a701af 100644
@@ -34,7 +34,7 @@ vfio_mp_primary(const struct rte_mp_msg *msg, const void *peer)
 	case SOCKET_REQ_GROUP:
 		r->req = SOCKET_REQ_GROUP;
 		r->group_num = m->group_num;
-		fd = dev_vfio_get_group_fd(m->group_num);
+		fd = vfio_get_group_fd_by_num(m->group_num);
 		if (fd < 0 && fd != -ENOENT)
 			r->result = SOCKET_ERR;
 		else if (fd == -ENOENT)
Signature · 1 line
2.52.0
#321 lore raw

PATCH v18 23/29 vfio: cleanup and refactor

In reply to Anatoly Burakov

Currently, VFIO code is a bit of an incoherent mess internally, with API's bleeding into each other, inconsistent returns, and a certain amount of spaghetti stemming from organic growth.

Refactor VFIO code to achieve the following goals:

- Make all error handling consistent, and provide/document rte_errno values returned from API's to indicate various conditions.

- Introduce new "VFIO mode" concept. This new API will tell caller which VFIO mode is in use, allowing callers to know when to call group number vs device number API

- Introduce new "IOVA mode" concept. This new API will tell caller if IOMMU is enabled or disabled.

- Decouple dev_vfio_setup_device semantics from PCI bus return convention. Currently, when device is not managed by VFIO, dev_vfio_setup_device will return 1, which is bus speak for "skip this device", however VFIO has nothing to do with PCI bus and should not follow its API conventions.

- Perform device setup in device assign, and make device setup use shared code path with device assign and explicitly assuming default container. This is technically not necessary for group mode as device set up is a two-step process in that mode, but coming cdev mode will have a single-step device setup, and it would be easier if the worked the same way under the hood.

- Add device deduplication based on sysfs path and device address.

- Make VFIO internals more readable. Introduce a lot of infrastructure and more explicit validation, rather than over-reliance on sentinel values and implicit assumptions. This will also make it easier to integrate cdev mode down the line, as it will rely on most of this infrastructure.

- Rename internal structs and macros to use vfio_* namespace

This will change behavior of the following functions:

- dev_vfio_setup_device - when the device is not managed by VFIO, the function will now return -1 with rte_errno set to ENODEV
- dev_vfio_get_group_num - when the device is not managed by VFIO, the function will now return -1 with rte_errno set to ENODEV
- dev_vfio_container_destroy - the function will now release and close all group and device resources associated with the container being destroyed by this call
- dev_vfio_noiommu_is_enabled is now using the new IOMMU mode infrastructure rather than reading a sysfs value

All users of dev_vfio_setup_device and dev_vfio_get_group_num have been adjusted to account for API change.

Because the no-IOMMU check now relies on new mode infrastructure, the VFIO initialization now needs to happen before bus scan, as buses depend on no-IOMMU information.

---
 config/arm/meson.build                   |    1 +
 config/meson.build                       |    1 +
 drivers/bus/cdx/cdx_vfio.c               |   17 +-
 drivers/bus/fslmc/fslmc_vfio.c           |    4 +-
 drivers/bus/pci/linux/pci_vfio.c         |   19 +-
 drivers/crypto/bcmfs/bcmfs_vfio.c        |    6 +-
 drivers/net/nbl/nbl_common/nbl_userdev.c |    2 +-
 lib/eal/include/dev_vfio.h               |  268 ++-
 lib/eal/linux/eal.c                      |   15 +-
 lib/eal/linux/eal_vfio.c                 | 2626 ++++++++--------------
 lib/eal/linux/eal_vfio.h                 |  158 +-
 lib/eal/linux/eal_vfio_group.c           |  951 ++++++++
 lib/eal/linux/eal_vfio_mp_sync.c         |   72 +-
 lib/eal/linux/meson.build                |    1 +
 14 files changed, 2305 insertions(+), 1836 deletions(-)
 create mode 100644 lib/eal/linux/eal_vfio_group.c
config/arm/meson.build +1 -0
index 27b549a0525..2b73cbef7e7 100644
@@ -147,6 +147,7 @@ implementer_cavium = {
     'description': 'Cavium',
     'flags': [
         ['RTE_MAX_VFIO_GROUPS', 128],
+        ['RTE_MAX_VFIO_DEVICES', 256],
         ['RTE_MAX_LCORE', 96],
         ['RTE_MAX_NUMA_NODES', 2]
     ],
config/meson.build +1 -0
index 344f68822be..aa1e83b1e2a 100644
@@ -386,6 +386,7 @@ dpdk_conf.set('RTE_ENABLE_TRACE_FP', get_option('enable_trace_fp'))
 dpdk_conf.set('RTE_PKTMBUF_HEADROOM', get_option('pkt_mbuf_headroom'))
 # values which have defaults which may be overridden
 dpdk_conf.set('RTE_MAX_VFIO_GROUPS', 64)
+dpdk_conf.set('RTE_MAX_VFIO_DEVICES', 256)
 dpdk_conf.set('RTE_DRIVER_MEMPOOL_BUCKET_SIZE_KB', 64)
 dpdk_conf.set('RTE_LIBRTE_DPAA2_USE_PHYS_IOVA', true)
 if get_option('mbuf_refcnt_atomic')
drivers/bus/cdx/cdx_vfio.c +12 -5
index 531e4ccc8d0..7ba09379508 100644
@@ -22,6 +22,7 @@
 
 #include <eal_export.h>
 #include <rte_eal_paging.h>
+#include <rte_errno.h>
 #include <rte_malloc.h>
 #include <dev_vfio.h>
 
@@ -402,8 +403,12 @@ cdx_vfio_map_resource_primary(struct rte_cdx_device *dev)
 
 	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
 				    &vfio_dev_fd);
-	if (ret)
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		return ret;
+	}
 
 	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
 	if (ret)
@@ -513,11 +518,13 @@ cdx_vfio_map_resource_secondary(struct rte_cdx_device *dev)
 		return -1;
 	}
 
-	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name,
-					&vfio_dev_fd);
-	if (ret)
+	ret = dev_vfio_setup_device(RTE_CDX_BUS_DEVICES_PATH, dev_name, &vfio_dev_fd);
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		return ret;
-
+	}
 	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
 	if (ret)
 		goto err_vfio_dev_fd;
drivers/bus/fslmc/fslmc_vfio.c +2 -2
index 153e6112dbf..c2b6ac1f3f7 100644
@@ -376,9 +376,9 @@ fslmc_get_group_id(const char *group_name,
 	/* get group number */
 	ret = dev_vfio_get_group_num(SYSFS_FSL_MC_DEVICES,
 			group_name, groupid);
-	if (ret <= 0) {
+	if (ret < 0) {
 		DPAA2_BUS_ERR("Find %s IOMMU group", group_name);
-		if (ret < 0)
+		if (rte_errno != ENODEV)
 			return ret;
 
 		return -EIO;
drivers/bus/pci/linux/pci_vfio.c +13 -6
index a4bb288916b..fae87a0dcdd 100644
@@ -20,6 +20,7 @@
 #include <rte_malloc.h>
 #include <dev_vfio.h>
 #include <rte_eal.h>
+#include <rte_errno.h>
 #include <bus_driver.h>
 #include <rte_spinlock.h>
 #include <rte_tailq.h>
@@ -752,10 +753,13 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 	snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,
 			loc->domain, loc->bus, loc->devid, loc->function);
 
-	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-					&vfio_dev_fd);
-	if (ret)
+	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr, &vfio_dev_fd);
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		return ret;
+	}
 
 	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
 	if (ret)
@@ -965,10 +969,13 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 		return -1;
 	}
 
-	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
-					&vfio_dev_fd);
-	if (ret)
+	ret = dev_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr, &vfio_dev_fd);
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		return ret;
+	}
 
 	ret = dev_vfio_get_device_info(vfio_dev_fd, &device_info);
 	if (ret)
drivers/crypto/bcmfs/bcmfs_vfio.c +5 -1
index ad244d97569..0e16af03655 100644
@@ -9,6 +9,7 @@
 #include <sys/mman.h>
 #include <sys/ioctl.h>
 
+#include <rte_errno.h>
 #include <dev_vfio.h>
 
 #include "bcmfs_device.h"
@@ -26,7 +27,10 @@ vfio_map_dev_obj(const char *path, const char *dev_obj,
 	struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
 
 	ret = dev_vfio_setup_device(path, dev_obj, dev_fd);
-	if (ret) {
+	if (ret < 0) {
+		/* Device not managed by VFIO - skip */
+		if (rte_errno == ENODEV)
+			ret = 1;
 		BCMFS_LOG(ERR, "VFIO Setting for device failed");
 		return ret;
 	}
drivers/net/nbl/nbl_common/nbl_userdev.c +1 -1
index 66ec8a69afd..9676ef18ae7 100644
@@ -429,7 +429,7 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
 		 "%s/%s/", rte_pci_get_sysfs_path(), dev_name);
 
 	ret = dev_vfio_get_group_num(pathname, dev_name, &common->iommu_group_num);
-	if (ret <= 0) {
+	if (ret < 0) {
 		NBL_LOG(ERR, "nbl vfio group number failed");
 		return -1;
 	}
lib/eal/include/dev_vfio.h +193 -75

425 lines not on this page · raw message

lib/eal/linux/eal.c +10 -5
index 419cebc236b..a6003559da7 100644
@@ -674,6 +674,16 @@ rte_eal_init(int argc, char **argv)
 		}
 	}
 
+	/*
+	 * VFIO must be initialized before bus scan because buses need to know
+	 * about no-IOMMU mode status.
+	 */
+	if (dev_vfio_enable()) {
+		rte_eal_init_alert("Cannot init VFIO");
+		rte_errno = EAGAIN;
+		goto err_out;
+	}
+
 	if (rte_bus_scan()) {
 		rte_eal_init_alert("Cannot scan the buses for devices");
 		rte_errno = ENODEV;
@@ -769,11 +779,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (dev_vfio_enable()) {
-		rte_eal_init_alert("Cannot init VFIO");
-		rte_errno = EAGAIN;
-		goto err_out;
-	}
 	/* in secondary processes, memory init may allocate additional fbarrays
 	 * not present in primary processes, so to avoid any potential issues,
 	 * initialize memzones first.
lib/eal/linux/eal_vfio.c +929 -1697

2,421 lines not on this page · raw message

lib/eal/linux/eal_vfio.h +134 -24

158 lines not on this page · raw message

lib/eal/linux/eal_vfio_group.c new file +951 -0

951 lines not on this page · raw message

lib/eal/linux/eal_vfio_mp_sync.c +52 -20

72 lines not on this page · raw message

lib/eal/linux/meson.build +1 -0
index 29ba3132187..5ec8eddaa27 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.52.0

Part of the diff is not shown here. View the raw message.

#322 lore raw

PATCH v18 24/29 bus/pci: use the new VFIO IOVA mode API

In reply to Anatoly Burakov

Use the new VFIO IOVA mode API to query no-IOMMU status.

---
 drivers/bus/pci/linux/pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/bus/pci/linux/pci.c +1 -1
index 233223fbe5b..cc952ca63b1 100644
@@ -627,7 +627,7 @@ pci_device_iova_mode(const struct rte_pci_driver *pdrv,
 		static int is_vfio_noiommu_enabled = -1;
 
 		if (is_vfio_noiommu_enabled == -1) {
-			if (dev_vfio_noiommu_is_enabled() == 1)
+			if (dev_vfio_get_iova_mode() == DEV_VFIO_IOVA_MODE_PA)
 				is_vfio_noiommu_enabled = 1;
 			else
 				is_vfio_noiommu_enabled = 0;
Signature · 1 line
2.52.0
#323 lore raw

PATCH v18 25/29 bus/fslmc: use the new VFIO IOVA mode API

In reply to Anatoly Burakov

FSLMC bus only supports operating in group mode, and relies on no-IOMMU mode checks. Use the new VFIO API's to query no-IOMMU status as well as to protect the bus from initializing in non-group mode.

---
 drivers/bus/fslmc/fslmc_bus.c  | 10 +++++++++-
 drivers/bus/fslmc/fslmc_vfio.c |  2 +-
 2 files changed, 10 insertions(+), 2 deletions(-)
drivers/bus/fslmc/fslmc_bus.c +9 -1
index d55c414eada..afb45e15db2 100644
@@ -332,6 +332,13 @@ rte_fslmc_scan(void)
 		goto scan_fail;
 	}
 
+	/* for container groups to work, VFIO must be in group mode */
+	if (dev_vfio_get_mode() != DEV_VFIO_MODE_GROUP) {
+		DPAA2_BUS_DEBUG("DPAA2: VFIO not in group mode");
+		ret = -EINVAL;
+		goto scan_fail;
+	}
+
 	ret = fslmc_get_container_group(group_name, &groupid);
 	if (ret != 0)
 		goto scan_fail;
@@ -500,7 +507,8 @@ rte_dpaa2_get_iommu_class(void)
 		return RTE_IOVA_DC;
 
 	/* check if all devices on the bus support Virtual addressing or not */
-	if (fslmc_all_device_support_iova() != 0 && dev_vfio_noiommu_is_enabled() == 0)
+	if (fslmc_all_device_support_iova() != 0 &&
+			dev_vfio_get_iova_mode() == DEV_VFIO_IOVA_MODE_VA)
 		return RTE_IOVA_VA;
 
 	return RTE_IOVA_PA;
drivers/bus/fslmc/fslmc_vfio.c +1 -1
index c2b6ac1f3f7..8e80336d517 100644
@@ -204,7 +204,7 @@ fslmc_vfio_add_group(int vfio_group_fd,
 	group->fd = vfio_group_fd;
 	group->groupid = iommu_group_num;
 	rte_strscpy(group->group_name, group_name, sizeof(group->group_name));
-	if (dev_vfio_noiommu_is_enabled() > 0)
+	if (dev_vfio_get_iova_mode() == DEV_VFIO_IOVA_MODE_PA)
 		group->iommu_type = VFIO_NOIOMMU_IOMMU;
 	else
 		group->iommu_type = VFIO_TYPE1_IOMMU;
Signature · 1 line
2.52.0
#324 lore raw

PATCH v18 26/29 net/hinic3: use the new VFIO IOVA mode API

In reply to Anatoly Burakov

Use new VFIO IOVA mode API to query no-IOMMU status.

---
 drivers/net/hinic3/base/hinic3_hwdev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/hinic3/base/hinic3_hwdev.c +2 -1
index 6a6cf447528..9406b6cff27 100644
@@ -78,7 +78,8 @@ hinic3_is_vfio_iommu_enable(const struct rte_eth_dev *eth_dev)
 {
 	struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
 
-	return pci_dev->kdrv == RTE_PCI_KDRV_VFIO && dev_vfio_noiommu_is_enabled() != 1;
+	return pci_dev->kdrv == RTE_PCI_KDRV_VFIO &&
+			dev_vfio_get_iova_mode() == DEV_VFIO_IOVA_MODE_VA;
 }
 
 int
Signature · 1 line
2.52.0
#325 lore raw

PATCH v18 27/29 net/ntnic: use the new VFIO IOVA mode API

In reply to Anatoly Burakov

Use new VFIO IOVA mode API to query no-IOMMU status.

---
 drivers/net/ntnic/ntnic_ethdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ntnic/ntnic_ethdev.c +1 -1
index d79c4fc1d54..e0d84705f53 100644
@@ -2729,7 +2729,7 @@ nthw_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			(pci_dev->device.devargs->data ? pci_dev->device.devargs->data : "NULL"));
 	}
 
-	const int n_rte_vfio_no_io_mmu_enabled = dev_vfio_noiommu_is_enabled();
+	const int n_rte_vfio_no_io_mmu_enabled = dev_vfio_get_iova_mode() == DEV_VFIO_IOVA_MODE_PA;
 	NT_LOG(DBG, NTNIC, "vfio_no_iommu_enabled=%d", n_rte_vfio_no_io_mmu_enabled);
 
 	if (n_rte_vfio_no_io_mmu_enabled) {
Signature · 1 line
2.52.0
#326 lore raw

PATCH v18 28/29 vfio: remove no-IOMMU check API

In reply to Anatoly Burakov

The dev_vfio_noiommu_is_enabled() check has now been replaced by the new IOVA mode API, so remove it.

---
 lib/eal/include/dev_vfio.h | 14 --------------
 lib/eal/linux/eal_vfio.c   |  7 -------
 2 files changed, 21 deletions(-)
lib/eal/include/dev_vfio.h +0 -14
index bca5bb36a6b..2f693ff761d 100644
@@ -227,20 +227,6 @@ __rte_internal
 enum dev_vfio_iova_mode
 dev_vfio_get_iova_mode(void);
 
-/**
- * @internal
- * Check if VFIO NOIOMMU mode is enabled.
- *
- * This function is only relevant on Linux.
- *
- * @return
- *   1 if enabled.
- *   0 if not enabled or not supported.
- */
-__rte_internal
-int
-dev_vfio_noiommu_is_enabled(void);
-
 /**
  * @internal
  * Parse IOMMU group number for a device.
lib/eal/linux/eal_vfio.c +0 -7
index e0cf806bbf8..57981270841 100644
@@ -1452,13 +1452,6 @@ container_dma_unmap(struct vfio_container *cfg, uint64_t vaddr, uint64_t iova,
 	return ret;
 }
 
-RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_noiommu_is_enabled)
-int
-dev_vfio_noiommu_is_enabled(void)
-{
-	return vfio_global_cfg.iova_mode == DEV_VFIO_IOVA_MODE_PA;
-}
-
 RTE_EXPORT_INTERNAL_SYMBOL(dev_vfio_container_create)
 int
 dev_vfio_container_create(void)
Signature · 1 line
2.52.0
#327 lore raw

PATCH v18 29/29 vfio: introduce cdev mode

In reply to Anatoly Burakov

Add support for VFIO cdev (also known as IOMMUFD) API. The group API is now considered legacy in the kernel, and all further development is expected to happen in IOMMUFD infrastructure.

The implementation largely follows the kernel reference code, with most differences from group mode concentrated in how the container and the devices are set up. The VFIO container allocates an "IOAS" (IO address space), maps the memory into that space, and attaches devices to IOAS - there is no IOMMU type discovery at device attach time.

Unlike group mode, the cdev mode is device-centric, and all DMA mappings are made for an IOAS and not into VFIO container itself. As a result, while group mode only maps memory during first device attach, cdev mode can map memory without having any devices attached. However, current VFIO init has moved to before bus scan, because we need VFIO mode information for buses to decide on IOVA mode. DMA memory mapping, however, must be performed after the DPDK memory was already initialized, so we add another internal API to trigger VFIO DMA maps for cdev mode right after memory init.

To assist any future use of VFIO cdev mode for custom behavior, also introduce "get device number" API, which is kind-of-but-not-really similar to the concept of IOMMU group.

---
 doc/guides/linux_gsg/linux_drivers.rst |  30 ++
 doc/guides/rel_notes/release_26_11.rst |   5 +
 lib/eal/include/dev_vfio.h             |  46 +++
 lib/eal/linux/eal.c                    |   7 +
 lib/eal/linux/eal_vfio.c               | 287 ++++++++++++++++-
 lib/eal/linux/eal_vfio.h               |  38 ++-
 lib/eal/linux/eal_vfio_cdev.c          | 420 +++++++++++++++++++++++++
 lib/eal/linux/eal_vfio_mp_sync.c       |  42 +++
 lib/eal/linux/meson.build              |   1 +
 9 files changed, 862 insertions(+), 14 deletions(-)
 create mode 100644 lib/eal/linux/eal_vfio_cdev.c
doc/guides/linux_gsg/linux_drivers.rst +30 -0
index 12e9faf4a2f..7dd38a69f81 100644
@@ -133,6 +133,31 @@ For proper operation of VFIO when running DPDK applications as a non-privileged
 For more information, please refer to :ref:`linux_gsg_running_without_root_privileges`.
 
 
+.. _linux_gsg_vfio_modes:
+
+VFIO group and cdev modes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Linux kernel provides two different interfaces for VFIO:
+
+group mode
+   The original interface, based on IOMMU groups.
+   It is accessed through the container device ``/dev/vfio/vfio`` and the per-group devices under ``/dev/vfio/``.
+
+cdev mode
+   The newer interface, based on iommufd.
+   It is accessed through ``/dev/iommu`` and the per-device character devices under ``/dev/vfio/devices/``.
+
+DPDK selects the mode automatically; there is no EAL option to force a particular mode.
+Currently, group mode is preferred and is used whenever the container device ``/dev/vfio/vfio`` is usable.
+Using cdev mode requires ``/dev/iommu`` to be present and accessible.
+
+.. note::
+
+   Using VF tokens in cdev mode requires Linux kernel version 6.17 or later.
+   On older kernels the device is bound without the token, so the kernel should be configured to use group mode if VF token support is required.
+
+
 .. _linux_gsg_vfio_noiommu:
 
 VFIO no-IOMMU mode
@@ -265,6 +290,11 @@ The token will be used for all PF and VF ports within the application.
    Linux versions earlier than version 5.7 do not support the creation of
    virtual functions within the VFIO framework.
 
+.. note::
+
+   When VFIO uses cdev mode, VF tokens require a newer kernel.
+   See :ref:`linux_gsg_vfio_modes` for details.
+
 Troubleshooting VFIO
 ~~~~~~~~~~~~~~~~~~~~
 
doc/guides/rel_notes/release_26_11.rst +5 -0
index b270f2fa2a3..95646a0386d 100644
@@ -135,6 +135,11 @@ New Features
   * Optimized the packed-ring Tx xmit path with per-descriptor mbuf
     free (``rte_pktmbuf_free_seg``) and prefetch hints.
 
+* **Added VFIO cdev (IOMMUFD) mode.**
+
+  Added support for the VFIO character device (cdev) API, also known as IOMMUFD.
+  DPDK now supports both the group mode and the new cdev mode.
+
 
 Removed Items
 -------------
lib/eal/include/dev_vfio.h +46 -0

76 lines not on this page · raw message

lib/eal/linux/eal.c +7 -0
index a6003559da7..278504237d5 100644
@@ -816,6 +816,13 @@ rte_eal_init(int argc, char **argv)
 		goto err_out;
 	}
 
+	/* VFIO memory setup that requires DPDK memory to be available. */
+	if (dev_vfio_init_mem() < 0) {
+		rte_eal_init_alert("Cannot init VFIO memory");
+		rte_errno = EAGAIN;
+		goto err_out;
+	}
+
 	/* register multi-process action callbacks for hotplug after memory init */
 	if (eal_mp_dev_hotplug_init() < 0) {
 		rte_eal_init_alert("failed to register mp callback for hotplug");
lib/eal/linux/eal_vfio.c +277 -10

381 lines not on this page · raw message

lib/eal/linux/eal_vfio.h +34 -4
index 2a391808328..1e3ccd1ebd3 100644
@@ -50,9 +50,16 @@ struct vfio_device {
 	bool active;
 	enum dev_vfio_mode mode;
 	int fd;
-	int group; /**< back-reference to group list */
-	char *sysfs_base; /**< sysfs path prefix */
-	char *dev_addr;   /**< device address */
+	union {
+		struct {
+			int dev_num;   /**< device number, e.g., X in /dev/vfio/devices/vfioX */
+		};
+		struct {
+			int group; /**< back-reference to group list */
+			char *sysfs_base; /**< sysfs path prefix */
+			char *dev_addr;   /**< device address */
+		};
+	};
 };
 
 /* group mode specific configuration */
@@ -63,13 +70,21 @@ struct vfio_group_config {
 	struct vfio_group groups[RTE_MAX_VFIO_GROUPS];
 };
 
+/* cdev mode specific configuration */
+struct vfio_cdev_config {
+	uint32_t ioas_id;
+};
+
 /* per-container configuration */
 struct vfio_container {
 	bool active;
 	bool dma_setup_done;
 	int container_fd;
 	struct vfio_user_mem_maps mem_maps;
-	struct vfio_group_config group_cfg;
+	union {
+		struct vfio_group_config group_cfg;
+		struct vfio_cdev_config cdev_cfg;
+	};
 	int n_devices;
 	struct vfio_device devices[RTE_MAX_VFIO_DEVICES];
 };
@@ -164,6 +179,17 @@ int vfio_group_setup_iommu(struct vfio_container *cfg);
 int vfio_group_setup_device_fd(const char *dev_addr,
 		struct vfio_group *grp, struct vfio_device *dev);
 
+/* cdev mode functions */
+int vfio_cdev_enable(struct vfio_container *cfg);
+void vfio_cdev_setup_ops(void);
+int vfio_cdev_setup_ioas(struct vfio_container *cfg);
+int vfio_cdev_sync_ioas(struct vfio_container *cfg);
+int vfio_cdev_get_iommufd(void);
+int vfio_cdev_get_device_num(const char *sysfs_base, const char *dev_addr,
+		int *cdev_dev_num);
+struct vfio_device *vfio_cdev_get_dev_by_num(struct vfio_container *cfg, int cdev_dev_num);
+int vfio_cdev_setup_device(struct vfio_container *cfg, struct vfio_device *dev);
+
 #define VFIO_NOIOMMU_MODE_PATH "/sys/module/vfio/parameters/enable_unsafe_noiommu_mode"
 #define VFIO_MEM_EVENT_CLB_NAME "vfio_mem_event_clb"
 #define VFIO_MODNAME "vfio"
@@ -173,6 +199,8 @@ int vfio_group_setup_device_fd(const char *dev_addr,
 #define VFIO_SOCKET_REQ_GROUP 0x200
 #define VFIO_SOCKET_REQ_IOMMU_TYPE 0x400
 #define VFIO_SOCKET_REQ_IOVA_MODE 0x800
+#define VFIO_SOCKET_REQ_CDEV 0x1000
+#define VFIO_SOCKET_REQ_IOAS_ID 0x2000
 #define VFIO_SOCKET_OK 0x0
 #define VFIO_SOCKET_NO_FD 0x1
 #define VFIO_SOCKET_ERR 0xFF
@@ -183,6 +211,8 @@ struct vfio_mp_param {
 	union {
 		int group_num;
 		int iommu_type_id;
+		int cdev_dev_num;
+		int ioas_id;
 		enum dev_vfio_mode mode;
 		enum dev_vfio_iova_mode iova_mode;
 	};
lib/eal/linux/eal_vfio_cdev.c new file +420 -0

420 lines not on this page · raw message

lib/eal/linux/eal_vfio_mp_sync.c +42 -0

48 lines not on this page · raw message

lib/eal/linux/meson.build +1 -0
index 5ec8eddaa27..c164a30b496 100644
@@ -16,6 +16,7 @@ sources += files(
         'eal_thread.c',
         'eal_timer.c',
         'eal_vfio.c',
+        'eal_vfio_cdev.c',
         'eal_vfio_group.c',
         'eal_vfio_mp_sync.c',
 )
Signature · 1 line
2.52.0
#328 lore raw

v19 cover Support VFIO cdev API in DPDK

In reply to a message not in the archive

This patchset introduces a major refactor of the VFIO subsystem in DPDK to support character device (cdev) interface introduced in Linux kernel, as well as make the API more streamlined and useful. The goal is to simplify device management, improve compatibility, make the code readable, and clarify API.

The following sections outline the key issues addressed by this patchset and the corresponding changes introduced.

1. Only group mode is supported
===============================

Since kernel version 4.14.327 (LTS), VFIO supports the new character device (cdev)-based way of working with VFIO devices (otherwise known as IOMMUFD). This is a device-centric mode and does away with all the complexity regarding groups and IOMMU types, delegating it all to the kernel, and exposes a much simpler interface to userspace. The old group-based implementation will still be around, and will need to be kept in DPDK for compatibility reasons.

To enable this, VFIO is heavily refactored, so that the code can support both modes while relying on (mostly) common infrastructure.

Additionally, new vfio_get_mode API is added for those cases that need some introspection into VFIO's internals, with two modes: group (old-style), and cdev (the new mode).

Historically, no-IOMMU mode was technically a variant of group mode, the distinction is largely irrelevant to the user, as all usages of noiommu checks in our codebase are for deciding whether to use IOVA or PA, not anything to do with managing groups. However, now that upcoming kernel versions will support no-IOMMU for both group, cdev compatibility, and full cdev paths, a new vfio_get_iommu_mode is also added, with two modes: safe (full IOMMU backing), and unsafe (no-IOMMU mode). The naming is chosen explicitly to emphasize that using no-IOMMU mode is not ideal.

2. Custom container assignment API does not map to cdev mode
============================================================

The existing rte_vfio_device_setup/release model is fundamentally incompatible with cdev mode, because for custom container cases, the expected flow is that the user binds the IOMMU group (and thus, implicitly, the device itself) to a specific container using rte_vfio_container_group_bind, whereas this step is not needed for cdev as the device fd is assigned to the container straight away.

Therefore, what we do instead is introduce a new API for container device assignment which, semantically, will assign a device to specified container, so that when it is mapped using rte_pci_map_device, the appropriate container is selected. Under the hood though, we essentially transition to getting device fd straight away at assign stage, so that by the time the PCI bus attempts to map the device, it is already mapped and we just return an fd. There is no "unassign" API because release_device already performs that function.

Because the API is now unified around device assignment, the old group-specific API's can be removed and, where appropriate, reimplemented using new API. There were other users of VFIO which relied on group API but only for convenience purposes; no actual VFIO functionality depended on those API's.

List of removed API's:

* rte_vfio_get_group_fd
* rte_vfio_clear_group
* rte_vfio_container_group_bind (replaced by container assign API)
* rte_vfio_container_group_unbind
* rte_vfio_noiommu_is_enabled (replaced by new mode API)

3. The API responsibilities aren't clear and bleed into each other
==================================================================

Some API's do multiple things at once. In particular:

* rte_vfio_get_device_info will setup the device
* rte_vfio_setup_device will get device info

These API's have been adjusted to do one thing only.

4. The API does not need to be public
=====================================

The initial idea for exposing VFIO API was to enable userspace applications to directly map memory for DMA, but it turns out that in practice only drivers use this API. Therefore, the entire VFIO API is made internal, driver-only, and is renamed from rte_vfio to dev_vfio.

v19:

TL;DR: the v18/v19 diff shows no major changes, more could have been done probably (especially on the huge API revamp patch), but rc1 is coming... Compilation per patch still works, hopefully my splitting broke nothing at runtime.

- Rebased so that CI can run on the series (did not happen with v18)
- Reordered patches:
- moved the uAPI update at the end of the series when needed
- moved small cleanups earlier in the series (vhost DMA capability cleanup, bus updates like PCI or fslmc...)
- Replaced bus/pci update with the change I prepared when replying on v18:
the most notable change is that the pci bus object is left in common code
- Fixed (well, removed) VFIO header from FreeBSD and Windows exports list and removed all mentions of "Linux only" in this same header since it is now only exported by Linux
(iow lib/eal/include/dev_vfio.h -> lib/eal/linux/include/dev_vfio.h)
- Squashed the patches touching kernel module: those are mechanical and the diff is small. Also fixed one small string truncation issue reported by AI
- Squashed the two patches around making VFIO internal only: the diff is huge, but the changes are mechanical and I saw no interest in keeping them separate
- Dropped rte_errno updates in patches that did not document the change in eal_vfio.h/dev_vfio.h (such updates were dropped later in the series anyway)
- Split the too big "vfio: cleanup and refactor" patch
- Mechanical changes have been isolated in first patches: like renaming or reorganising structures
- Macros only used in one location were removed from headers
- vfio_containers is not exposed out of eal_vfio.c anymore
- Fixed uapi/linux/vfio.h inclusion (must be included *first*, important because of stddef dependencies)
- Fixed coding style like indentation, or line wrapping for 80 columns(?) or log messages split over multiple lines

v18:
- Adjusted pre-refactor VFIO cleanup to not rely on per-config enabled flag
- Moved loaded module detection from EAL into VFIO
- Added API to check for specific VFIO modules being loaded
- Removed VFIO stubs from non-Linux code by removing PCI bus dependency on VFIO
- Reworked vhost DMA capability check
- Renamed "IOMMU mode" and "safe/unsafe" terminology to IOVA VA/PA
- Fixed typo in FSLMC bus IOVA mode selection

v17:
- Support multiple devices per group in NBL

v16:
- Fixed an unused variable compile error due to typo
- Fixed code for patch 19 being accidentally added into patch 21
- Included the NBL fix[1] in the patchset to enable CI testing

[1] https://patches.dpdk.org/project/dpdk/patch/75e8e3b8ff4d0647e2a5216dcde0d93f3856e821.1787820465.git.anatoly.burakov@intel.com/

v15:
- Fixed resource leak in group mode deduplication path
- On account of kernel 7.3 supporting no-IOMMU mode in kernel version 7.3, split the "VFIO mode" model into two distinct axis: group/cdev, and IOMMU mode

v14:
- Hardened the transitional patches against attempting to use VFIO without having done initialization
- Fixed a bunch of typos, moved a few hunks around to where they belong, and added a more release note entries

v13:
- Addressed feedback from Stephen's AI review:
- Added strdup-based deduplication for group mode to avoid leaking fd's when container assignment API is used
- Added more documentation about cdev mode to Linux GSG
- Fixed comments and log levels in a couple of places
- Renamed the API from rte_vfio_* to dev_vfio_* on account of it no longer being a publicly visible API
- Moved dev_vfio.h into driver SDK headers
- Decoupled VFIO internals from FSLMC and EAL
- Added proper teardown for VFIO subsystem on cleanup

v12:
- Addressed feedback from Stephen's AI review:
- Add release notes updates to patch 2 and 20
- Fix ENXIO typos
- Added a new init step after memory init to enable DMA mapping for cdev

v11:
- Addressed feedback from Stephen's AI review:
- Use CONTAINER_INITIALIZER for reset
- Set container fd to -1 in CONTAINER_INITIALIZER
- Fixed double close()
- Moved VFIO init to earlier in init sequence to account for bus drivers needing no-IOMMU mode status
- Fixed missing ops set for cdev mode, and missing ops reset
- Fixed fd leak on failed attach in cdev

v10:
- Added a patch that renames confusing error labels
- Fixed compiler warning about unused variable

v9:
- Moved erroneous rte_errno-related comments to later in the patchset
- Moved removal of vDPA group fd API's to their respective patches
- Fixed typo in errno comments (ENXIO vs ENOXIO)
- Fixed corruption of group config in secondary process (v8 AI review)

v8:
- Rebase
- Fixed build errors due to variable shadowing
- Removed duplicate fd check as kernel does not provide a way to distinguish between device fd's

v7:
- Rebase
- Added removal of deprecation notices
- Fixed implicit numeric comparison in patch 12

v6:
- Fixed missing header include in vfio cdev file

v5:
- Added back missing uapi patch

v4:
- Fixed issues with documenting rte_vfio_mode enum
- Separated deprecation notices into a separate patchset

v3:
- Make API removal cleaner
- Fix get_group_num usages to align with new API
- Fix issues with function exports
- Fix issues with setup_device returning old-style values in some cases

v2:
- Make the entire API internal
- More aggressive API pruning, complete removal of group API
- Fixed a bug in group mode where device could not be used
- Better documentation and deprecation notice patches
- Moved doc patches to beginning of patchset

Anatoly Burakov (24):
vhost: check DMA capability only once
bus/fslmc: decouple from EAL VFIO
bus/pci: rename mismatching error labels
vfio: make all functions internal
vfio: add module check API
vfio: teardown internals on VFIO cleanup
vfio: split get device info from setup
vfio: add container device assignment API
net/nbl: do not use VFIO group bind API
net/ntnic: use container device assignment API
vdpa/ifc: use container device assignment API
vdpa/nfp: use container device assignment API
vdpa/sfc: use container device assignment API
vhost: remove group-related API from driver
vfio: remove group-based API
vfio: rename some internal types and macros
vfio: declare global configuration
vfio: separate group-based IOMMU types
vfio: add some check on input parameters
vfio: decouple device setup from bus concerns
vfio: introduce IOVA mode
vfio: introduce VFIO mode
uapi: import IOMMUFD header
vfio: introduce cdev mode

David Marchand (2):
bus/pci: move VFIO concerns in Linux implementation
eal: provide VFIO only for Linux

 config/arm/meson.build                    |    1 +
 config/meson.build                        |    1 +
 doc/api/doxy-api-index.md                 |    3 +-
 doc/guides/linux_gsg/linux_drivers.rst    |   30 +
 doc/guides/prog_guide/vhost_lib.rst       |    4 -
 doc/guides/rel_notes/deprecation.rst      |   10 -
 doc/guides/rel_notes/release_26_11.rst    |   12 +
 drivers/bus/cdx/cdx.c                     |    6 +-
 drivers/bus/cdx/cdx_vfio.c                |   38 +-
 drivers/bus/fslmc/fslmc_bus.c             |   12 +-
 drivers/bus/fslmc/fslmc_vfio.c            |   66 +-
 drivers/bus/fslmc/meson.build             |    1 -
 drivers/bus/pci/bsd/pci.c                 |   12 +
 drivers/bus/pci/linux/pci.c               |   39 +-
 drivers/bus/pci/linux/pci_vfio.c          |   84 +-
 drivers/bus/pci/pci_common.c              |   26 +-
 drivers/bus/pci/private.h                 |   41 +
 drivers/bus/pci/windows/pci.c             |   12 +
 drivers/bus/platform/platform.c           |   17 +-
 drivers/crypto/bcmfs/bcmfs_vfio.c         |   23 +-
 drivers/net/hinic3/base/hinic3_hwdev.c    |    5 +-
 drivers/net/nbl/nbl_common/nbl_userdev.c  |   73 +-
 drivers/net/nbl/nbl_common/nbl_userdev.h  |    1 +
 drivers/net/nbl/nbl_include/nbl_include.h |    1 +
 drivers/net/ntnic/ntnic_ethdev.c          |    4 +-
 drivers/net/ntnic/ntnic_vfio.c            |   48 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c             |   54 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c             |    1 -
 drivers/vdpa/nfp/nfp_vdpa.c               |   53 +-
 drivers/vdpa/sfc/sfc_vdpa.c               |   47 +-
 drivers/vdpa/sfc/sfc_vdpa.h               |    2 -
 drivers/vdpa/sfc/sfc_vdpa_hw.c            |   12 +-
 kernel/linux/uapi/linux/iommufd.h         | 1302 ++++++++++
 lib/eal/common/eal_private.h              |   14 -
 lib/eal/freebsd/eal.c                     |  128 -
 lib/eal/include/meson.build               |    1 -
 lib/eal/include/rte_vfio.h                |  338 ---
 lib/eal/linux/eal.c                       |   62 +-
 lib/eal/linux/eal_vfio.c                  | 2661 +++++++++------------
 lib/eal/linux/eal_vfio.h                  |  164 +-
 lib/eal/linux/eal_vfio_cdev.c             |  415 ++++
 lib/eal/linux/eal_vfio_group.c            |  923 +++++++
 lib/eal/linux/eal_vfio_mp_sync.c          |  118 +-
 lib/eal/linux/include/dev_vfio.h          |  451 ++++
 lib/eal/linux/include/meson.build         |    4 +
 lib/eal/linux/meson.build                 |    2 +
 lib/eal/windows/eal.c                     |   23 -
 lib/vhost/socket.c                        |    5 +-
 lib/vhost/vdpa_driver.h                   |    3 -
 lib/vhost/vhost.h                         |    1 +
 lib/vhost/vhost_user.c                    |   16 +-
 51 files changed, 4978 insertions(+), 2392 deletions(-)
 create mode 100644 kernel/linux/uapi/linux/iommufd.h
 delete mode 100644 lib/eal/include/rte_vfio.h
 create mode 100644 lib/eal/linux/eal_vfio_cdev.c
 create mode 100644 lib/eal/linux/eal_vfio_group.c
 create mode 100644 lib/eal/linux/include/dev_vfio.h
Signature · 1 line
2.54.0
#329 lore raw

PATCH v19 1/26 vhost: check DMA capability only once

From: Anatoly Burakov <[email protected]>

Currently, vhost async copy feature will check if VFIO supports DMA mapping on every attempt to add/remove memory region or set memory table. This is not necessary, so instead check this once at new vhost connection, and store that value for future use.

---
 lib/vhost/socket.c     |  5 ++++-
 lib/vhost/vhost.h      |  1 +
 lib/vhost/vhost_user.c | 10 +++++-----
 3 files changed, 10 insertions(+), 6 deletions(-)
lib/vhost/socket.c +4 -1
index 0943b3e9bb..a8f58c95e8 100644
@@ -17,6 +17,7 @@
 #include <eal_export.h>
 #include <rte_thread.h>
 #include <rte_log.h>
+#include <rte_vfio.h>
 
 #include "fd_man.h"
 #include "vduse.h"
@@ -242,8 +243,10 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 	if (vsocket->async_copy) {
 		dev = get_device(vid);
 
-		if (dev)
+		if (dev != NULL) {
 			dev->async_copy = 1;
+			dev->dma_map_available = rte_vfio_is_enabled("vfio");
+		}
 	}
 
 	VHOST_CONFIG_LOG(vsocket->path, INFO, "new device, handle is %d", vid);
lib/vhost/vhost.h +1 -0
index bb4708aed5..75736eed3b 100644
@@ -499,6 +499,7 @@ struct __rte_cache_aligned virtio_net {
 	RTE_ATOMIC(int16_t)	broadcast_rarp;
 	uint32_t		nr_vring;
 	int			async_copy;
+	bool			dma_map_available;
 
 	int			extbuf;
 	int			linearbuf;
lib/vhost/vhost_user.c +5 -5
index 020c993b29..2d91722fcc 100644
@@ -267,7 +267,7 @@ free_all_mem_regions(struct virtio_net *dev)
 	if (!dev || !dev->mem)
 		return;
 
-	if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+	if (dev->async_copy && dev->dma_map_available)
 		async_dma_map(dev, false);
 
 	for (i = 0; i < VHOST_MEMORY_MAX_NREGIONS; i++) {
@@ -1564,7 +1564,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev,
 		dev->mem->nregions++;
 	}
 
-	if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+	if (dev->async_copy && dev->dma_map_available)
 		async_dma_map(dev, true);
 
 	if (vhost_user_postcopy_register(dev, main_fd, ctx) < 0)
@@ -1750,7 +1750,7 @@ vhost_user_add_mem_reg(struct virtio_net **pdev,
 
 	dev->mem->nregions++;
 
-	if (dev->async_copy && rte_vfio_is_enabled("vfio")) {
+	if (dev->async_copy && dev->dma_map_available) {
 		if (async_dma_map_region(dev, reg, true) < 0)
 			goto free_new_region_no_dma;
 	}
@@ -1791,7 +1791,7 @@ vhost_user_add_mem_reg(struct virtio_net **pdev,
 	return RTE_VHOST_MSG_RESULT_OK;
 
 free_new_region:
-	if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+	if (dev->async_copy && dev->dma_map_available)
 		async_dma_map_region(dev, reg, false);
 free_new_region_no_dma:
 	remove_guest_pages(dev, reg);
@@ -1827,7 +1827,7 @@ vhost_user_rem_mem_reg(struct virtio_net **pdev,
 		if (region->userspace_addr == current_region->guest_user_addr
 			&& region->guest_phys_addr == current_region->guest_phys_addr
 			&& region->memory_size == current_region->size) {
-			if (dev->async_copy && rte_vfio_is_enabled("vfio"))
+			if (dev->async_copy && dev->dma_map_available)
 				async_dma_map_region(dev, current_region, false);
 			if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))
 				vhost_user_iotlb_cache_remove(dev,
Signature · 1 line
2.54.0
#330 lore raw

PATCH v19 2/26 bus/fslmc: decouple from EAL VFIO

In reply to David Marchand

From: Anatoly Burakov <[email protected]>

FSLMC bus has its own VFIO implementation which is completely separate from one in EAL or rte_vfio. Yet, it references a couple of macros and uses a struct definition. Fully decoupling them is not a huge lift, so do that.

---
 drivers/bus/fslmc/fslmc_vfio.c | 50 +++++++++++++++++++++-------------
 drivers/bus/fslmc/meson.build  |  1 -
 2 files changed, 31 insertions(+), 20 deletions(-)
drivers/bus/fslmc/fslmc_vfio.c +31 -19
index 412b70e5ae..8d39895bac 100644
@@ -35,7 +35,6 @@
 #include <dev_driver.h>
 #include <rte_eal_memconfig.h>
 #include <rte_vfio.h>
-#include <eal_vfio.h>
 
 #include "private.h"
 #include "fslmc_vfio.h"
@@ -73,8 +72,21 @@ struct fslmc_dmaseg_list fslmc_iosegs =
 static uint64_t fslmc_mem_va2iova = RTE_BAD_IOVA;
 static int fslmc_mem_map_num;
 
+#define FSLMC_VFIO_SOCKET_OK 0x0
+#define FSLMC_VFIO_SOCKET_NO_FD 0x1
+#define FSLMC_VFIO_SOCKET_ERR 0xFF
+
+struct fslmc_vfio_mp_param {
+	int req;
+	int result;
+	union {
+		int group_num;
+		int iommu_type_id;
+	};
+};
+
 struct fslmc_mem_param {
-	struct vfio_mp_param mp_param;
+	struct fslmc_vfio_mp_param mp_param;
 	struct fslmc_dmaseg_list memsegs;
 	struct fslmc_dmaseg_list iosegs;
 	uint64_t mem_va2iova;
@@ -386,7 +398,7 @@ fslmc_vfio_open_group_fd(const char *group_name)
 	struct rte_mp_msg mp_req, *mp_rep;
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
-	struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param;
+	struct fslmc_vfio_mp_param *p = (struct fslmc_vfio_mp_param *)mp_req.param;
 	int iommu_group_num, ret;
 
 	vfio_group_fd = fslmc_vfio_group_fd_by_name(group_name);
@@ -417,10 +429,10 @@ fslmc_vfio_open_group_fd(const char *group_name)
 	if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
 	    mp_reply.nb_received == 1) {
 		mp_rep = &mp_reply.msgs[0];
-		p = (struct vfio_mp_param *)mp_rep->param;
-		if (p->result == SOCKET_OK && mp_rep->num_fds == 1)
+		p = (struct fslmc_vfio_mp_param *)mp_rep->param;
+		if (p->result == FSLMC_VFIO_SOCKET_OK && mp_rep->num_fds == 1)
 			vfio_group_fd = mp_rep->fds[0];
-		else if (p->result == SOCKET_NO_FD)
+		else if (p->result == FSLMC_VFIO_SOCKET_NO_FD)
 			DPAA2_BUS_ERR("Bad VFIO group fd");
 	}
 
@@ -490,7 +502,7 @@ fslmc_vfio_open_container_fd(void)
 	struct rte_mp_msg mp_req, *mp_rep;
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
-	struct vfio_mp_param *p = (void *)mp_req.param;
+	struct fslmc_vfio_mp_param *p = (void *)mp_req.param;
 
 	if (fslmc_vfio_container_fd() > 0)
 		return fslmc_vfio_container_fd();
@@ -551,7 +563,7 @@ fslmc_vfio_open_container_fd(void)
 
 	mp_rep = &mp_reply.msgs[0];
 	p = (void *)mp_rep->param;
-	if (p->result == SOCKET_OK && mp_rep->num_fds == 1) {
+	if (p->result == FSLMC_VFIO_SOCKET_OK && mp_rep->num_fds == 1) {
 		vfio_container_fd = mp_rep->fds[0];
 		free(mp_reply.msgs);
 	}
@@ -594,8 +606,8 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 	int fd = -1;
 	int ret;
 	struct rte_mp_msg reply;
-	struct vfio_mp_param *r = (void *)reply.param;
-	const struct vfio_mp_param *m = (const void *)msg->param;
+	struct fslmc_vfio_mp_param *r = (void *)reply.param;
+	const struct fslmc_vfio_mp_param *m = (const void *)msg->param;
 	struct fslmc_mem_param *map;
 
 	if (msg->len_param != sizeof(*m)) {
@@ -612,13 +624,13 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 		r->group_num = m->group_num;
 		fd = fslmc_vfio_group_fd_by_id(m->group_num);
 		if (fd < 0) {
-			r->result = SOCKET_ERR;
+			r->result = FSLMC_VFIO_SOCKET_ERR;
 		} else if (!fd) {
 			/* if group exists but isn't bound to VFIO driver */
-			r->result = SOCKET_NO_FD;
+			r->result = FSLMC_VFIO_SOCKET_NO_FD;
 		} else {
 			/* if group exists and is bound to VFIO driver */
-			r->result = SOCKET_OK;
+			r->result = FSLMC_VFIO_SOCKET_OK;
 			reply.num_fds = 1;
 			reply.fds[0] = fd;
 		}
@@ -628,9 +640,9 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 		r->req = FSLMC_VFIO_SOCKET_REQ_CONTAINER;
 		fd = fslmc_vfio_container_fd();
 		if (fd <= 0) {
-			r->result = SOCKET_ERR;
+			r->result = FSLMC_VFIO_SOCKET_ERR;
 		} else {
-			r->result = SOCKET_OK;
+			r->result = FSLMC_VFIO_SOCKET_OK;
 			reply.num_fds = 1;
 			reply.fds[0] = fd;
 		}
@@ -640,7 +652,7 @@ fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
 		map = (void *)reply.param;
 		r = &map->mp_param;
 		r->req = FSLMC_VFIO_SOCKET_REQ_MEM;
-		r->result = SOCKET_OK;
+		r->result = FSLMC_VFIO_SOCKET_OK;
 		map->memsegs = fslmc_memsegs;
 		map->iosegs = fslmc_iosegs;
 		map->mem_va2iova = fslmc_mem_va2iova;
@@ -666,19 +678,19 @@ fslmc_vfio_mp_sync_mem_req(void)
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
 	int ret = 0;
-	struct vfio_mp_param *mp_param;
+	struct fslmc_vfio_mp_param *mp_param;
 	struct fslmc_mem_param *mem_rsp;
 
 	mp_param = (void *)mp_req.param;
 	memset(&mp_req, 0, sizeof(struct rte_mp_msg));
 	mp_param->req = FSLMC_VFIO_SOCKET_REQ_MEM;
 	rte_strscpy(mp_req.name, FSLMC_VFIO_MP, sizeof(mp_req.name));
-	mp_req.len_param = sizeof(struct vfio_mp_param);
+	mp_req.len_param = sizeof(struct fslmc_vfio_mp_param);
 	if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
 		mp_reply.nb_received == 1) {
 		mp_rep = &mp_reply.msgs[0];
 		mem_rsp = (struct fslmc_mem_param *)mp_rep->param;
-		if (mem_rsp->mp_param.result == SOCKET_OK) {
+		if (mem_rsp->mp_param.result == FSLMC_VFIO_SOCKET_OK) {
 			fslmc_memsegs = mem_rsp->memsegs;
 			fslmc_mem_va2iova = mem_rsp->mem_va2iova;
 			fslmc_mem_map_num = mem_rsp->mem_map_num;
drivers/bus/fslmc/meson.build +0 -1
index 50d9e91a37..55f9d2e808 100644
@@ -30,4 +30,3 @@ sources = files(
 )
 
 includes += include_directories('mc', 'qbman/include', 'portal')
-includes += include_directories('../../../lib/eal/linux')
Signature · 1 line
2.54.0
#331 lore raw

PATCH v19 3/26 bus/pci: rename mismatching error labels

In reply to David Marchand

From: Anatoly Burakov <[email protected]>

Currently, there are two VFIO map functions - primary and secondary - that use a very similar goto error pattern. However, the label names are confusing.

Specifically, for primary, we have three error labels: vfio_res (release VFIO resource), vfio_dev_fd (close the fd), and map (unmap all the mapped regions). For secondary, there is vfio_dev (close the fd), and vfio_dev_fd (unmap all mapped regions).

For consistency, align secondary process function's error labels to match semantics of how they work in primary process function.

---
 drivers/bus/pci/linux/pci_vfio.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/bus/pci/linux/pci_vfio.c +7 -7
index bc5c5c2499..a67de6ea02 100644
@@ -968,7 +968,7 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 
 	ret = pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info);
 	if (ret)
-		goto err_vfio_dev;
+		goto err_vfio_dev_fd;
 
 	/* map BARs */
 	maps = vfio_res->maps;
@@ -979,14 +979,14 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 			if (ret < 0) {
 				PCI_LOG(ERR, "%s sparse mapping BAR%i failed: %s",
 					pci_addr, i, strerror(errno));
-				goto err_vfio_dev_fd;
+				goto err_map;
 			}
 		} else {
 			ret = pci_vfio_mmap_bar(vfio_dev_fd, vfio_res, i, MAP_FIXED);
 			if (ret < 0) {
 				PCI_LOG(ERR, "%s mapping BAR%i failed: %s",
 					pci_addr, i, strerror(errno));
-				goto err_vfio_dev_fd;
+				goto err_map;
 			}
 		}
 
@@ -995,17 +995,17 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 
 	/* we need save vfio_dev_fd, so it can be used during release */
 	if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd))
-		goto err_vfio_dev_fd;
+		goto err_map;
 	if (rte_intr_dev_fd_set(dev->vfio_req_intr_handle, vfio_dev_fd))
-		goto err_vfio_dev_fd;
+		goto err_map;
 
 	return 0;
-err_vfio_dev_fd:
+err_map:
 	for (j = 0; j < i; j++) {
 		if (maps[j].addr)
 			pci_unmap_resource(maps[j].addr, maps[j].size);
 	}
-err_vfio_dev:
+err_vfio_dev_fd:
 	rte_vfio_release_device(rte_pci_get_sysfs_path(),
 			pci_addr, vfio_dev_fd);
 	return -1;
Signature · 1 line
2.54.0
#332 lore raw

PATCH v19 4/26 bus/pci: move VFIO concerns in Linux implementation

In reply to David Marchand

Make the common PCI code independent of the VFIO API. Move VFIO dma map/unmap operation in Linux only code: adopt the same approach than IOMMU VA support and expose a OS specific handler which calls a common implementation for FreeBSD and Windows.

---
 drivers/bus/pci/bsd/pci.c     | 12 ++++++++++
 drivers/bus/pci/linux/pci.c   | 35 ++++++++++++++++++++++++++++++
 drivers/bus/pci/pci_common.c  | 26 +++++-----------------
 drivers/bus/pci/private.h     | 41 +++++++++++++++++++++++++++++++++++
 drivers/bus/pci/windows/pci.c | 12 ++++++++++
 5 files changed, 105 insertions(+), 21 deletions(-)
drivers/bus/pci/bsd/pci.c +12 -0
index c6df31d486..2af99d3678 100644
@@ -397,6 +397,18 @@ rte_pci_scan(void)
 	return -1;
 }
 
+int
+pci_device_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
+{
+	return pci_dma_map(dev, addr, iova, len);
+}
+
+int
+pci_device_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
+{
+	return pci_dma_unmap(dev, addr, iova, len);
+}
+
 bool
 pci_device_iommu_support_va(__rte_unused const struct rte_pci_device *dev)
 {
drivers/bus/pci/linux/pci.c +35 -0
index 9aae0a5d14..bcb5b3278d 100644
@@ -5,6 +5,7 @@
 #include <string.h>
 #include <dirent.h>
 
+#include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_pci.h>
 #include <rte_bus_pci.h>
@@ -474,6 +475,40 @@ rte_pci_scan(void)
 	return -1;
 }
 
+int
+pci_device_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
+{
+	int ret = pci_dma_map(dev, addr, iova, len);
+
+	if (ret == -1 && rte_errno == ENOTSUP) {
+		struct rte_pci_device *pdev = RTE_BUS_DEVICE(dev, *pdev);
+
+		/* In case driver doesn't provide any specific mapping try fallback to VFIO. */
+		if (pdev->kdrv == RTE_PCI_KDRV_VFIO)
+			ret = rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD,
+				(uintptr_t)addr, iova, len);
+	}
+
+	return ret;
+}
+
+int
+pci_device_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
+{
+	int ret = pci_dma_unmap(dev, addr, iova, len);
+
+	if (ret == -1 && rte_errno == ENOTSUP) {
+		struct rte_pci_device *pdev = RTE_BUS_DEVICE(dev, *pdev);
+
+		/* In case driver doesn't provide any specific mapping try fallback to VFIO. */
+		if (pdev->kdrv == RTE_PCI_KDRV_VFIO)
+			return rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD,
+				(uintptr_t)addr, iova, len);
+	}
+
+	return ret;
+}
+
 #if defined(RTE_ARCH_X86)
 bool
 pci_device_iommu_support_va(const struct rte_pci_device *dev)
drivers/bus/pci/pci_common.c +5 -21
index dc8db80d3b..3770b4ad75 100644
@@ -25,7 +25,6 @@
 #include <rte_string_fns.h>
 #include <rte_common.h>
 #include <rte_devargs.h>
-#include <rte_vfio.h>
 #include <rte_tailq.h>
 
 #include "private.h"
@@ -474,7 +473,7 @@ pci_sigbus_handler(const void *failure_addr)
 	return ret;
 }
 
-static int
+int
 pci_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 {
 	struct rte_pci_device *pdev = RTE_BUS_DEVICE(dev, *pdev);
@@ -482,19 +481,12 @@ pci_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 
 	if (pdrv->dma_map != NULL)
 		return pdrv->dma_map(pdev, addr, iova, len);
-	/**
-	 *  In case driver don't provides any specific mapping
-	 *  try fallback to VFIO.
-	 */
-	if (pdev->kdrv == RTE_PCI_KDRV_VFIO)
-		return rte_vfio_container_dma_map
-				(RTE_VFIO_DEFAULT_CONTAINER_FD, (uintptr_t)addr,
-				 iova, len);
+
 	rte_errno = ENOTSUP;
 	return -1;
 }
 
-static int
+int
 pci_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 {
 	struct rte_pci_device *pdev = RTE_BUS_DEVICE(dev, *pdev);
@@ -502,14 +494,6 @@ pci_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
 
 	if (pdrv->dma_unmap != NULL)
 		return pdrv->dma_unmap(pdev, addr, iova, len);
-	/**
-	 *  In case driver don't provides any specific mapping
-	 *  try fallback to VFIO.
-	 */
-	if (pdev->kdrv == RTE_PCI_KDRV_VFIO)
-		return rte_vfio_container_dma_unmap
-				(RTE_VFIO_DEFAULT_CONTAINER_FD, (uintptr_t)addr,
-				 iova, len);
 	rte_errno = ENOTSUP;
 	return -1;
 }
@@ -727,8 +711,8 @@ struct rte_bus rte_pci_bus = {
 	.parse = pci_parse,
 	.dev_compare = pci_dev_compare,
 	.devargs_parse = rte_pci_devargs_parse,
-	.dma_map = pci_dma_map,
-	.dma_unmap = pci_dma_unmap,
+	.dma_map = pci_device_dma_map,
+	.dma_unmap = pci_device_dma_unmap,
 	.get_iommu_class = rte_pci_get_iommu_class,
 	.dev_iterate = rte_pci_dev_iterate,
 	.hot_unplug_handler = pci_hot_unplug_handler,
drivers/bus/pci/private.h +41 -0

47 lines not on this page · raw message

drivers/bus/pci/windows/pci.c +12 -0
index 7b51301d1e..383c6bdc2f 100644
@@ -120,6 +120,18 @@ rte_pci_mmio_write(const struct rte_pci_device *dev, int bar,
 	return len;
 }
 
+int
+pci_device_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
+{
+	return pci_dma_map(dev, addr, iova, len);
+}
+
+int
+pci_device_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
+{
+	return pci_dma_unmap(dev, addr, iova, len);
+}
+
 enum rte_iova_mode
 pci_device_iova_mode(const struct rte_pci_driver *pdrv __rte_unused,
 		const struct rte_pci_device *pdev __rte_unused)
Signature · 1 line
2.54.0
author Acked-by on v19 4/26
#333 lore raw

Re: [PATCH v19 04/26] bus/pci: move VFIO concerns in Linux implementation

Quoted 7 lines · David Marchand

Make the common PCI code independent of the VFIO API. Move VFIO dma map/unmap operation in Linux only code: adopt the same approach than IOMMU VA support and expose a OS specific handler which calls a common implementation for FreeBSD and Windows.

---

Signature · 2 lines
Thanks,
Anatoly
#334 lore raw

PATCH v19 5/26 eal: provide VFIO only for Linux

In reply to David Marchand

The VFIO API is used only in Linux related code.

We can hide this API on other OSes and unexport associated symbols, before the next commit which makes this API entirely internal.

---
 lib/eal/freebsd/eal.c                  | 128 -------------------------
 lib/eal/include/meson.build            |   1 -
 lib/eal/linux/include/meson.build      |   1 +
 lib/eal/{ => linux}/include/rte_vfio.h |  31 ------
 lib/eal/windows/eal.c                  |  23 -----
 5 files changed, 1 insertion(+), 183 deletions(-)
 rename lib/eal/{ => linux}/include/rte_vfio.h (88%)
lib/eal/freebsd/eal.c +0 -128
index 8b1ba5b99b..faf5f0e911 100644
@@ -41,7 +41,6 @@
 #include <rte_dev.h>
 #include <rte_devargs.h>
 #include <rte_version.h>
-#include <rte_vfio.h>
 #include <malloc_heap.h>
 #include <telemetry_internal.h>
 
@@ -818,130 +817,3 @@ void
 rte_eal_vfio_get_vf_token(__rte_unused rte_uuid_t vf_token)
 {
 }
-
-RTE_EXPORT_SYMBOL(rte_vfio_setup_device)
-int rte_vfio_setup_device(__rte_unused const char *sysfs_base,
-		      __rte_unused const char *dev_addr,
-		      __rte_unused int *vfio_dev_fd,
-		      __rte_unused struct vfio_device_info *device_info)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_release_device)
-int rte_vfio_release_device(__rte_unused const char *sysfs_base,
-			__rte_unused const char *dev_addr,
-			__rte_unused int fd)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_enable)
-int rte_vfio_enable(__rte_unused const char *modname)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_is_enabled)
-int rte_vfio_is_enabled(__rte_unused const char *modname)
-{
-	return 0;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_noiommu_is_enabled)
-int rte_vfio_noiommu_is_enabled(void)
-{
-	return 0;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_clear_group)
-int rte_vfio_clear_group(__rte_unused int vfio_group_fd)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_num)
-int
-rte_vfio_get_group_num(__rte_unused const char *sysfs_base,
-		       __rte_unused const char *dev_addr,
-		       __rte_unused int *iommu_group_num)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_get_container_fd)
-int
-rte_vfio_get_container_fd(void)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_get_group_fd)
-int
-rte_vfio_get_group_fd(__rte_unused int iommu_group_num)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_container_create)
-int
-rte_vfio_container_create(void)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_container_destroy)
-int
-rte_vfio_container_destroy(__rte_unused int container_fd)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_bind)
-int
-rte_vfio_container_group_bind(__rte_unused int container_fd,
-		__rte_unused int iommu_group_num)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_container_group_unbind)
-int
-rte_vfio_container_group_unbind(__rte_unused int container_fd,
-		__rte_unused int iommu_group_num)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_map)
-int
-rte_vfio_container_dma_map(__rte_unused int container_fd,
-			__rte_unused uint64_t vaddr,
-			__rte_unused uint64_t iova,
-			__rte_unused uint64_t len)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_unmap)
-int
-rte_vfio_container_dma_unmap(__rte_unused int container_fd,
-			__rte_unused uint64_t vaddr,
-			__rte_unused uint64_t iova,
-			__rte_unused uint64_t len)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
lib/eal/include/meson.build +0 -1
index aef5824e5f..67c6a8021a 100644
@@ -55,7 +55,6 @@ headers += files(
         'rte_trace_point_register.h',
         'rte_uuid.h',
         'rte_version.h',
-        'rte_vfio.h',
 )
 
 driver_sdk_headers = files(
lib/eal/linux/include/meson.build +1 -0
index 7d18dd52f1..00854cd6fa 100644
@@ -5,4 +5,5 @@ includes += include_directories('.')
 
 headers += files(
         'rte_os.h',
+        'rte_vfio.h',
 )
lib/eal/linux/include/rte_vfio.h renamed from lib/eal/include/rte_vfio.h +0 -31
similarity index 88%
rename from lib/eal/include/rte_vfio.h
rename to lib/eal/linux/include/rte_vfio.h
index d1e8bce56b..432ad3c10d 100644
@@ -19,8 +19,6 @@
 extern "C" {
 #endif
 
-#ifdef RTE_EXEC_ENV_LINUX
-
 #define RTE_VFIO_DIR "/dev/vfio"
 #define RTE_VFIO_CONTAINER_PATH "/dev/vfio/vfio"
 #define RTE_VFIO_GROUP_FMT "/dev/vfio/%u"
@@ -28,8 +26,6 @@ extern "C" {
 #define RTE_VFIO_NOIOMMU_MODE      \
 	"/sys/module/vfio/parameters/enable_unsafe_noiommu_mode"
 
-#endif /* RTE_EXEC_ENV_LINUX */
-
 /* we don't need an actual definition, only pointer is used */
 struct vfio_device_info;
 
@@ -40,9 +36,6 @@ struct vfio_device_info;
  * It discovers the configured I/O MMU groups or sets a new one for the device.
  * If a new groups is assigned, the DMA mapping is performed.
  *
- * This function is only relevant to linux and will return
- * an error on BSD.
- *
  * @param sysfs_base
  *   sysfs path prefix.
  *
@@ -66,9 +59,6 @@ int rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 /**
  * Release a device mapped to a VFIO-managed I/O MMU group.
  *
- * This function is only relevant to linux and will return
- * an error on BSD.
- *
  * @param sysfs_base
  *   sysfs path prefix.
  *
@@ -87,9 +77,6 @@ int rte_vfio_release_device(const char *sysfs_base, const char *dev_addr, int fd
 /**
  * Enable a VFIO-related kmod.
  *
- * This function is only relevant to linux and will return
- * an error on BSD.
- *
  * @param modname
  *   kernel module name.
  *
@@ -102,8 +89,6 @@ int rte_vfio_enable(const char *modname);
 /**
  * Check whether a VFIO-related kmod is enabled.
  *
- * This function is only relevant to Linux.
- *
  * @param modname
  *   kernel module name.
  *
@@ -116,8 +101,6 @@ int rte_vfio_is_enabled(const char *modname);
 /**
  * Whether VFIO NOIOMMU mode is enabled.
  *
- * This function is only relevant to Linux.
- *
  * @return
  *   1 if true.
  *   0 if false.
@@ -128,9 +111,6 @@ int rte_vfio_noiommu_is_enabled(void);
 /**
  * Remove group fd from internal VFIO group fd array/
  *
- * This function is only relevant to linux and will return
- * an error on BSD.
- *
  * @param vfio_group_fd
  *   VFIO Group FD.
  *
@@ -144,9 +124,6 @@ rte_vfio_clear_group(int vfio_group_fd);
 /**
  * Parse IOMMU group number for a device
  *
- * This function is only relevant to linux and will return
- * an error on BSD.
- *
  * @param sysfs_base
  *   sysfs path prefix.
  *
@@ -168,8 +145,6 @@ rte_vfio_get_group_num(const char *sysfs_base,
 /**
  * Get device information
  *
- * This function is only relevant to Linux and will return an error on BSD.
- *
  * @param sysfs_base
  *   sysfs path prefix.
  *
@@ -194,9 +169,6 @@ rte_vfio_get_device_info(const char *sysfs_base, const char *dev_addr,
 /**
  * Get the default VFIO container fd
  *
- * This function is only relevant to linux and will return
- * an error on BSD.
- *
  * @return
  *  > 0 default container fd
  *  < 0 if VFIO is not enabled or not supported
@@ -207,9 +179,6 @@ rte_vfio_get_container_fd(void);
 /**
  * Open VFIO group fd or get an existing one
  *
- * This function is only relevant to linux and will return
- * an error on BSD.
- *
  * @param iommu_group_num
  *   iommu group number
  *
lib/eal/windows/eal.c +0 -23
index 6dacae7235..cac8faa53d 100644
@@ -24,7 +24,6 @@
 #include <eal_options.h>
 #include <eal_private.h>
 #include <rte_service_component.h>
-#include <rte_vfio.h>
 
 #include "eal_firmware.h"
 #include "eal_hugepages.h"
@@ -453,28 +452,6 @@ eal_asprintf(char **buffer, const char *format, ...)
 	return ret;
 }
 
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_map)
-int
-rte_vfio_container_dma_map(__rte_unused int container_fd,
-			__rte_unused uint64_t vaddr,
-			__rte_unused uint64_t iova,
-			__rte_unused uint64_t len)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
-RTE_EXPORT_SYMBOL(rte_vfio_container_dma_unmap)
-int
-rte_vfio_container_dma_unmap(__rte_unused int container_fd,
-			__rte_unused uint64_t vaddr,
-			__rte_unused uint64_t iova,
-			__rte_unused uint64_t len)
-{
-	rte_errno = ENOTSUP;
-	return -1;
-}
-
 RTE_EXPORT_INTERNAL_SYMBOL(rte_firmware_read)
 int
 rte_firmware_read(__rte_unused const char *name,
Signature · 1 line
2.54.0