* [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix
@ 2026-03-17 17:57 Lucas Amaral
2026-03-17 17:57 ` [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs Lucas Amaral
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Lucas Amaral @ 2026-03-17 17:57 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, agraf, peter.maydell, mohamed, Lucas Amaral
Fix a bug in the MAP_FIXED blob mapping path (introduced by 4eb0aace)
where non-host-page-aligned offsets cause mmap(MAP_FIXED) to fail with
EINVAL. This affects any host where the page size exceeds the guest's
(ARM64 with 16KB/64KB pages, macOS ARM64).
This series introduces:
1. MAP_FIXED alignment validation in virtio-gpu: check that both
offset and blob size are aligned to the host page size before
calling virgl_renderer_resource_map_fixed(). When not aligned,
fall through to the subregion method (which works at any
alignment).
2. A map granule abstraction (hvf_set/get_map_granule) replacing
hardcoded qemu_real_host_page_size() calls in HVF memory mapping.
Non-aligned regions return early instead of proceeding with
add=false (which attempted an unnecessary unmap).
An 'ipa-granule' property (auto, 4k, 16k) on the HVF accelerator
object allows opt-in configuration:
-accel hvf,ipa-granule=4k
The property follows the kvm_arch_accel_class_init() pattern:
ARM registers the property in hvf_arch_accel_class_init(), x86
provides an empty stub.
3. macOS 26 IPA granule support via hv_vm_config_set_ipa_granule(),
reading the ipa-granule property to select HV_IPA_GRANULE_4KB or
HV_IPA_GRANULE_16KB. Falls back with a warning on macOS < 26.
Dependencies: none.
Changes v3 -> v4:
- Rebased onto current master (no code changes)
- Fix Signed-off-by email in patches 2/3 and 3/3
- Resent as new top-level thread per Alex Bennée's feedback
Changes v2 -> v3:
- Rebased on current master
- Add MAP_FIXED alignment validation (new patch 1)
- Move #ifdef __aarch64__ property code into hvf_arch_accel_class_init
following kvm_arch_accel_class_init() pattern (x86 empty stub)
- Use MAC_OS_VERSION_26_0 named constant
- Remove Venus blob mapping warning
Changes v1 -> v2 (Mohamed Mosaad review):
- Replace hardcoded 4KB with configurable ipa-granule property
(auto, 4k, 16k) on the HVF accelerator object.
- 'auto' defaults to host page size; explicit values opt in.
- Add fallback warning when macOS < 26 can't honor the request.
- Add Venus blob mapping safety warning.
- Use KiB constants instead of magic numbers.
Lucas Amaral (3):
virtio-gpu: validate host page alignment for MAP_FIXED blobs
accel/hvf: introduce map granule abstraction and IPA property
target/arm/hvf: configure IPA granule on macOS 26
accel/hvf/hvf-all.c | 30 +++++++++++++--
hw/display/virtio-gpu-virgl.c | 45 +++++++++++++---------
include/system/hvf.h | 15 ++++++++
include/system/hvf_int.h | 2 +
target/arm/hvf/hvf.c | 72 +++++++++++++++++++++++++++++++++++
target/i386/hvf/hvf.c | 4 ++
6 files changed, 147 insertions(+), 21 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs 2026-03-17 17:57 [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix Lucas Amaral @ 2026-03-17 17:57 ` Lucas Amaral 2026-04-23 18:00 ` Alex Bennée 2026-03-17 17:57 ` [PATCH v4 2/3] accel/hvf: introduce map granule abstraction and IPA property Lucas Amaral ` (2 subsequent siblings) 3 siblings, 1 reply; 17+ messages in thread From: Lucas Amaral @ 2026-03-17 17:57 UTC (permalink / raw) To: qemu-devel; +Cc: qemu-arm, agraf, peter.maydell, mohamed, Lucas Amaral Commit 4eb0aace ("virtio-gpu: Support mapping hostmem blobs with map_fixed") uses mmap(MAP_FIXED) to map blob resources into a pre-allocated hostmem region. Both the offset and size passed to mmap must be aligned to the host page size, but the code does not validate this. On hosts where qemu_real_host_page_size() exceeds the guest's page size (e.g. ARM64 with 16KB or 64KB pages, macOS ARM64), the guest may provide blob offsets aligned to its own page size (4KB) but not to the host's. This causes mmap(MAP_FIXED) to fail with EINVAL, and the subsequent unmap (which also uses mmap MAP_FIXED) fails the same way, producing: virtio_gpu_virgl_unmap_resource_blob: failed to unmap(fixed) virgl resource: Invalid argument Add an alignment check before attempting MAP_FIXED. When the offset or blob size is not host-page-aligned, skip the MAP_FIXED path and fall through to the existing subregion method, which handles any alignment. Fixes: 4eb0aace ("virtio-gpu: Support mapping hostmem blobs with map_fixed") Signed-off-by: Lucas Amaral <lucaaamaral@gmail.com> --- hw/display/virtio-gpu-virgl.c | 45 +++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c index b7a2d160..f6583b48 100644 --- a/hw/display/virtio-gpu-virgl.c +++ b/hw/display/virtio-gpu-virgl.c @@ -185,25 +185,34 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g, return -EBUSY; } - ret = virgl_renderer_resource_map_fixed(res->base.resource_id, - gl->hostmem_mmap + offset); - switch (ret) { - case 0: - res->map_fixed = gl->hostmem_mmap + offset; - return 0; - - case -EOPNOTSUPP: - /* - * MAP_FIXED is unsupported by this resource. - * Mapping falls back to a blob subregion method in that case. - */ - break; + /* + * MAP_FIXED requires host-page-aligned offset and size. Hosts with + * page sizes larger than the guest's (e.g. 16KB on ARM64) may receive + * non-aligned blob offsets. Fall through to the subregion method when + * alignment requirements are not met. + */ + if (QEMU_IS_ALIGNED(offset, qemu_real_host_page_size()) && + QEMU_IS_ALIGNED(res->base.blob_size, qemu_real_host_page_size())) { + ret = virgl_renderer_resource_map_fixed(res->base.resource_id, + gl->hostmem_mmap + offset); + switch (ret) { + case 0: + res->map_fixed = gl->hostmem_mmap + offset; + return 0; + + case -EOPNOTSUPP: + /* + * MAP_FIXED is unsupported by this resource. + * Mapping falls back to a blob subregion method in that case. + */ + break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: failed to map(fixed) virgl resource: %s\n", - __func__, strerror(-ret)); - return ret; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: failed to map(fixed) virgl resource: %s\n", + __func__, strerror(-ret)); + return ret; + } } #endif -- 2.52.0 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs 2026-03-17 17:57 ` [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs Lucas Amaral @ 2026-04-23 18:00 ` Alex Bennée 2026-04-23 23:44 ` Lucas Amaral 0 siblings, 1 reply; 17+ messages in thread From: Alex Bennée @ 2026-04-23 18:00 UTC (permalink / raw) To: Lucas Amaral; +Cc: qemu-devel, qemu-arm, agraf, peter.maydell, mohamed Lucas Amaral <lucaaamaral@gmail.com> writes: > Commit 4eb0aace ("virtio-gpu: Support mapping hostmem blobs with > map_fixed") uses mmap(MAP_FIXED) to map blob resources into a > pre-allocated hostmem region. Both the offset and size passed to > mmap must be aligned to the host page size, but the code does not > validate this. > > On hosts where qemu_real_host_page_size() exceeds the guest's page > size (e.g. ARM64 with 16KB or 64KB pages, macOS ARM64), the guest > may provide blob offsets aligned to its own page size (4KB) but not > to the host's. What was your test case? Is it possible to publish some images for a functional test? > This causes mmap(MAP_FIXED) to fail with EINVAL, > and the subsequent unmap (which also uses mmap MAP_FIXED) fails the > same way, producing: > > virtio_gpu_virgl_unmap_resource_blob: failed to unmap(fixed) > virgl resource: Invalid argument > > Add an alignment check before attempting MAP_FIXED. When the offset > or blob size is not host-page-aligned, skip the MAP_FIXED path and > fall through to the existing subregion method, which handles any > alignment. > > Fixes: 4eb0aace ("virtio-gpu: Support mapping hostmem blobs with map_fixed") > Signed-off-by: Lucas Amaral <lucaaamaral@gmail.com> > --- > hw/display/virtio-gpu-virgl.c | 45 +++++++++++++++++++++-------------- > 1 file changed, 27 insertions(+), 18 deletions(-) > > diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c > index b7a2d160..f6583b48 100644 > --- a/hw/display/virtio-gpu-virgl.c > +++ b/hw/display/virtio-gpu-virgl.c > @@ -185,25 +185,34 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g, > return -EBUSY; > } > > - ret = virgl_renderer_resource_map_fixed(res->base.resource_id, > - gl->hostmem_mmap + offset); > - switch (ret) { > - case 0: > - res->map_fixed = gl->hostmem_mmap + offset; > - return 0; > - > - case -EOPNOTSUPP: > - /* > - * MAP_FIXED is unsupported by this resource. > - * Mapping falls back to a blob subregion method in that case. > - */ > - break; > + /* > + * MAP_FIXED requires host-page-aligned offset and size. Hosts with > + * page sizes larger than the guest's (e.g. 16KB on ARM64) may receive > + * non-aligned blob offsets. Fall through to the subregion method when > + * alignment requirements are not met. > + */ > + if (QEMU_IS_ALIGNED(offset, qemu_real_host_page_size()) && > + QEMU_IS_ALIGNED(res->base.blob_size, qemu_real_host_page_size())) { > + ret = virgl_renderer_resource_map_fixed(res->base.resource_id, > + gl->hostmem_mmap + offset); > + switch (ret) { > + case 0: > + res->map_fixed = gl->hostmem_mmap + offset; > + return 0; > + > + case -EOPNOTSUPP: > + /* > + * MAP_FIXED is unsupported by this resource. > + * Mapping falls back to a blob subregion method in that case. > + */ > + break; > > - default: > - qemu_log_mask(LOG_GUEST_ERROR, > - "%s: failed to map(fixed) virgl resource: %s\n", > - __func__, strerror(-ret)); > - return ret; > + default: > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: failed to map(fixed) virgl resource: %s\n", > + __func__, strerror(-ret)); > + return ret; > + } > } > #endif -- Alex Bennée Virtualisation Tech Lead @ Linaro ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs 2026-04-23 18:00 ` Alex Bennée @ 2026-04-23 23:44 ` Lucas Amaral 2026-04-24 10:09 ` Alex Bennée 0 siblings, 1 reply; 17+ messages in thread From: Lucas Amaral @ 2026-04-23 23:44 UTC (permalink / raw) To: Alex Bennée Cc: Lucas Amaral, qemu-devel, qemu-arm, peter.maydell, agraf, mohamed Hi Alex, Thanks for looking at this. > What was your test case? Is it possible to publish some images for a > functional test? The test case is running a Linux VM with virtio-gpu Venus (Vulkan passthrough) on an Apple Silicon Mac: - Host: macOS ARM64 with 16KB pages - Guest: Linux ARM64 with 4KB pages - GPU: virtio-gpu-gl with Venus/virglrenderer + MoltenVK When the guest allocates a blob resource with a 4KB-aligned size, mmap(MAP_FIXED) fails with EINVAL because the size isn't aligned to the host's 16KB page boundary. Without this patch the blob resource is silently unusable — the guest sees no GPU output. Reproducing it requires the full macOS Venus stack, which includes patches across multiple projects: QEMU (this series + two others on the list): - Stack A: ISV=0 data abort emulation (v6, R-b by Mohamed) https://patchew.org/QEMU/20260409220614.65558-1-lucaaamaral@gmail.com/ - Stack B: this series (hvf map granule + MAP_FIXED alignment) - Stack C: Venus without OpenGL (v5) https://patchew.org/QEMU/20260317182049.33848-1-lucaaamaral@gmail.com/ virglrenderer (GitLab MRs): - MR !1600: macOS build support (merged) - MR !1601: posix_spawn worker for macOS (merged) - MR !1602: Metal shared memory (R-b by Yiwei Zhang, under review) https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1602 - MR !1603: SOCK_CLOEXEC/MSG_CMSG_CLOEXEC optional (merged) - MR !1607: server preparations for macOS process model (merged) - MR !1608: Metal vulkan header roll (merged) I don't think a functional test is practical for CI since it requires macOS + HVF + MoltenVK + a guest image, but I'm open to suggestions. Thanks, Lucas ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs 2026-04-23 23:44 ` Lucas Amaral @ 2026-04-24 10:09 ` Alex Bennée 2026-04-24 21:37 ` Lucas Amaral 0 siblings, 1 reply; 17+ messages in thread From: Alex Bennée @ 2026-04-24 10:09 UTC (permalink / raw) To: Lucas Amaral; +Cc: qemu-devel, qemu-arm, peter.maydell, agraf, mohamed Lucas Amaral <lucaaamaral@gmail.com> writes: > Hi Alex, > > Thanks for looking at this. > >> What was your test case? Is it possible to publish some images for a >> functional test? > > The test case is running a Linux VM with virtio-gpu Venus (Vulkan > passthrough) on an Apple Silicon Mac: > > - Host: macOS ARM64 with 16KB pages > - Guest: Linux ARM64 with 4KB pages Well we at least images for the Linux side which we can use. See tests/functional/aarch64/test_virt_gpu.py > - GPU: virtio-gpu-gl with Venus/virglrenderer + MoltenVK > > When the guest allocates a blob resource with a 4KB-aligned size, > mmap(MAP_FIXED) fails with EINVAL because the size isn't aligned to > the host's 16KB page boundary. Without this patch the blob resource > is silently unusable — the guest sees no GPU output. I wonder if TCG guests will also fail? > > Reproducing it requires the full macOS Venus stack, which includes > patches across multiple projects: > > QEMU (this series + two others on the list): > - Stack A: ISV=0 data abort emulation (v6, R-b by Mohamed) > https://patchew.org/QEMU/20260409220614.65558-1-lucaaamaral@gmail.com/ > - Stack B: this series (hvf map granule + MAP_FIXED alignment) > - Stack C: Venus without OpenGL (v5) > https://patchew.org/QEMU/20260317182049.33848-1-lucaaamaral@gmail.com/ A lot of moving parts, do you have a rolled up branch I can test against? > virglrenderer (GitLab MRs): > - MR !1600: macOS build support (merged) > - MR !1601: posix_spawn worker for macOS (merged) > - MR !1602: Metal shared memory (R-b by Yiwei Zhang, under review) > https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1602 > - MR !1603: SOCK_CLOEXEC/MSG_CMSG_CLOEXEC optional (merged) > - MR !1607: server preparations for macOS process model (merged) > - MR !1608: Metal vulkan header roll (merged) Any rolled up branch for this set as well? > > I don't think a functional test is practical for CI since it requires > macOS + HVF + MoltenVK + a guest image, but I'm open to suggestions. This is a bit of a challenge - we will be loosing CirrusCI soon which has our only real MacOS build test. Either we get someone willing to host a custom runner or we need to find another CI runner that we can plug MacOS tests into. > > Thanks, > Lucas -- Alex Bennée Virtualisation Tech Lead @ Linaro ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs 2026-04-24 10:09 ` Alex Bennée @ 2026-04-24 21:37 ` Lucas Amaral 0 siblings, 0 replies; 17+ messages in thread From: Lucas Amaral @ 2026-04-24 21:37 UTC (permalink / raw) To: Alex Bennée Cc: qemu-devel, qemu-arm, Peter Maydell, Mohamed Mediouni, Philippe Mathieu-Daudé, Alexander Graf On 2026-04-24, Alex Bennée wrote: > Well we at least images for the Linux side which we can use. See > tests/functional/aarch64/test_virt_gpu.py Good pointer — that infrastructure should work. My local reproduction is even simpler: a plain Ubuntu 24.04 ARM64 image, unmodified, with stock Mesa. The failure surfaces immediately on: sudo vulkaninfo --summary sudo run_wayland timeout 120 vkmark Without patch 1/3, virgl_renderer_resource_map_fixed() returns EINVAL on the first 4KB-aligned blob and the guest renderer falls over. > I wonder if TCG guests will also fail? Yes — the MAP_FIXED requirement is a host kernel mmap() constraint, not an accelerator one. The patch 1/3 guard sits in the accelerator-agnostic path and protects all configurations, including TCG. > A lot of moving parts, do you have a rolled up branch I can test > against? > Any rolled up branch for this set as well? Easier than a rolled-up branch — the three QEMU series apply cleanly on current master in any order: Stack A (ISV=0 emulation): https://patchew.org/QEMU/20260409220614.65558-1-lucaaamaral@gmail.com/ Stack B (this series): https://patchew.org/QEMU/20260424000544.9617-1-lucaaamaral@gmail.com/ Stack C (Venus without OpenGL): https://patchew.org/QEMU/20260317182049.33848-1-lucaaamaral@gmail.com/ Renderer side just needs current virglrenderer main — the last macOS Metal/Vulkan MR landed yesterday. > This is a bit of a challenge - we will be loosing CirrusCI soon > which has our only real MacOS build test. Either we get someone > willing to host a custom runner or we need to find another CI > runner that we can plug MacOS tests into. Acknowledged — separate infrastructure problem, but I'm happy to share my macOS test scripts/workflow if useful, and can ack-test macOS-specific patches locally on Apple Silicon when asked. Thanks, Lucas ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v4 2/3] accel/hvf: introduce map granule abstraction and IPA property 2026-03-17 17:57 [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix Lucas Amaral 2026-03-17 17:57 ` [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs Lucas Amaral @ 2026-03-17 17:57 ` Lucas Amaral 2026-04-23 18:05 ` Alex Bennée 2026-03-17 17:57 ` [PATCH v4 3/3] target/arm/hvf: configure IPA granule on macOS 26 Lucas Amaral 2026-04-09 17:52 ` [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix Lucas Amaral 3 siblings, 1 reply; 17+ messages in thread From: Lucas Amaral @ 2026-03-17 17:57 UTC (permalink / raw) To: qemu-devel; +Cc: qemu-arm, agraf, peter.maydell, mohamed, Lucas Amaral Add a map granule abstraction that decouples HVF memory mapping alignment from the host page size. On ARM64, Apple Silicon supports stage-2 translation with 4KB page granules regardless of the host OS page size (16KB on macOS). This allows running guests with 4KB pages without interior mapping failures. Introduce hvf_set_map_granule()/hvf_get_map_granule() in hvf-all.c to replace hard-coded qemu_real_host_page_size() references in do_hv_vm_protect() and hvf_set_phys_mem(). When the granule is not explicitly configured, fall back to host page size to preserve the previous behaviour. Add an "ipa-granule" accelerator property (auto, 4k, 16k) following the established kvm_arch_accel_class_init() pattern: ARM registers the property in hvf_arch_accel_class_init(), x86 provides an empty stub. This avoids #ifdef __aarch64__ in common code while keeping a single hvf-all.c shared by both targets. Fix hvf_set_phys_mem() to return early for non-aligned regions instead of clearing the add flag, which previously fell through to an incorrect unmap of a region that was never mapped. Signed-off-by: Lucas Amaral <lucaaamaral@gmail.com> --- accel/hvf/hvf-all.c | 30 +++++++++++++++++++++++++++--- include/system/hvf.h | 15 +++++++++++++++ include/system/hvf_int.h | 2 ++ target/arm/hvf/hvf.c | 40 ++++++++++++++++++++++++++++++++++++++++ target/i386/hvf/hvf.c | 4 ++++ 5 files changed, 88 insertions(+), 3 deletions(-) diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c index 5f357c6d..d745fefd 100644 --- a/accel/hvf/hvf-all.c +++ b/accel/hvf/hvf-all.c @@ -10,6 +10,8 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" +#include "qemu/units.h" +#include "qapi/error.h" #include "accel/accel-ops.h" #include "exec/cpu-common.h" #include "system/address-spaces.h" @@ -22,6 +24,21 @@ bool hvf_allowed; +static uint64_t hvf_map_granule; + +void hvf_set_map_granule(uint64_t size) +{ + hvf_map_granule = size; +} + +uint64_t hvf_get_map_granule(void) +{ + if (!hvf_map_granule) { + return qemu_real_host_page_size(); + } + return hvf_map_granule; +} + const char *hvf_return_string(hv_return_t ret) { switch (ret) { @@ -53,7 +70,7 @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, static void do_hv_vm_protect(hwaddr start, size_t size, hv_memory_flags_t flags) { - intptr_t page_mask = qemu_real_host_page_mask(); + intptr_t page_mask = -(intptr_t)hvf_get_map_granule(); hv_return_t ret; trace_hvf_vm_protect(start, size, flags, @@ -83,7 +100,7 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add) MemoryRegion *area = section->mr; bool writable = !area->readonly && !area->rom_device; hv_memory_flags_t flags; - uint64_t page_size = qemu_real_host_page_size(); + uint64_t page_size = hvf_get_map_granule(); uint64_t gpa = section->offset_within_address_space; uint64_t size = int128_get64(section->size); hv_return_t ret; @@ -104,7 +121,7 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add) if (!QEMU_IS_ALIGNED(size, page_size) || !QEMU_IS_ALIGNED(gpa, page_size)) { /* Not page aligned, so we can not map as RAM */ - add = false; + return; } if (!add) { @@ -186,6 +203,11 @@ static int hvf_accel_init(AccelState *as, MachineState *ms) int pa_range = 36; MachineClass *mc = MACHINE_GET_CLASS(ms); + /* Resolve ipa-granule=auto → host page size */ + if (!s->ipa_granule) { + s->ipa_granule = qemu_real_host_page_size(); + } + hvf_set_map_granule(s->ipa_granule); if (mc->get_physical_address_range) { pa_range = mc->get_physical_address_range(ms, @@ -223,6 +245,8 @@ static void hvf_accel_class_init(ObjectClass *oc, const void *data) ac->init_machine = hvf_accel_init; ac->allowed = &hvf_allowed; ac->gdbstub_supported_sstep_flags = hvf_gdbstub_sstep_flags; + + hvf_arch_accel_class_init(oc); } static const TypeInfo hvf_accel_type = { diff --git a/include/system/hvf.h b/include/system/hvf.h index d3dcf088..3c4c3b89 100644 --- a/include/system/hvf.h +++ b/include/system/hvf.h @@ -36,4 +36,19 @@ typedef struct HVFState HVFState; DECLARE_INSTANCE_CHECKER(HVFState, HVF_STATE, TYPE_HVF_ACCEL) +#ifdef CONFIG_HVF_IS_POSSIBLE +/* + * Minimum alignment for hv_vm_map(). Returns the configured IPA granule + * or host page size if not set. + */ +void hvf_set_map_granule(uint64_t size); +uint64_t hvf_get_map_granule(void); +#else +static inline void hvf_set_map_granule(uint64_t size) {} +static inline uint64_t hvf_get_map_granule(void) +{ + return qemu_real_host_page_size(); +} +#endif + #endif diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index 2621164c..9589b022 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -38,6 +38,7 @@ struct HVFState { hvf_vcpu_caps *hvf_caps; uint64_t vtimer_offset; + uint32_t ipa_granule; QTAILQ_HEAD(, hvf_sw_breakpoint) hvf_sw_breakpoints; }; extern HVFState *hvf_state; @@ -57,6 +58,7 @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, const char *hvf_return_string(hv_return_t ret); int hvf_arch_init(void); hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range); +void hvf_arch_accel_class_init(ObjectClass *oc); uint32_t hvf_arch_get_default_ipa_bit_size(void); uint32_t hvf_arch_get_max_ipa_bit_size(void); void hvf_kick_vcpu_thread(CPUState *cpu); diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 5fc8f6bb..1ba5bbf3 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -12,6 +12,8 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "qemu/log.h" +#include "qemu/units.h" +#include "qapi/error.h" #include "system/runstate.h" #include "system/hvf.h" @@ -1218,6 +1220,44 @@ void hvf_arch_vcpu_destroy(CPUState *cpu) assert_hvf_ok(ret); } +static char *hvf_get_ipa_granule(Object *obj, Error **errp) +{ + HVFState *s = HVF_STATE(obj); + + if (s->ipa_granule == 4 * KiB) { + return g_strdup("4k"); + } + if (s->ipa_granule == 16 * KiB) { + return g_strdup("16k"); + } + return g_strdup("auto"); +} + +static void hvf_set_ipa_granule(Object *obj, const char *value, Error **errp) +{ + HVFState *s = HVF_STATE(obj); + + if (!strcmp(value, "auto")) { + s->ipa_granule = 0; + } else if (!strcmp(value, "4k")) { + s->ipa_granule = 4 * KiB; + } else if (!strcmp(value, "16k")) { + s->ipa_granule = 16 * KiB; + } else { + error_setg(errp, "invalid ipa-granule: '%s' (use auto, 4k, 16k)", + value); + } +} + +void hvf_arch_accel_class_init(ObjectClass *oc) +{ + object_class_property_add_str(oc, "ipa-granule", + hvf_get_ipa_granule, + hvf_set_ipa_granule); + object_class_property_set_description(oc, "ipa-granule", + "IPA granule for HVF stage-2 translation (auto, 4k, 16k)"); +} + hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range) { hv_return_t ret; diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index c0d028b1..565c79b3 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -228,6 +228,10 @@ int hvf_arch_init(void) return 0; } +void hvf_arch_accel_class_init(ObjectClass *oc) +{ +} + /* 48-bit on all Intel Macs. Function currently unused. */ uint32_t hvf_arch_get_default_ipa_bit_size(void) { -- 2.52.0 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v4 2/3] accel/hvf: introduce map granule abstraction and IPA property 2026-03-17 17:57 ` [PATCH v4 2/3] accel/hvf: introduce map granule abstraction and IPA property Lucas Amaral @ 2026-04-23 18:05 ` Alex Bennée 2026-04-23 23:44 ` Lucas Amaral 0 siblings, 1 reply; 17+ messages in thread From: Alex Bennée @ 2026-04-23 18:05 UTC (permalink / raw) To: Lucas Amaral; +Cc: qemu-devel, qemu-arm, agraf, peter.maydell, mohamed Lucas Amaral <lucaaamaral@gmail.com> writes: > Add a map granule abstraction that decouples HVF memory mapping > alignment from the host page size. On ARM64, Apple Silicon supports > stage-2 translation with 4KB page granules regardless of the host OS > page size (16KB on macOS). This allows running guests with 4KB pages > without interior mapping failures. > > Introduce hvf_set_map_granule()/hvf_get_map_granule() in hvf-all.c > to replace hard-coded qemu_real_host_page_size() references in > do_hv_vm_protect() and hvf_set_phys_mem(). When the granule is not > explicitly configured, fall back to host page size to preserve the > previous behaviour. > > Add an "ipa-granule" accelerator property (auto, 4k, 16k) following > the established kvm_arch_accel_class_init() pattern: ARM registers > the property in hvf_arch_accel_class_init(), x86 provides an empty > stub. This avoids #ifdef __aarch64__ in common code while keeping > a single hvf-all.c shared by both targets. > > Fix hvf_set_phys_mem() to return early for non-aligned regions instead > of clearing the add flag, which previously fell through to an > incorrect unmap of a region that was never mapped. > > Signed-off-by: Lucas Amaral <lucaaamaral@gmail.com> > --- > accel/hvf/hvf-all.c | 30 +++++++++++++++++++++++++++--- > include/system/hvf.h | 15 +++++++++++++++ > include/system/hvf_int.h | 2 ++ > target/arm/hvf/hvf.c | 40 ++++++++++++++++++++++++++++++++++++++++ > target/i386/hvf/hvf.c | 4 ++++ > 5 files changed, 88 insertions(+), 3 deletions(-) > > diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c > index 5f357c6d..d745fefd 100644 > --- a/accel/hvf/hvf-all.c > +++ b/accel/hvf/hvf-all.c > @@ -10,6 +10,8 @@ > > #include "qemu/osdep.h" > #include "qemu/error-report.h" > +#include "qemu/units.h" > +#include "qapi/error.h" > #include "accel/accel-ops.h" > #include "exec/cpu-common.h" > #include "system/address-spaces.h" > @@ -22,6 +24,21 @@ > > bool hvf_allowed; > > +static uint64_t hvf_map_granule; > + > +void hvf_set_map_granule(uint64_t size) > +{ > + hvf_map_granule = size; > +} > + > +uint64_t hvf_get_map_granule(void) > +{ > + if (!hvf_map_granule) { > + return qemu_real_host_page_size(); > + } > + return hvf_map_granule; > +} > + > const char *hvf_return_string(hv_return_t ret) > { > switch (ret) { > @@ -53,7 +70,7 @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, > static void do_hv_vm_protect(hwaddr start, size_t size, > hv_memory_flags_t flags) > { > - intptr_t page_mask = qemu_real_host_page_mask(); > + intptr_t page_mask = -(intptr_t)hvf_get_map_granule(); > hv_return_t ret; > > trace_hvf_vm_protect(start, size, flags, > @@ -83,7 +100,7 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add) > MemoryRegion *area = section->mr; > bool writable = !area->readonly && !area->rom_device; > hv_memory_flags_t flags; > - uint64_t page_size = qemu_real_host_page_size(); > + uint64_t page_size = hvf_get_map_granule(); > uint64_t gpa = section->offset_within_address_space; > uint64_t size = int128_get64(section->size); > hv_return_t ret; > @@ -104,7 +121,7 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add) > if (!QEMU_IS_ALIGNED(size, page_size) || > !QEMU_IS_ALIGNED(gpa, page_size)) { > /* Not page aligned, so we can not map as RAM */ > - add = false; > + return; > } > > if (!add) { > @@ -186,6 +203,11 @@ static int hvf_accel_init(AccelState *as, MachineState *ms) > int pa_range = 36; > MachineClass *mc = MACHINE_GET_CLASS(ms); > > + /* Resolve ipa-granule=auto → host page size */ > + if (!s->ipa_granule) { > + s->ipa_granule = qemu_real_host_page_size(); > + } > + hvf_set_map_granule(s->ipa_granule); > > if (mc->get_physical_address_range) { > pa_range = mc->get_physical_address_range(ms, > @@ -223,6 +245,8 @@ static void hvf_accel_class_init(ObjectClass *oc, const void *data) > ac->init_machine = hvf_accel_init; > ac->allowed = &hvf_allowed; > ac->gdbstub_supported_sstep_flags = hvf_gdbstub_sstep_flags; > + > + hvf_arch_accel_class_init(oc); > } > > static const TypeInfo hvf_accel_type = { > diff --git a/include/system/hvf.h b/include/system/hvf.h > index d3dcf088..3c4c3b89 100644 > --- a/include/system/hvf.h > +++ b/include/system/hvf.h > @@ -36,4 +36,19 @@ typedef struct HVFState HVFState; > DECLARE_INSTANCE_CHECKER(HVFState, HVF_STATE, > TYPE_HVF_ACCEL) > > +#ifdef CONFIG_HVF_IS_POSSIBLE > +/* > + * Minimum alignment for hv_vm_map(). Returns the configured IPA granule > + * or host page size if not set. > + */ > +void hvf_set_map_granule(uint64_t size); > +uint64_t hvf_get_map_granule(void); > +#else > +static inline void hvf_set_map_granule(uint64_t size) {} > +static inline uint64_t hvf_get_map_granule(void) > +{ > + return qemu_real_host_page_size(); > +} > +#endif > + > #endif > diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h > index 2621164c..9589b022 100644 > --- a/include/system/hvf_int.h > +++ b/include/system/hvf_int.h > @@ -38,6 +38,7 @@ struct HVFState { > > hvf_vcpu_caps *hvf_caps; > uint64_t vtimer_offset; > + uint32_t ipa_granule; > QTAILQ_HEAD(, hvf_sw_breakpoint) hvf_sw_breakpoints; > }; > extern HVFState *hvf_state; > @@ -57,6 +58,7 @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, > const char *hvf_return_string(hv_return_t ret); > int hvf_arch_init(void); > hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range); > +void hvf_arch_accel_class_init(ObjectClass *oc); > uint32_t hvf_arch_get_default_ipa_bit_size(void); > uint32_t hvf_arch_get_max_ipa_bit_size(void); > void hvf_kick_vcpu_thread(CPUState *cpu); > diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c > index 5fc8f6bb..1ba5bbf3 100644 > --- a/target/arm/hvf/hvf.c > +++ b/target/arm/hvf/hvf.c > @@ -12,6 +12,8 @@ > #include "qemu/osdep.h" > #include "qemu/error-report.h" > #include "qemu/log.h" > +#include "qemu/units.h" > +#include "qapi/error.h" > > #include "system/runstate.h" > #include "system/hvf.h" > @@ -1218,6 +1220,44 @@ void hvf_arch_vcpu_destroy(CPUState *cpu) > assert_hvf_ok(ret); > } > > +static char *hvf_get_ipa_granule(Object *obj, Error **errp) > +{ > + HVFState *s = HVF_STATE(obj); > + > + if (s->ipa_granule == 4 * KiB) { > + return g_strdup("4k"); > + } > + if (s->ipa_granule == 16 * KiB) { > + return g_strdup("16k"); > + } > + return g_strdup("auto"); > +} > + > +static void hvf_set_ipa_granule(Object *obj, const char *value, Error **errp) > +{ > + HVFState *s = HVF_STATE(obj); > + > + if (!strcmp(value, "auto")) { > + s->ipa_granule = 0; > + } else if (!strcmp(value, "4k")) { > + s->ipa_granule = 4 * KiB; > + } else if (!strcmp(value, "16k")) { > + s->ipa_granule = 16 * KiB; > + } else { > + error_setg(errp, "invalid ipa-granule: '%s' (use auto, 4k, 16k)", > + value); > + } There is a minor preference to use the glib functions here, g_strcmp0(). > +} > + > +void hvf_arch_accel_class_init(ObjectClass *oc) > +{ > + object_class_property_add_str(oc, "ipa-granule", > + hvf_get_ipa_granule, > + hvf_set_ipa_granule); > + object_class_property_set_description(oc, "ipa-granule", > + "IPA granule for HVF stage-2 translation (auto, 4k, 16k)"); > +} > + > hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range) > { > hv_return_t ret; > diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c > index c0d028b1..565c79b3 100644 > --- a/target/i386/hvf/hvf.c > +++ b/target/i386/hvf/hvf.c > @@ -228,6 +228,10 @@ int hvf_arch_init(void) > return 0; > } > > +void hvf_arch_accel_class_init(ObjectClass *oc) > +{ > +} > + > /* 48-bit on all Intel Macs. Function currently unused. */ > uint32_t hvf_arch_get_default_ipa_bit_size(void) > { -- Alex Bennée Virtualisation Tech Lead @ Linaro ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 2/3] accel/hvf: introduce map granule abstraction and IPA property 2026-04-23 18:05 ` Alex Bennée @ 2026-04-23 23:44 ` Lucas Amaral 0 siblings, 0 replies; 17+ messages in thread From: Lucas Amaral @ 2026-04-23 23:44 UTC (permalink / raw) To: Alex Bennée Cc: Lucas Amaral, qemu-devel, qemu-arm, peter.maydell, agraf, mohamed Hi Alex, > There is a minor preference to use the glib functions here, g_strcmp0(). Will fix in v5, thanks. Lucas ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v4 3/3] target/arm/hvf: configure IPA granule on macOS 26 2026-03-17 17:57 [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix Lucas Amaral 2026-03-17 17:57 ` [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs Lucas Amaral 2026-03-17 17:57 ` [PATCH v4 2/3] accel/hvf: introduce map granule abstraction and IPA property Lucas Amaral @ 2026-03-17 17:57 ` Lucas Amaral 2026-04-09 17:52 ` [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix Lucas Amaral 3 siblings, 0 replies; 17+ messages in thread From: Lucas Amaral @ 2026-03-17 17:57 UTC (permalink / raw) To: qemu-devel; +Cc: qemu-arm, agraf, peter.maydell, mohamed, Lucas Amaral Read the ipa-granule property (set by hvf_accel_init) and configure the HVF stage-2 translation granule via hv_vm_config_set_ipa_granule() on macOS 26+. When ipa-granule=4k, use HV_IPA_GRANULE_4KB to allow HVF to map memory at 4KB granularity, matching 4KB-page guests on hosts with larger page sizes. If macOS < 26 and a sub-host-page granule was requested, warn and fall back to the host page size. Signed-off-by: Lucas Amaral <lucaaamaral@gmail.com> --- target/arm/hvf/hvf.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 1ba5bbf3..e3b1e3e1 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -1269,6 +1269,38 @@ hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range) } chosen_ipa_bit_size = pa_range; + /* + * Configure IPA granule from the ipa-granule property. + * hvf_get_map_granule() was set by hvf_accel_init() before this call. + */ + { + uint64_t granule = hvf_get_map_granule(); + bool granule_set = false; + +#if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ + (__MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_26_0) + if (__builtin_available(macOS 26, *)) { + hv_ipa_granule_t hv_gran = (granule <= 4 * KiB) + ? HV_IPA_GRANULE_4KB : HV_IPA_GRANULE_16KB; + ret = hv_vm_config_set_ipa_granule(config, hv_gran); + if (ret != HV_SUCCESS) { + error_report("HVF: failed to set IPA granule: %s", + hvf_return_string(ret)); + goto cleanup; + } + granule_set = true; + } +#endif + + if (!granule_set && granule < qemu_real_host_page_size()) { + warn_report("HVF: ipa-granule=%zuKB requested but macOS < 26; " + "falling back to host page size (%zuKB)", + (size_t)(granule / KiB), + (size_t)(qemu_real_host_page_size() / KiB)); + hvf_set_map_granule(qemu_real_host_page_size()); + } + } + ret = hv_vm_create(config); cleanup: -- 2.52.0 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix 2026-03-17 17:57 [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix Lucas Amaral ` (2 preceding siblings ...) 2026-03-17 17:57 ` [PATCH v4 3/3] target/arm/hvf: configure IPA granule on macOS 26 Lucas Amaral @ 2026-04-09 17:52 ` Lucas Amaral 2026-04-09 19:06 ` Peter Maydell 3 siblings, 1 reply; 17+ messages in thread From: Lucas Amaral @ 2026-04-09 17:52 UTC (permalink / raw) To: qemu-devel Cc: Lucas Amaral, qemu-arm, agraf, peter.maydell, mohamed, alex.bennee Ping. https://patchew.org/QEMU/20260317175744.32469-1-lucaaamaral@gmail.com/ Mohamed gave Reviewed-by on v2 (nits addressed in v3/v4). Patches still apply cleanly on current master. Thanks, Lucas ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix 2026-04-09 17:52 ` [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix Lucas Amaral @ 2026-04-09 19:06 ` Peter Maydell 2026-04-10 14:13 ` Peter Maydell 0 siblings, 1 reply; 17+ messages in thread From: Peter Maydell @ 2026-04-09 19:06 UTC (permalink / raw) To: Lucas Amaral; +Cc: qemu-devel, qemu-arm, agraf, mohamed, alex.bennee On Thu, 9 Apr 2026 at 18:52, Lucas Amaral <lucaaamaral@gmail.com> wrote: > > Ping. > > https://patchew.org/QEMU/20260317175744.32469-1-lucaaamaral@gmail.com/ > > Mohamed gave Reviewed-by on v2 (nits addressed in v3/v4). Patches still > apply cleanly on current master. This is on my todo list to look at; I've been prioritizing 11.0 work while we're in freeze. thanks -- PMM ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix 2026-04-09 19:06 ` Peter Maydell @ 2026-04-10 14:13 ` Peter Maydell 2026-04-23 17:22 ` Lucas Amaral 0 siblings, 1 reply; 17+ messages in thread From: Peter Maydell @ 2026-04-10 14:13 UTC (permalink / raw) To: Lucas Amaral; +Cc: qemu-devel, qemu-arm, agraf, mohamed, alex.bennee On Thu, 9 Apr 2026 at 20:06, Peter Maydell <peter.maydell@linaro.org> wrote: > > On Thu, 9 Apr 2026 at 18:52, Lucas Amaral <lucaaamaral@gmail.com> wrote: > > > > Ping. > > > > https://patchew.org/QEMU/20260317175744.32469-1-lucaaamaral@gmail.com/ > > > > Mohamed gave Reviewed-by on v2 (nits addressed in v3/v4). Patches still > > apply cleanly on current master. > > This is on my todo list to look at; I've been prioritizing 11.0 > work while we're in freeze. None of these patches seem to have reviewed-by tags. Mohamed, Alex B, would you mind taking a look at them ? The question that comes to my mind is whether the two places changed in accel/hvf to look at hvf_get_map_granule() really are the only two places in the whole of QEMU where we call qemu_real_host_page_size() and expect it to be also the guest page size. The general idea of "guest page size might not be the same as the host page size QEMU itself gets" isn't hvf specific -- maybe we should have a qemu_guest_page_size() function ? thanks -- PMM ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix 2026-04-10 14:13 ` Peter Maydell @ 2026-04-23 17:22 ` Lucas Amaral 2026-04-24 7:08 ` Philippe Mathieu-Daudé 0 siblings, 1 reply; 17+ messages in thread From: Lucas Amaral @ 2026-04-23 17:22 UTC (permalink / raw) To: Peter Maydell Cc: Lucas Amaral, qemu-devel, qemu-arm, agraf, mohamed, alex.bennee Hi Peter, Thanks for the review and for asking Mohamed and Alex to take a look. > The question that comes to my mind is whether the two places changed > in accel/hvf to look at hvf_get_map_granule() really are the only > two places in the whole of QEMU where we call > qemu_real_host_page_size() and expect it to be also the guest page > size. The general idea of 'guest page size might not be the same as > the host page size QEMU itself gets' isn't hvf specific -- maybe we > should have a qemu_guest_page_size() function? Good point. I'll audit the qemu_real_host_page_size() call sites to see which ones actually mean "guest page size" and whether a broader qemu_guest_page_size() abstraction makes sense. I'd send that as a follow-up series once these patches land, so the immediate HVF fix isn't blocked on the broader refactor. Thanks, Lucas ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix 2026-04-23 17:22 ` Lucas Amaral @ 2026-04-24 7:08 ` Philippe Mathieu-Daudé 2026-04-24 21:38 ` Lucas Amaral 0 siblings, 1 reply; 17+ messages in thread From: Philippe Mathieu-Daudé @ 2026-04-24 7:08 UTC (permalink / raw) To: Lucas Amaral, Peter Maydell Cc: qemu-devel, qemu-arm, agraf, mohamed, alex.bennee Hi Lucas, On 23/4/26 19:22, Lucas Amaral wrote: > Hi Peter, > > Thanks for the review and for asking Mohamed and Alex to take a look. > >> The question that comes to my mind is whether the two places changed >> in accel/hvf to look at hvf_get_map_granule() really are the only >> two places in the whole of QEMU where we call >> qemu_real_host_page_size() and expect it to be also the guest page >> size. The general idea of 'guest page size might not be the same as >> the host page size QEMU itself gets' isn't hvf specific -- maybe we >> should have a qemu_guest_page_size() function? > > Good point. I'll audit the qemu_real_host_page_size() call sites to > see which ones actually mean "guest page size" and whether a broader > qemu_guest_page_size() abstraction makes sense. I'd send that as a > follow-up series once these patches land, so the immediate HVF fix > isn't blocked on the broader refactor. If using a generic approach, the property added in the previous patch should go into AccelState, at a glance registering the QOM property in accel_ops_class_init() in accel/accel-system.c. Also HVFState::ipa_granule -> AccelState::guest_page_size? ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix 2026-04-24 7:08 ` Philippe Mathieu-Daudé @ 2026-04-24 21:38 ` Lucas Amaral 0 siblings, 0 replies; 17+ messages in thread From: Lucas Amaral @ 2026-04-24 21:38 UTC (permalink / raw) To: Philippe Mathieu-Daudé Cc: qemu-devel, qemu-arm, Peter Maydell, Mohamed Mediouni, Alex Bennée, Alexander Graf On 2026-04-24, Philippe Mathieu-Daudé wrote: > If using a generic approach, the property added in the previous > patch should go into AccelState, at a glance registering the QOM > property in accel_ops_class_init() in accel/accel-system.c. > > Also HVFState::ipa_granule -> AccelState::guest_page_size? Would you prefer the AccelState lift bundled into v6 of this series, or done as the separate follow-up after v5 lands? Thanks, Lucas ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix
@ 2026-03-17 17:48 Lucas Amaral
2026-03-17 17:48 ` [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs Lucas Amaral
0 siblings, 1 reply; 17+ messages in thread
From: Lucas Amaral @ 2026-03-17 17:48 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, agraf, peter.maydell, mohamed, Lucas Amaral
Fix a bug in the MAP_FIXED blob mapping path (introduced by 4eb0aace)
where non-host-page-aligned offsets cause mmap(MAP_FIXED) to fail with
EINVAL. This affects any host where the page size exceeds the guest's
(ARM64 with 16KB/64KB pages, macOS ARM64).
This series introduces:
1. MAP_FIXED alignment validation in virtio-gpu: check that both
offset and blob size are aligned to the host page size before
calling virgl_renderer_resource_map_fixed(). When not aligned,
fall through to the subregion method (which works at any
alignment).
2. A map granule abstraction (hvf_set/get_map_granule) replacing
hardcoded qemu_real_host_page_size() calls in HVF memory mapping.
Non-aligned regions return early instead of proceeding with
add=false (which attempted an unnecessary unmap).
An 'ipa-granule' property (auto, 4k, 16k) on the HVF accelerator
object allows opt-in configuration:
-accel hvf,ipa-granule=4k
The property follows the kvm_arch_accel_class_init() pattern:
ARM registers the property in hvf_arch_accel_class_init(), x86
provides an empty stub.
3. macOS 26 IPA granule support via hv_vm_config_set_ipa_granule(),
reading the ipa-granule property to select HV_IPA_GRANULE_4KB or
HV_IPA_GRANULE_16KB. Falls back with a warning on macOS < 26.
Dependencies: none.
Changes v3 -> v4:
- Rebased onto current master (no code changes)
- Resent as new top-level thread per Alex Bennée's feedback
Changes v2 -> v3:
- Rebased on current master
- Add MAP_FIXED alignment validation (new patch 1)
- Move #ifdef __aarch64__ property code into hvf_arch_accel_class_init
following kvm_arch_accel_class_init() pattern (x86 empty stub)
- Use MAC_OS_VERSION_26_0 named constant
- Remove Venus blob mapping warning
Changes v1 -> v2 (Mohamed Mosaad review):
- Replace hardcoded 4KB with configurable ipa-granule property
(auto, 4k, 16k) on the HVF accelerator object.
- 'auto' defaults to host page size; explicit values opt in.
- Add fallback warning when macOS < 26 can't honor the request.
- Add Venus blob mapping safety warning.
- Use KiB constants instead of magic numbers.
Lucas Amaral (3):
virtio-gpu: validate host page alignment for MAP_FIXED blobs
accel/hvf: introduce map granule abstraction and IPA property
target/arm/hvf: configure IPA granule on macOS 26
accel/hvf/hvf-all.c | 30 +++++++++++++--
hw/display/virtio-gpu-virgl.c | 45 +++++++++++++---------
include/system/hvf.h | 15 ++++++++
include/system/hvf_int.h | 2 +
target/arm/hvf/hvf.c | 72 +++++++++++++++++++++++++++++++++++
target/i386/hvf/hvf.c | 4 ++
6 files changed, 147 insertions(+), 21 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs 2026-03-17 17:48 Lucas Amaral @ 2026-03-17 17:48 ` Lucas Amaral 0 siblings, 0 replies; 17+ messages in thread From: Lucas Amaral @ 2026-03-17 17:48 UTC (permalink / raw) To: qemu-devel; +Cc: qemu-arm, agraf, peter.maydell, mohamed, Lucas Amaral Commit 4eb0aace ("virtio-gpu: Support mapping hostmem blobs with map_fixed") uses mmap(MAP_FIXED) to map blob resources into a pre-allocated hostmem region. Both the offset and size passed to mmap must be aligned to the host page size, but the code does not validate this. On hosts where qemu_real_host_page_size() exceeds the guest's page size (e.g. ARM64 with 16KB or 64KB pages, macOS ARM64), the guest may provide blob offsets aligned to its own page size (4KB) but not to the host's. This causes mmap(MAP_FIXED) to fail with EINVAL, and the subsequent unmap (which also uses mmap MAP_FIXED) fails the same way, producing: virtio_gpu_virgl_unmap_resource_blob: failed to unmap(fixed) virgl resource: Invalid argument Add an alignment check before attempting MAP_FIXED. When the offset or blob size is not host-page-aligned, skip the MAP_FIXED path and fall through to the existing subregion method, which handles any alignment. Fixes: 4eb0aace ("virtio-gpu: Support mapping hostmem blobs with map_fixed") Signed-off-by: Lucas Amaral <lucaaamaral@gmail.com> --- hw/display/virtio-gpu-virgl.c | 45 +++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c index b7a2d160..f6583b48 100644 --- a/hw/display/virtio-gpu-virgl.c +++ b/hw/display/virtio-gpu-virgl.c @@ -185,25 +185,34 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g, return -EBUSY; } - ret = virgl_renderer_resource_map_fixed(res->base.resource_id, - gl->hostmem_mmap + offset); - switch (ret) { - case 0: - res->map_fixed = gl->hostmem_mmap + offset; - return 0; - - case -EOPNOTSUPP: - /* - * MAP_FIXED is unsupported by this resource. - * Mapping falls back to a blob subregion method in that case. - */ - break; + /* + * MAP_FIXED requires host-page-aligned offset and size. Hosts with + * page sizes larger than the guest's (e.g. 16KB on ARM64) may receive + * non-aligned blob offsets. Fall through to the subregion method when + * alignment requirements are not met. + */ + if (QEMU_IS_ALIGNED(offset, qemu_real_host_page_size()) && + QEMU_IS_ALIGNED(res->base.blob_size, qemu_real_host_page_size())) { + ret = virgl_renderer_resource_map_fixed(res->base.resource_id, + gl->hostmem_mmap + offset); + switch (ret) { + case 0: + res->map_fixed = gl->hostmem_mmap + offset; + return 0; + + case -EOPNOTSUPP: + /* + * MAP_FIXED is unsupported by this resource. + * Mapping falls back to a blob subregion method in that case. + */ + break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: failed to map(fixed) virgl resource: %s\n", - __func__, strerror(-ret)); - return ret; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: failed to map(fixed) virgl resource: %s\n", + __func__, strerror(-ret)); + return ret; + } } #endif -- 2.52.0 ^ permalink raw reply related [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-04-24 21:38 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-17 17:57 [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix Lucas Amaral 2026-03-17 17:57 ` [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs Lucas Amaral 2026-04-23 18:00 ` Alex Bennée 2026-04-23 23:44 ` Lucas Amaral 2026-04-24 10:09 ` Alex Bennée 2026-04-24 21:37 ` Lucas Amaral 2026-03-17 17:57 ` [PATCH v4 2/3] accel/hvf: introduce map granule abstraction and IPA property Lucas Amaral 2026-04-23 18:05 ` Alex Bennée 2026-04-23 23:44 ` Lucas Amaral 2026-03-17 17:57 ` [PATCH v4 3/3] target/arm/hvf: configure IPA granule on macOS 26 Lucas Amaral 2026-04-09 17:52 ` [PATCH v4 0/3] hvf: map granule abstraction, configurable IPA, and MAP_FIXED alignment fix Lucas Amaral 2026-04-09 19:06 ` Peter Maydell 2026-04-10 14:13 ` Peter Maydell 2026-04-23 17:22 ` Lucas Amaral 2026-04-24 7:08 ` Philippe Mathieu-Daudé 2026-04-24 21:38 ` Lucas Amaral -- strict thread matches above, loose matches on Subject: below -- 2026-03-17 17:48 Lucas Amaral 2026-03-17 17:48 ` [PATCH v4 1/3] virtio-gpu: validate host page alignment for MAP_FIXED blobs Lucas Amaral
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.