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

Cédric Le Goater posted 1 patch 1 month, 1 week 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 1 month, 1 week 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


Re: [PATCH] vfio/iommufd: Merge .dma_map_file() into .dma_map()
Posted by Cédric Le Goater 3 weeks ago
On 6/8/26 07:57, Cédric Le Goater wrote:
> 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;


Applied to

     https://github.com/legoater/qemu vfio-next

Thanks,

C.


Re: [PATCH] vfio/iommufd: Merge .dma_map_file() into .dma_map()
Posted by Alex Williamson 1 month ago
On Mon,  8 Jun 2026 07:57:58 +0200
Cédric Le Goater <clg@redhat.com> wrote:

> 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(-)

Reviewed-by: Alex Williamson <alex@shazbot.org>