2 * DMA memory preregistration
5 * Alexey Kardashevskiy <aik@ozlabs.ru>
7 * This work is licensed under the terms of the GNU GPL, version 2. See
8 * the COPYING file in the top-level directory.
11 #include "qemu/osdep.h"
13 #include <sys/ioctl.h>
14 #include <linux/vfio.h>
16 #include "hw/vfio/vfio-common.h"
18 #include "exec/ram_addr.h"
19 #include "qemu/error-report.h"
20 #include "qapi/error.h"
23 static bool vfio_prereg_listener_skipped_section(MemoryRegionSection
*section
)
25 if (memory_region_is_iommu(section
->mr
)) {
26 hw_error("Cannot possibly preregister IOMMU memory");
29 return !memory_region_is_ram(section
->mr
) ||
30 memory_region_is_ram_device(section
->mr
);
33 static void *vfio_prereg_gpa_to_vaddr(MemoryRegionSection
*section
, hwaddr gpa
)
35 return memory_region_get_ram_ptr(section
->mr
) +
36 section
->offset_within_region
+
37 (gpa
- section
->offset_within_address_space
);
40 static void vfio_prereg_listener_region_add(MemoryListener
*listener
,
41 MemoryRegionSection
*section
)
43 VFIOContainer
*container
= container_of(listener
, VFIOContainer
,
45 const hwaddr gpa
= section
->offset_within_address_space
;
48 hwaddr page_mask
= qemu_real_host_page_mask
;
49 struct vfio_iommu_spapr_register_memory reg
= {
54 if (vfio_prereg_listener_skipped_section(section
)) {
55 trace_vfio_prereg_listener_region_add_skip(
56 section
->offset_within_address_space
,
57 section
->offset_within_address_space
+
58 int128_get64(int128_sub(section
->size
, int128_one())));
62 if (unlikely((section
->offset_within_address_space
& ~page_mask
) ||
63 (section
->offset_within_region
& ~page_mask
) ||
64 (int128_get64(section
->size
) & ~page_mask
))) {
65 error_report("%s received unaligned region", __func__
);
69 end
= section
->offset_within_address_space
+ int128_get64(section
->size
);
74 memory_region_ref(section
->mr
);
76 reg
.vaddr
= (uintptr_t) vfio_prereg_gpa_to_vaddr(section
, gpa
);
79 ret
= ioctl(container
->fd
, VFIO_IOMMU_SPAPR_REGISTER_MEMORY
, ®
);
80 trace_vfio_prereg_register(reg
.vaddr
, reg
.size
, ret
? -errno
: 0);
83 * On the initfn path, store the first error in the container so we
84 * can gracefully fail. Runtime, there's not much we can do other
85 * than throw a hardware error.
87 if (!container
->initialized
) {
88 if (!container
->error
) {
89 error_setg_errno(&container
->error
, -ret
,
90 "Memory registering failed");
93 hw_error("vfio: Memory registering failed, unable to continue");
98 static void vfio_prereg_listener_region_del(MemoryListener
*listener
,
99 MemoryRegionSection
*section
)
101 VFIOContainer
*container
= container_of(listener
, VFIOContainer
,
103 const hwaddr gpa
= section
->offset_within_address_space
;
106 hwaddr page_mask
= qemu_real_host_page_mask
;
107 struct vfio_iommu_spapr_register_memory reg
= {
108 .argsz
= sizeof(reg
),
112 if (vfio_prereg_listener_skipped_section(section
)) {
113 trace_vfio_prereg_listener_region_del_skip(
114 section
->offset_within_address_space
,
115 section
->offset_within_address_space
+
116 int128_get64(int128_sub(section
->size
, int128_one())));
120 if (unlikely((section
->offset_within_address_space
& ~page_mask
) ||
121 (section
->offset_within_region
& ~page_mask
) ||
122 (int128_get64(section
->size
) & ~page_mask
))) {
123 error_report("%s received unaligned region", __func__
);
127 end
= section
->offset_within_address_space
+ int128_get64(section
->size
);
132 reg
.vaddr
= (uintptr_t) vfio_prereg_gpa_to_vaddr(section
, gpa
);
133 reg
.size
= end
- gpa
;
135 ret
= ioctl(container
->fd
, VFIO_IOMMU_SPAPR_UNREGISTER_MEMORY
, ®
);
136 trace_vfio_prereg_unregister(reg
.vaddr
, reg
.size
, ret
? -errno
: 0);
139 const MemoryListener vfio_prereg_listener
= {
140 .region_add
= vfio_prereg_listener_region_add
,
141 .region_del
= vfio_prereg_listener_region_del
,
144 int vfio_spapr_create_window(VFIOContainer
*container
,
145 MemoryRegionSection
*section
,
149 IOMMUMemoryRegion
*iommu_mr
= IOMMU_MEMORY_REGION(section
->mr
);
150 uint64_t pagesize
= memory_region_iommu_get_min_page_size(iommu_mr
);
151 unsigned entries
, bits_total
, bits_per_level
, max_levels
;
152 struct vfio_iommu_spapr_tce_create create
= { .argsz
= sizeof(create
) };
153 long rampagesize
= qemu_minrampagesize();
156 * The host might not support the guest supported IOMMU page size,
157 * so we will use smaller physical IOMMU pages to back them.
159 if (pagesize
> rampagesize
) {
160 pagesize
= rampagesize
;
162 pagesize
= 1ULL << (63 - clz64(container
->pgsizes
&
163 (pagesize
| (pagesize
- 1))));
165 error_report("Host doesn't support page size 0x%"PRIx64
166 ", the supported mask is 0x%lx",
167 memory_region_iommu_get_min_page_size(iommu_mr
),
173 * FIXME: For VFIO iommu types which have KVM acceleration to
174 * avoid bouncing all map/unmaps through qemu this way, this
175 * would be the right place to wire that up (tell the KVM
176 * device emulation the VFIO iommu handles to use).
178 create
.window_size
= int128_get64(section
->size
);
179 create
.page_shift
= ctz64(pagesize
);
181 * SPAPR host supports multilevel TCE tables. We try to guess optimal
182 * levels number and if this fails (for example due to the host memory
183 * fragmentation), we increase levels. The DMA address structure is:
184 * rrrrrrrr rxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx iiiiiiii
186 * r = reserved (bits >= 55 are reserved in the existing hardware)
187 * i = IOMMU page offset (64K in this example)
188 * x = bits to index a TCE which can be split to equal chunks to index
190 * The aim is to split "x" to smaller possible number of levels.
192 entries
= create
.window_size
>> create
.page_shift
;
193 /* bits_total is number of "x" needed */
194 bits_total
= ctz64(entries
* sizeof(uint64_t));
196 * bits_per_level is a safe guess of how much we can allocate per level:
197 * 8 is the current minimum for CONFIG_FORCE_MAX_ZONEORDER and MAX_ORDER
198 * is usually bigger than that.
199 * Below we look at getpagesize() as TCEs are allocated from system pages.
201 bits_per_level
= ctz64(getpagesize()) + 8;
202 create
.levels
= bits_total
/ bits_per_level
;
203 if (bits_total
% bits_per_level
) {
206 max_levels
= (64 - create
.page_shift
) / ctz64(getpagesize());
207 for ( ; create
.levels
<= max_levels
; ++create
.levels
) {
208 ret
= ioctl(container
->fd
, VFIO_IOMMU_SPAPR_TCE_CREATE
, &create
);
214 error_report("Failed to create a window, ret = %d (%m)", ret
);
218 if (create
.start_addr
!= section
->offset_within_address_space
) {
219 vfio_spapr_remove_window(container
, create
.start_addr
);
221 error_report("Host doesn't support DMA window at %"HWADDR_PRIx
", must be %"PRIx64
,
222 section
->offset_within_address_space
,
223 (uint64_t)create
.start_addr
);
226 trace_vfio_spapr_create_window(create
.page_shift
,
235 int vfio_spapr_remove_window(VFIOContainer
*container
,
236 hwaddr offset_within_address_space
)
238 struct vfio_iommu_spapr_tce_remove remove
= {
239 .argsz
= sizeof(remove
),
240 .start_addr
= offset_within_address_space
,
244 ret
= ioctl(container
->fd
, VFIO_IOMMU_SPAPR_TCE_REMOVE
, &remove
);
246 error_report("Failed to remove window at %"PRIx64
,
247 (uint64_t)remove
.start_addr
);
251 trace_vfio_spapr_remove_window(offset_within_address_space
);