macOS 27.0 ships with an experimental VHE enablement private API. Expose support for it as x-vhe.
Signed-off-by: Mohamed Mediouni <[email protected]> --- accel/hvf/hvf-all.c | 2 + include/system/hvf_int.h | 1 + target/arm/hvf/hvf.c | 89 ++++++++++++++++++++++++++++++++++++++++ target/i386/hvf/hvf.c | 4 ++ 4 files changed, 96 insertions(+) diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c index 8bd9154a50..bbff3c6867 100644 --- a/accel/hvf/hvf-all.c +++ b/accel/hvf/hvf-all.c @@ -282,6 +282,8 @@ static void hvf_accel_class_init(ObjectClass *oc, const void *data) NULL, NULL); object_class_property_set_description(oc, "kernel-irqchip", "Configure HVF irqchip"); + + hvf_arch_accel_class_init(oc); } static const TypeInfo hvf_accel_type = { diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index a01691ce17..44ae2e7c4c 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -110,5 +110,6 @@ int hvf_update_guest_debug(CPUState *cpu); bool hvf_arch_cpu_realize(CPUState *cpu, Error **errp); uint32_t hvf_arch_get_default_ipa_bit_size(void); uint32_t hvf_arch_get_max_ipa_bit_size(void); +void hvf_arch_accel_class_init(ObjectClass *oc); #endif diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index f881d6cc67..b61554e108 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -22,6 +22,7 @@ #include "cpu-sysregs.h" #include <mach/mach_time.h> +#include <dlfcn.h> #include "system/address-spaces.h" #include "system/memory.h" @@ -39,6 +40,7 @@ #include "target/arm/trace.h" #include "trace.h" #include "migration/vmstate.h" +#include "migration/blocker.h" #include "gdbstub/enums.h" @@ -1132,6 +1134,60 @@ static void clamp_id_aa64mmfr0_parange_to_ipa_size(ARMISARegisters *isar) SET_IDREG(isar, ID_AA64MMFR0, id_aa64mmfr0); } +bool hvf_vhe; + +static void hvf_set_vhe(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + OnOffAuto mode; + + if (!visit_type_OnOffAuto(v, name, &mode, errp)) { + return; + } + + switch (mode) { + case ON_OFF_AUTO_ON: + if (__builtin_available(macOS 27.0, *)) { + hvf_vhe = true; + } else { + error_report("VHE emulation not supported on this system."); + } + break; + + case ON_OFF_AUTO_OFF: + hvf_vhe = false; + break; + + case ON_OFF_AUTO_AUTO: + /* Experimental feature as of macOS 27.0 */ + hvf_vhe = false; + break; + default: + /* + * The value was checked in visit_type_OnOffAuto() above. If + * we get here, then something is wrong in QEMU. + */ + abort(); + } +} + +static bool hvf_get_vhe(void) +{ + return hvf_vhe; +} + +void hvf_arch_accel_class_init(ObjectClass *oc) +{ + hvf_vhe = false; + + object_class_property_add(oc, "x-vhe", "OnOffAuto", + NULL, hvf_set_vhe, + NULL, NULL); + object_class_property_set_description(oc, "x-vhe", + "Configure experimental VHE enablement"); +} + static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) { ARMISARegisters host_isar = {}; @@ -1227,6 +1283,9 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) if (hvf_nested_virt_enabled()) { /* SME is not implemented with nested virt on the Apple side */ FIELD_DP64_IDREG(&host_isar, ID_AA64PFR1, SME, 0); + if (hvf_get_vhe()) { + FIELD_DP64_IDREG(&host_isar, ID_AA64MMFR1, VH, 0x1); + } } /* @@ -1357,6 +1416,36 @@ hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range) } } + if (hvf_get_vhe()) { + Error *vhe_migration_blocker = NULL; + Error* errp; + + void* hvf = dlopen("/System/Library/Frameworks/Hypervisor.framework/Versions/A/Hypervisor", RTLD_LOCAL); + + if (!hvf) { + /* Unreachable. */ + error_report("Failed to dlopen() Hypervisor.framework."); + goto cleanup; + } + + /* Experimental API: might change before release. */ + hv_return_t (*_hv_vm_config_set_vhe_enabled)(hv_vm_config_t cfg, bool vhe) = dlsym(hvf, "_hv_vm_config_set_vhe_enabled"); + if (!_hv_vm_config_set_vhe_enabled) { + error_report("_hv_vm_config_set_vhe_enabled API not available."); + goto cleanup; + } + _hv_vm_config_set_vhe_enabled(config, true); + + error_setg(&vhe_migration_blocker, + "Live migration disabled because VHE support is experimental"); + if (migrate_add_blocker(&vhe_migration_blocker, &errp)) { + error_report("Failed to add migration blocker."); + goto cleanup; + } + + dlclose(hvf); + } + ret = hv_vm_create(config); if (hvf_irqchip_in_kernel()) { if (__builtin_available(macOS 15.0, *)) { diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 150598418e..5a39a82492 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -1068,3 +1068,7 @@ void hvf_arch_remove_all_gdbstub_hw_breakpoints(void) void hvf_arch_update_guest_debug(CPUState *cpu) { } + +void hvf_arch_accel_class_init(ObjectClass *oc) +{ +} -- 2.54.0 (Apple Git-156)
