Replace hardcoded qemu_real_host_page_size() calls in HVF memory
mapping with a configurable map granule (hvf_set/get_map_granule).
On macOS ARM64, the host page size is 16KB, but the guest kernel
typically uses 4KB pages. The map granule determines the minimum
alignment for hv_vm_map() and hv_vm_protect().
Default behavior is unchanged (returns host page size). A subsequent
commit will configure 4KB granule on macOS 26+.
Also fix the non-aligned region path in hvf_set_phys_mem() to return
early instead of proceeding with add=false, which would attempt an
unnecessary unmap of a region that was never mapped.
Signed-off-by: Lucas Amaral <lucaaamaral@gmail.com>
---
accel/hvf/hvf-all.c | 21 ++++++++++++++++++---
include/system/hvf.h | 15 +++++++++++++++
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index 033c677..ccff626 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -23,6 +23,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) {
@@ -54,7 +69,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,
@@ -84,7 +99,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;
@@ -105,7 +120,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) {
diff --git a/include/system/hvf.h b/include/system/hvf.h
index d3dcf08..d1b702b 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 host page size (16KB on
+ * macOS ARM64), or 4KB when HVF 4KB IPA granule is configured (macOS 26+).
+ */
+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
--
2.52.0