vfio/iommufd: Merge .dma_map_file() into .dma_map()
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. Reviewed-by: Alex Williamson <alex@shazbot.org> Link: https://lore.kernel.org/qemu-devel/20260608055758.359002-1-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com>
Cédric Le Goater committed
Jun 8, 2026 at 07:57 UTC
877da3831355ee68e3476a6401bac30ae70097ee
3 files changed
+37
-66
hw/vfio/container.c
-38
@@ -15,7 +15,6 @@
15
#include <linux/vfio.h>
16
17
#include "system/tcg.h"
18
-#include "system/ramblock.h"
18
#include "qapi/error.h"
19
#include "qemu/error-report.h"
20
#include "hw/vfio/vfio-container.h"
@@ -74,49 +73,12 @@ void vfio_address_space_insert(VFIOAddressSpace *space,
73
bcontainer->space = space;
74
}
75
77
-static bool vfio_container_can_dma_map_file(VFIOContainer *bcontainer,
78
- MemoryRegion *mr, int *fd)
79
-{
80
- VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
81
- RAMBlock *rb = mr->ram_block;
82
-
83
- if (!vioc->dma_map_file || !rb) {
84
- return false;
85
- }
86
-
87
- *fd = qemu_ram_get_fd(rb);
88
- if (*fd < 0) {
89
- return false;
90
- }
91
-
92
- /*
93
- * We can use IOMMU DMA mapping (IOMMU_IOAS_MAP_FILE) for :
94
- *
95
- * 1) Guest RAM blocks explicitly configured as shared (MAP_SHARED)
96
- * 2) RAM device sub-regions (MMIO BARs)
97
- *
98
- * Private RAM mappings (MAP_PRIVATE) are strictly excluded. Because
99
- * they are subject to copy-on-write (COW) anomalies, their underlying
100
- * PFNs can permanently diverge from the backing file
101
- */
102
- return qemu_ram_is_shared(rb) || memory_region_is_ram_device(mr);
103
-}
104
-
76
int vfio_container_dma_map(VFIOContainer *bcontainer,
77
hwaddr iova, uint64_t size,
78
void *vaddr, bool readonly, MemoryRegion *mr)
79
{
80
VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
110
- int mfd;
81
112
- if (vfio_container_can_dma_map_file(bcontainer, mr, &mfd)) {
113
- RAMBlock *rb = mr->ram_block;
114
- unsigned long start = vaddr - qemu_ram_get_host_addr(rb);
115
- unsigned long offset = qemu_ram_get_fd_offset(rb);
116
-
117
- return vioc->dma_map_file(bcontainer, iova, size, mfd, start + offset,
118
- readonly);
119
- }
82
g_assert(vioc->dma_map);
83
return vioc->dma_map(bcontainer, iova, size, vaddr, readonly, mr);
84
}
hw/vfio/iommufd.c
+37
-13
@@ -20,6 +20,7 @@
20
#include "trace.h"
21
#include "qapi/error.h"
22
#include "system/iommufd.h"
23
+#include "system/ramblock.h"
24
#include "hw/core/iommu.h"
25
#include "hw/core/qdev.h"
26
#include "hw/vfio/vfio-cpr.h"
@@ -35,26 +36,50 @@
36
#define TYPE_HOST_IOMMU_DEVICE_IOMMUFD_VFIO \
37
TYPE_HOST_IOMMU_DEVICE_IOMMUFD "-vfio"
38
39
+static bool iommufd_cdev_can_map_file_dma(MemoryRegion *mr, int *fd)
40
+{
41
+ RAMBlock *rb = mr ? mr->ram_block : NULL;
42
+
43
+ if (!rb) {
44
+ return false;
45
+ }
46
+
47
+ *fd = qemu_ram_get_fd(rb);
48
+ if (*fd < 0) {
49
+ return false;
50
+ }
51
+
52
+ /*
53
+ * Use iommufd_backend_map_file_dma() (IOMMU_IOAS_MAP_FILE) for:
54
+ * 1) Guest RAM blocks explicitly configured as shared (MAP_SHARED)
55
+ * 2) RAM device sub-regions (MMIO BARs)
56
+ *
57
+ * Private RAM mappings (MAP_PRIVATE) are excluded: copy-on-write
58
+ * semantics can cause their underlying PFNs to permanently diverge
59
+ * from the backing file.
60
+ */
61
+ return qemu_ram_is_shared(rb) || memory_region_is_ram_device(mr);
62
+}
63
+
64
static int iommufd_cdev_map(const VFIOContainer *bcontainer, hwaddr iova,
65
uint64_t size, void *vaddr, bool readonly,
66
MemoryRegion *mr)
67
{
68
const VFIOIOMMUFDContainer *container = VFIO_IOMMU_IOMMUFD(bcontainer);
69
+ int fd;
70
44
- return iommufd_backend_map_dma(container->be,
45
- container->ioas_id,
46
- iova, size, vaddr, readonly);
47
-}
71
+ if (iommufd_cdev_can_map_file_dma(mr, &fd)) {
72
+ RAMBlock *rb = mr->ram_block;
73
+ unsigned long start = vaddr - qemu_ram_get_host_addr(rb);
74
+ unsigned long offset = qemu_ram_get_fd_offset(rb);
75
49
-static int iommufd_cdev_map_file(const VFIOContainer *bcontainer,
50
- hwaddr iova, uint64_t size,
51
- int fd, unsigned long start, bool readonly)
52
-{
53
- const VFIOIOMMUFDContainer *container = VFIO_IOMMU_IOMMUFD(bcontainer);
76
+ return iommufd_backend_map_file_dma(container->be, container->ioas_id,
77
+ iova, size, fd,
78
+ start + offset, readonly);
79
+ }
80
55
- return iommufd_backend_map_file_dma(container->be,
56
- container->ioas_id,
57
- iova, size, fd, start, readonly);
81
+ return iommufd_backend_map_dma(container->be, container->ioas_id,
82
+ iova, size, vaddr, readonly);
83
}
84
85
static int iommufd_cdev_unmap(const VFIOContainer *bcontainer,
@@ -929,7 +954,6 @@ static void vfio_iommu_iommufd_class_init(ObjectClass *klass, const void *data)
954
VFIOIOMMUClass *vioc = VFIO_IOMMU_CLASS(klass);
955
956
vioc->dma_map = iommufd_cdev_map;
932
- vioc->dma_map_file = iommufd_cdev_map_file;
957
vioc->dma_unmap = iommufd_cdev_unmap;
958
vioc->attach_device = iommufd_cdev_attach;
959
vioc->detach_device = iommufd_cdev_detach;
include/hw/vfio/vfio-container.h
-15
@@ -172,21 +172,6 @@ struct VFIOIOMMUClass {
172
int (*dma_map)(const VFIOContainer *bcontainer,
173
hwaddr iova, uint64_t size,
174
void *vaddr, bool readonly, MemoryRegion *mr);
175
- /**
176
- * @dma_map_file
177
- *
178
- * Map a file range for the container.
179
- *
180
- * @bcontainer: #VFIOContainer to use for map
181
- * @iova: start address to map
182
- * @size: size of the range to map
183
- * @fd: descriptor of the file to map
184
- * @start: starting file offset of the range to map
185
- * @readonly: map read only if true
186
- */
187
- int (*dma_map_file)(const VFIOContainer *bcontainer,
188
- hwaddr iova, uint64_t size,
189
- int fd, unsigned long start, bool readonly);
175
/**
176
* @dma_unmap
177
*