@@ -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 = {
@@ -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
@@ -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, *)) {
@@ -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)
+{
+}
macOS 27.0 ships with an experimental VHE enablement private API. Expose support for it as x-vhe. Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> --- 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(+)