[PATCH] vfio/iommufd: Merge .dma_map_file() into .dma_map()

Cédric Le Goater posted 1 patch 18 hours ago
Failed in applying to current master (apply log)
include/hw/vfio/vfio-container.h | 15 ----------
hw/vfio/container.c              | 38 ------------------------
hw/vfio/iommufd.c                | 50 +++++++++++++++++++++++---------
3 files changed, 37 insertions(+), 66 deletions(-)
[PATCH] vfio/iommufd: Merge .dma_map_file() into .dma_map()
Posted by Cédric Le Goater 18 hours ago
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 <clg@redhat.com>
---
 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