Simplify the VFIOIOMMUClass interface by removing the dma_map_file handler. Move the logic to decide between the standard virtual and file-backed mapping into the IOMMUFD backend, utilizing the MemoryRegion already passed to the dma_map handler.
This removes redundant dispatch logic from the generic container layer and let backends to manage their own mapping strategies. This is similar to the vfio-user implementation. Signed-off-by: Cédric Le Goater <[email protected]> --- include/hw/vfio/vfio-container.h | 15 ---------- hw/vfio/container.c | 38 ------------------------ hw/vfio/iommufd.c | 50 +++++++++++++++++++++++--------- 3 files changed, 37 insertions(+), 66 deletions(-) diff --git a/include/hw/vfio/vfio-container.h b/include/hw/vfio/vfio-container.h index a7d5c5ed679a0338937ae02f37140d94720f6f11..c70828a0529cb2b41162a8bd452da1d9c20bc08f 100644 --- a/include/hw/vfio/vfio-container.h +++ b/include/hw/vfio/vfio-container.h @@ -172,21 +172,6 @@ struct VFIOIOMMUClass { int (*dma_map)(const VFIOContainer *bcontainer, hwaddr iova, uint64_t size, void *vaddr, bool readonly, MemoryRegion *mr); - /** - * @dma_map_file - * - * Map a file range for the container. - * - * @bcontainer: #VFIOContainer to use for map - * @iova: start address to map - * @size: size of the range to map - * @fd: descriptor of the file to map - * @start: starting file offset of the range to map - * @readonly: map read only if true - */ - int (*dma_map_file)(const VFIOContainer *bcontainer, - hwaddr iova, uint64_t size, - int fd, unsigned long start, bool readonly); /** * @dma_unmap * diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 56bd9ac0095df7b0f4da85f1d8dcb8d571fa9f2a..d09a6637324c6bf29b2fe22369082f87e280c98f 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -15,7 +15,6 @@ #include <linux/vfio.h> #include "system/tcg.h" -#include "system/ramblock.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/vfio/vfio-container.h" @@ -74,49 +73,12 @@ void vfio_address_space_insert(VFIOAddressSpace *space, bcontainer->space = space; } -static bool vfio_container_can_dma_map_file(VFIOContainer *bcontainer, - MemoryRegion *mr, int *fd) -{ - VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer); - RAMBlock *rb = mr->ram_block; - - if (!vioc->dma_map_file || !rb) { - return false; - } - - *fd = qemu_ram_get_fd(rb); - if (*fd < 0) { - return false; - } - - /* - * We can use IOMMU DMA mapping (IOMMU_IOAS_MAP_FILE) for : - * - * 1) Guest RAM blocks explicitly configured as shared (MAP_SHARED) - * 2) RAM device sub-regions (MMIO BARs) - * - * Private RAM mappings (MAP_PRIVATE) are strictly excluded. Because - * they are subject to copy-on-write (COW) anomalies, their underlying - * PFNs can permanently diverge from the backing file - */ - return qemu_ram_is_shared(rb) || memory_region_is_ram_device(mr); -} - int vfio_container_dma_map(VFIOContainer *bcontainer, hwaddr iova, uint64_t size, void *vaddr, bool readonly, MemoryRegion *mr) { VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer); - int mfd; - if (vfio_container_can_dma_map_file(bcontainer, mr, &mfd)) { - RAMBlock *rb = mr->ram_block; - unsigned long start = vaddr - qemu_ram_get_host_addr(rb); - unsigned long offset = qemu_ram_get_fd_offset(rb); - - return vioc->dma_map_file(bcontainer, iova, size, mfd, start + offset, - readonly); - } g_assert(vioc->dma_map); return vioc->dma_map(bcontainer, iova, size, vaddr, readonly, mr); } diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index 68f2ae6f9f667bb05c20e452e8c5b43da6558098..6ff668d2597e07c6953cf0f1997514aec199642c 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -20,6 +20,7 @@ #include "trace.h" #include "qapi/error.h" #include "system/iommufd.h" +#include "system/ramblock.h" #include "hw/core/iommu.h" #include "hw/core/qdev.h" #include "hw/vfio/vfio-cpr.h" @@ -35,26 +36,50 @@ #define TYPE_HOST_IOMMU_DEVICE_IOMMUFD_VFIO \ TYPE_HOST_IOMMU_DEVICE_IOMMUFD "-vfio" +static bool iommufd_cdev_can_map_file_dma(MemoryRegion *mr, int *fd) +{ + RAMBlock *rb = mr ? mr->ram_block : NULL; + + if (!rb) { + return false; + } + + *fd = qemu_ram_get_fd(rb); + if (*fd < 0) { + return false; + } + + /* + * Use iommufd_backend_map_file_dma() (IOMMU_IOAS_MAP_FILE) for: + * 1) Guest RAM blocks explicitly configured as shared (MAP_SHARED) + * 2) RAM device sub-regions (MMIO BARs) + * + * Private RAM mappings (MAP_PRIVATE) are excluded: copy-on-write + * semantics can cause their underlying PFNs to permanently diverge + * from the backing file. + */ + return qemu_ram_is_shared(rb) || memory_region_is_ram_device(mr); +} + static int iommufd_cdev_map(const VFIOContainer *bcontainer, hwaddr iova, uint64_t size, void *vaddr, bool readonly, MemoryRegion *mr) { const VFIOIOMMUFDContainer *container = VFIO_IOMMU_IOMMUFD(bcontainer); + int fd; - return iommufd_backend_map_dma(container->be, - container->ioas_id, - iova, size, vaddr, readonly); -} + if (iommufd_cdev_can_map_file_dma(mr, &fd)) { + RAMBlock *rb = mr->ram_block; + unsigned long start = vaddr - qemu_ram_get_host_addr(rb); + unsigned long offset = qemu_ram_get_fd_offset(rb); -static int iommufd_cdev_map_file(const VFIOContainer *bcontainer, - hwaddr iova, uint64_t size, - int fd, unsigned long start, bool readonly) -{ - const VFIOIOMMUFDContainer *container = VFIO_IOMMU_IOMMUFD(bcontainer); + return iommufd_backend_map_file_dma(container->be, container->ioas_id, + iova, size, fd, + start + offset, readonly); + } - return iommufd_backend_map_file_dma(container->be, - container->ioas_id, - iova, size, fd, start, readonly); + return iommufd_backend_map_dma(container->be, container->ioas_id, + iova, size, vaddr, readonly); } static int iommufd_cdev_unmap(const VFIOContainer *bcontainer, @@ -929,7 +954,6 @@ static void vfio_iommu_iommufd_class_init(ObjectClass *klass, const void *data) VFIOIOMMUClass *vioc = VFIO_IOMMU_CLASS(klass); vioc->dma_map = iommufd_cdev_map; - vioc->dma_map_file = iommufd_cdev_map_file; vioc->dma_unmap = iommufd_cdev_unmap; vioc->attach_device = iommufd_cdev_attach; vioc->detach_device = iommufd_cdev_detach; -- 2.54.0
