diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2024-10-25 13:35:13 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2024-10-25 13:35:13 +0100 |
| commit | 94be8fd6926cb20c1aa8dd361c6bc10b39b9a376 (patch) | |
| tree | 17bddae13bbbdce40753e6c309d2f906938c0ce4 /hw/vfio/helpers.c | |
| parent | e17e57e862faf6e1f372385c18dcf6d3fd31158e (diff) | |
| parent | 00b519c0bca0e933ed22e2e6f8bca6b23f41f950 (diff) | |
| download | focaccia-qemu-94be8fd6926cb20c1aa8dd361c6bc10b39b9a376.tar.gz focaccia-qemu-94be8fd6926cb20c1aa8dd361c6bc10b39b9a376.zip | |
Merge tag 'pull-vfio-20241024' of https://github.com/legoater/qemu into staging
vfio queue: * Fixed size reported in vfio_state_pending_exact() * Added support for PMD or PUD aligned mappings # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmcZ22wACgkQUaNDx8/7 # 7KHU5g/8Cr1487IJQb5cbpLu2Nviu3wjzhbCFFdbl99uLifdc0GK1P6fqDNQ7BVx # 2vpZgJRXLTxlUSTpreFw4z6TH7/C4HoNiluQV4l0vxqG/Y9q68SJBpT9WENwXUyY # +2laDmGQbUjDznxIFlmCgZZAssCIJNp0esNE9hvwkQCarZx9m+QQSSkeVHVWNFqX # +zTd4v076Q9hi53+4e7FlqFKaFoa54IcZe3gz+GjY/IXMqCDNFw9e9xJxML+zSg3 # HZ4/YMQj+EsKX2gm460EYBmt13kd0wdtFzA1MNc7XcSlBlLk/WmezpEzHZRubiLs # mbUZ68/cweJmrO0WatycWg9JwQ2q9FlKH1Acgun4Fcf8Zov5ovHuYAsWYbdGDbN1 # E7pY/XlUf6b7Vk+yAGTnKKRi6OguTEmVyRRFy/4V8TwvZNycbeOMebKilGQUGfKj # iLWuzF6NilT4ZGo7sWnlLZWcmrxN57wJh77GlmcqiqguskB8WGdh/SZSVCkkzr3y # PN3FGSTseNaxalcjECEFnfE8+bUShLei+I6fppTfqLBaLHJ72lRel0Cg07FS8oM4 # 3ev7etH7jFT5xET00DBamDXacgNtLqFqO6XIK3bFTkLmP0FFQi9u+bvy04IyTVCC # gd9Zg2vhxp0mjuwtelB+i7yD3pmA2LWFkEzoShpkH/h38CnpoyQ= # =+69I # -----END PGP SIGNATURE----- # gpg: Signature made Thu 24 Oct 2024 06:30:20 BST # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full] # gpg: aka "Cédric Le Goater <clg@kaod.org>" [full] # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-vfio-20241024' of https://github.com/legoater/qemu: vfio/helpers: Align mmaps vfio/helpers: Refactor vfio_region_mmap() error handling vfio/migration: Change trace formats from hex to decimal vfio/migration: Report only stop-copy size in vfio_state_pending_exact() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/vfio/helpers.c')
| -rw-r--r-- | hw/vfio/helpers.c | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index ea15c79db0..913796f437 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -27,6 +27,7 @@ #include "trace.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/units.h" #include "monitor/monitor.h" /* @@ -395,7 +396,7 @@ static void vfio_subregion_unmap(VFIORegion *region, int index) int vfio_region_mmap(VFIORegion *region) { - int i, prot = 0; + int i, ret, prot = 0; char *name; if (!region->mem) { @@ -406,27 +407,40 @@ int vfio_region_mmap(VFIORegion *region) prot |= region->flags & VFIO_REGION_INFO_FLAG_WRITE ? PROT_WRITE : 0; for (i = 0; i < region->nr_mmaps; i++) { - region->mmaps[i].mmap = mmap(NULL, region->mmaps[i].size, prot, - MAP_SHARED, region->vbasedev->fd, - region->fd_offset + - region->mmaps[i].offset); - if (region->mmaps[i].mmap == MAP_FAILED) { - int ret = -errno; + size_t align = MIN(1ULL << ctz64(region->mmaps[i].size), 1 * GiB); + void *map_base, *map_align; - trace_vfio_region_mmap_fault(memory_region_name(region->mem), i, - region->fd_offset + - region->mmaps[i].offset, - region->fd_offset + - region->mmaps[i].offset + - region->mmaps[i].size - 1, ret); - - region->mmaps[i].mmap = NULL; + /* + * Align the mmap for more efficient mapping in the kernel. Ideally + * we'd know the PMD and PUD mapping sizes to use as discrete alignment + * intervals, but we don't. As of Linux v6.12, the largest PUD size + * supporting huge pfnmap is 1GiB (ARCH_SUPPORTS_PUD_PFNMAP is only set + * on x86_64). Align by power-of-two size, capped at 1GiB. + * + * NB. qemu_memalign() and friends actually allocate memory, whereas + * the region size here can exceed host memory, therefore we manually + * create an oversized anonymous mapping and clean it up for alignment. + */ + map_base = mmap(0, region->mmaps[i].size + align, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (map_base == MAP_FAILED) { + ret = -errno; + goto no_mmap; + } - for (i--; i >= 0; i--) { - vfio_subregion_unmap(region, i); - } + map_align = (void *)ROUND_UP((uintptr_t)map_base, (uintptr_t)align); + munmap(map_base, map_align - map_base); + munmap(map_align + region->mmaps[i].size, + align - (map_align - map_base)); - return ret; + region->mmaps[i].mmap = mmap(map_align, region->mmaps[i].size, prot, + MAP_SHARED | MAP_FIXED, + region->vbasedev->fd, + region->fd_offset + + region->mmaps[i].offset); + if (region->mmaps[i].mmap == MAP_FAILED) { + ret = -errno; + goto no_mmap; } name = g_strdup_printf("%s mmaps[%d]", @@ -446,6 +460,20 @@ int vfio_region_mmap(VFIORegion *region) } return 0; + +no_mmap: + trace_vfio_region_mmap_fault(memory_region_name(region->mem), i, + region->fd_offset + region->mmaps[i].offset, + region->fd_offset + region->mmaps[i].offset + + region->mmaps[i].size - 1, ret); + + region->mmaps[i].mmap = NULL; + + for (i--; i >= 0; i--) { + vfio_subregion_unmap(region, i); + } + + return ret; } void vfio_region_unmap(VFIORegion *region) |