Re: [PATCH v10 00/20] Support VFIO cdev API in DPDK
Stephen Hemminger <[email protected]>
| Newsgroups | org.dpdk.dev |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 6 Aug 2026 15:11:00 +0100 Anatoly Burakov <[email protected]> wrote: > 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, and clarify API responsibilities. > > 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 interface is still around, and will need to be kept in DPDK both > for compatibility reasons, as well as supporting special cases (FSLMC bus, NBL > driver, no-IOMMU mode etc.), but it is now internal-only and not exposed through > the API the way it was before. > > To enable this, VFIO is heavily refactored, so that the code can support both > modes while relying on (mostly) common infrastructure. > > Note that 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. > > Additionally, a new `rte_vfio_get_mode` API is added for those cases that need > some introspection into VFIO's internals, with three new modes: group > (old-style), no-iommu (old-style but without IOMMU), and cdev (the new mode). > Although no-IOMMU is 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. The current plan for kernel community is to *not* introduce no-IOMMU > cdev implementation, and IOMMUFD's own group API compatibility layer also does > not implement no-IOMMU mode, which is why this will be kept for compatibility > for these use cases. > > 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. Therefore, group > API's are removed and, where appropriate, replaced with the new 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) > > 2. 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. > > 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 (20): > uapi: update to v6.17 and add iommufd.h > vfio: make all functions internal > 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 mode API > bus/fslmc: use the new VFIO mode API > net/hinic3: use the new VFIO mode API > net/ntnic: use the new VFIO mode API > vfio: remove no-IOMMU check API > vfio: introduce cdev mode > > config/arm/meson.build | 1 + > config/meson.build | 1 + > doc/guides/prog_guide/vhost_lib.rst | 4 - > doc/guides/rel_notes/deprecation.rst | 10 - > drivers/bus/cdx/cdx_vfio.c | 25 +- > drivers/bus/fslmc/fslmc_bus.c | 10 +- > drivers/bus/fslmc/fslmc_vfio.c | 6 +- > drivers/bus/pci/linux/pci.c | 2 +- > drivers/bus/pci/linux/pci_vfio.c | 47 +- > drivers/bus/platform/platform.c | 9 +- > drivers/crypto/bcmfs/bcmfs_vfio.c | 14 +- > drivers/net/hinic3/base/hinic3_hwdev.c | 3 +- > drivers/net/nbl/nbl_common/nbl_userdev.c | 21 +- > drivers/net/nbl/nbl_include/nbl_include.h | 1 + > drivers/net/ntnic/ntnic_ethdev.c | 2 +- > drivers/net/ntnic/ntnic_vfio.c | 30 +- > drivers/vdpa/ifc/ifcvf_vdpa.c | 34 +- > drivers/vdpa/mlx5/mlx5_vdpa.c | 1 - > drivers/vdpa/nfp/nfp_vdpa.c | 37 +- > drivers/vdpa/sfc/sfc_vdpa.c | 39 +- > drivers/vdpa/sfc/sfc_vdpa.h | 2 - > 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/freebsd/eal.c | 98 +- > lib/eal/include/rte_vfio.h | 387 ++-- > lib/eal/linux/eal_vfio.c | 2444 ++++++++------------- > lib/eal/linux/eal_vfio.h | 167 +- > lib/eal/linux/eal_vfio_cdev.c | 390 ++++ > lib/eal/linux/eal_vfio_group.c | 984 +++++++++ > lib/eal/linux/eal_vfio_mp_sync.c | 80 +- > lib/eal/linux/meson.build | 2 + > lib/eal/windows/eal.c | 4 +- > lib/vhost/vdpa_driver.h | 3 - > 35 files changed, 4263 insertions(+), 1903 deletions(-) > create mode 100644 kernel/linux/uapi/linux/iommufd.h > create mode 100644 lib/eal/linux/eal_vfio_cdev.c > create mode 100644 lib/eal/linux/eal_vfio_group.c > Still lots of open AI review feedback: Patch 14/20 (vfio: cleanup and refactor) Error: close(fd 0) on the container error path. CONTAINER_INITIALIZER in eal_vfio.h sets only the mem_maps lock, so container_fd is 0: #define CONTAINER_INITIALIZER \ ((struct container){ \ .mem_maps = {.lock = RTE_SPINLOCK_RECURSIVE_INITIALIZER,}, \ }) vfio_container_erase() then does if (cfg->container_fd >= 0 && close(cfg->container_fd)) so any container allocated but not yet given an fd closes stdin on teardown. rte_vfio_container_create() reaches this from three arms (group open failure, iommufd open failure, default:), and vfio_select_mode()'s err label reaches it too. The pre-refactor code initialized every vfio_cfgs[i].vfio_container_fd to -1. Add .container_fd = -1 to CONTAINER_INITIALIZER, and use that initializer in vfio_container_erase() rather than (struct container){0}. Error: double close in vfio_has_supported_extensions(). The VFIO_CHECK_EXTENSION failure path closes vfio_container_fd and returns -1, and vfio_group_open_container_fd() closes it again: ret = vfio_has_supported_extensions(vfio_container_fd); if (ret) { EAL_LOG(DEBUG, "No supported IOMMU extensions found!"); close(vfio_container_fd); return -1; } Upstream had the close in the callee on both of its error paths and none in the caller. The refactor added the caller close but removed only the n_extensions == 0 close, leaving the ioctl path closing twice. Drop the close() inside vfio_has_supported_extensions(). Warning: no release notes. The series makes the whole rte_vfio API internal, removes five public functions, and adds cdev mode. Only deprecation.rst is touched; release_26_11.rst needs "Removed Items" and "New Features" entries. Patch 15/20 (bus/pci: use the new VFIO mode API) Error: noiommu is never detected. pci_device_iova_mode() runs under rte_bus_get_iommu_class() at eal.c:689; rte_vfio_enable() does not run until :775. rte_vfio_get_mode() returns RTE_VFIO_MODE_NONE at that point, so is_vfio_noiommu_enabled latches to 0 and IOVA VA is chosen on a noiommu system. rte_vfio_noiommu_is_enabled() read the sysfs knob and did not depend on VFIO init. Patch 16/20 (bus/fslmc: use the new VFIO mode API) Error: fslmc bus scan fails on every system. rte_fslmc_scan() runs from rte_bus_scan() at eal.c:680, also before rte_vfio_enable(), so if (rte_vfio_get_mode() != RTE_VFIO_MODE_GROUP && rte_vfio_get_mode() != RTE_VFIO_MODE_NOIOMMU) { ret = -EINVAL; goto scan_fail; } always takes the failure branch and no DPAA2 device is ever scanned. The same ordering issue applies to rte_dpaa2_get_iommu_class() and to fslmc_vfio_add_group(), which will now always select VFIO_TYPE1_IOMMU. Warning: the new scan_fail branch logs nothing, unlike every other failure in that function, so the failure is silent. Patch 20/20 (vfio: introduce cdev mode) Error: vfio_cfg.ops is never set in a cdev-mode secondary. The only assignment is in vfio_cdev_enable(), reached solely from the primary arm of vfio_select_mode(); the secondary arm calls vfio_sync_mode() and vfio_cdev_sync_ioas(), neither of which touches ops. Every rte_vfio_container_dma_map()/dma_unmap() in a cdev secondary therefore fails in vfio_dma_mem_map() with "VFIO support not initialized". A container made by rte_vfio_container_create() in a secondary has the same problem: iommufd opened, IOAS allocated, ops NULL. Set ops in the secondary cdev path. Note also that container_dma_map()/container_dma_unmap() dereference vfio_cfg.ops->partial_unmap with no NULL check; only vfio_dma_mem_map() guards it. Patch 3/20 (bus/pci: rename mismatching error labels) Info: "Specifcally" in the commit body. Patch 6/20 (net/nbl: do not use VFIO group bind API) Info: blank line needed between the declaration and the statements in nbl_open_group_fd().