From 43dc32d4afbd24fe131741cbf24c075a4edbc849 Mon Sep 17 00:00:00 2001 From: osy <50960678+osy@users.noreply.github.com> Date: Thu, 29 Dec 2022 00:27:38 -0800 Subject: [PATCH 1/2] qemu: patch to enable TSO on hacked iOS --- patches/qemu-7.2.0-utm.patch | 263 ++++++++++++++++++++++++++++++++++ patches/sources | 2 +- scripts/build_dependencies.sh | 2 +- 3 files changed, 265 insertions(+), 2 deletions(-) diff --git a/patches/qemu-7.2.0-utm.patch b/patches/qemu-7.2.0-utm.patch index 3231e60ed..caa4a10d2 100644 --- a/patches/qemu-7.2.0-utm.patch +++ b/patches/qemu-7.2.0-utm.patch @@ -322,3 +322,266 @@ index 7f589b4146..d311c57cca 100644 -- 2.28.0 +From 531da34587b38c64787cb25b1de1c5d13f75def8 Mon Sep 17 00:00:00 2001 +From: osy <50960678+osy@users.noreply.github.com> +Date: Wed, 28 Dec 2022 16:50:49 -0800 +Subject: [PATCH] hvf: support TSO mode (private feature) + +Apple Silicon supports TSO mode which can be used for emulating strong +memory ordering in the guest. This feature requires the private entitlement +`com.apple.private.hypervisor` as well as a private function to modify +ACTLR_EL1 not exposed by the public Hypervisor framework. +--- + accel/hvf/hvf-accel-ops.c | 51 ++++++++++++++++++++++++++--------- + include/sysemu/hvf_int.h | 13 +++++++++ + meson.build | 1 + + meson_options.txt | 2 ++ + scripts/meson-buildoptions.sh | 3 +++ + target/arm/hvf/hvf.c | 28 +++++++++++++++++++ + target/i386/hvf/hvf.c | 5 ++++ + 7 files changed, 90 insertions(+), 13 deletions(-) + +diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c +index 24913ca9c4..b414e240ec 100644 +--- a/accel/hvf/hvf-accel-ops.c ++++ b/accel/hvf/hvf-accel-ops.c +@@ -57,13 +57,10 @@ + #include "sysemu/hvf_int.h" + #include "sysemu/runstate.h" + #include "qemu/guest-random.h" ++#include "hw/boards.h" + + HVFState *hvf_state; + +-#ifdef __aarch64__ +-#define HV_VM_DEFAULT NULL +-#endif +- + /* Memory slots */ + + hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size) +@@ -319,25 +316,44 @@ bool hvf_allowed; + + static int hvf_accel_init(MachineState *ms) + { +- int x; + hv_return_t ret; +- HVFState *s; ++ HVFState *s = HVF_STATE(ms->accelerator); + +- ret = hv_vm_create(HV_VM_DEFAULT); ++ ret = hvf_arch_vm_create(s); + assert_hvf_ok(ret); + +- s = g_new0(HVFState, 1); ++ hvf_state = s; ++ memory_listener_register(&hvf_memory_listener, &address_space_memory); ++ ++ return hvf_arch_init(); ++} ++ ++#if defined(CONFIG_HVF_PRIVATE) && defined(__aarch64__) ++ ++static bool hvf_get_tso(Object *obj, Error **errp) ++{ ++ HVFState *s = HVF_STATE(obj); ++ return s->tso_mode; ++} ++ ++static void hvf_set_tso(Object *obj, bool value, Error **errp) ++{ ++ HVFState *s = HVF_STATE(obj); ++ s->tso_mode = value; ++} ++ ++#endif ++ ++static void hvf_accel_instance_init(Object *obj) ++{ ++ int x; ++ HVFState *s = HVF_STATE(obj); + + s->num_slots = ARRAY_SIZE(s->slots); + for (x = 0; x < s->num_slots; ++x) { + s->slots[x].size = 0; + s->slots[x].slot_id = x; + } +- +- hvf_state = s; +- memory_listener_register(&hvf_memory_listener, &address_space_memory); +- +- return hvf_arch_init(); + } + + static void hvf_accel_class_init(ObjectClass *oc, void *data) +@@ -346,12 +362,21 @@ static void hvf_accel_class_init(ObjectClass *oc, void *data) + ac->name = "HVF"; + ac->init_machine = hvf_accel_init; + ac->allowed = &hvf_allowed; ++ ++#if defined(CONFIG_HVF_PRIVATE) && defined(__aarch64__) ++ object_class_property_add_bool(oc, "tso", ++ hvf_get_tso, hvf_set_tso); ++ object_class_property_set_description(oc, "tso", ++ "Set on/off to enable/disable total store ordering mode"); ++#endif + } + + static const TypeInfo hvf_accel_type = { + .name = TYPE_HVF_ACCEL, + .parent = TYPE_ACCEL, ++ .instance_init = hvf_accel_instance_init, + .class_init = hvf_accel_class_init, ++ .instance_size = sizeof(HVFState), + }; + + static void hvf_type_init(void) +diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h +index 6545f7cd61..9f550b9f8b 100644 +--- a/include/sysemu/hvf_int.h ++++ b/include/sysemu/hvf_int.h +@@ -17,6 +17,15 @@ + #include + #endif + ++#if defined(CONFIG_HVF_PRIVATE) && defined(__aarch64__) ++extern hv_return_t _hv_vm_config_set_isa(hv_vm_config_t config, uint32_t isa); ++extern hv_return_t _hv_vcpu_get_actlr(hv_vcpu_t vcpu, uint64_t* value); ++extern hv_return_t _hv_vcpu_set_actlr(hv_vcpu_t vcpu, uint64_t value); ++ ++#define HV_VM_CONFIG_ISA_PRIVATE (3) ++#define ACTLR_EL1_TSO_ENABLE_MASK ((1 << 1) | (1 << 9)) ++#endif ++ + /* hvf_slot flags */ + #define HVF_SLOT_LOG (1 << 0) + +@@ -45,6 +54,9 @@ struct HVFState { + + hvf_vcpu_caps *hvf_caps; + uint64_t vtimer_offset; ++#if defined(CONFIG_HVF_PRIVATE) && defined(__aarch64__) ++ bool tso_mode; ++#endif + }; + extern HVFState *hvf_state; + +@@ -56,6 +68,7 @@ struct hvf_vcpu_state { + }; + + void assert_hvf_ok(hv_return_t ret); ++hv_return_t hvf_arch_vm_create(HVFState *s); + int hvf_arch_init(void); + int hvf_arch_init_vcpu(CPUState *cpu); + void hvf_arch_vcpu_destroy(CPUState *cpu); +diff --git a/meson.build b/meson.build +index 00fccfc676..ab6a60d1a8 100644 +--- a/meson.build ++++ b/meson.build +@@ -440,6 +440,7 @@ if get_option('hvf').allowed() + required: get_option('hvf')) + if hvf.found() + accelerators += 'CONFIG_HVF' ++ config_host_data.set('CONFIG_HVF_PRIVATE', get_option('hvf_private')) + endif + endif + if get_option('hax').allowed() +diff --git a/meson_options.txt b/meson_options.txt +index 43916078c8..8415d45071 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -72,6 +72,8 @@ option('whpx', type: 'feature', value: 'auto', + description: 'WHPX acceleration support') + option('hvf', type: 'feature', value: 'auto', + description: 'HVF acceleration support') ++option('hvf_private', type: 'boolean', value: 'false', ++ description: 'HVF private features (entitlements required)') + option('nvmm', type: 'feature', value: 'auto', + description: 'NVMM acceleration support') + option('xen', type: 'feature', value: 'auto', +diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh +index 2496991056..010515ac98 100644 +--- a/scripts/meson-buildoptions.sh ++++ b/scripts/meson-buildoptions.sh +@@ -26,6 +26,7 @@ meson_options_help() { + printf "%s\n" ' --enable-fuzzing build fuzzing targets' + printf "%s\n" ' --enable-gcov Enable coverage tracking.' + printf "%s\n" ' --enable-gprof QEMU profiling with gprof' ++ printf "%s\n" ' --enable-hvf-private HVF private features (entitlements required)' + printf "%s\n" ' --enable-lto Use link time optimization' + printf "%s\n" ' --enable-malloc=CHOICE choose memory allocator to use [system] (choices:' + printf "%s\n" ' jemalloc/system/tcmalloc)' +@@ -289,6 +290,8 @@ _meson_option_parse() { + --disable-hax) printf "%s" -Dhax=disabled ;; + --enable-hvf) printf "%s" -Dhvf=enabled ;; + --disable-hvf) printf "%s" -Dhvf=disabled ;; ++ --enable-hvf-private) printf "%s" -Dhvf_private=true ;; ++ --disable-hvf-private) printf "%s" -Dhvf_private=false ;; + --iasl=*) quote_sh "-Diasl=$2" ;; + --enable-iconv) printf "%s" -Diconv=enabled ;; + --disable-iconv) printf "%s" -Diconv=disabled ;; +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index 2c0323fe7f..bb7a4d5004 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -623,6 +623,18 @@ int hvf_arch_init_vcpu(CPUState *cpu) + &arm_cpu->isar.id_aa64mmfr0); + assert_hvf_ok(ret); + ++#if defined(CONFIG_HVF_PRIVATE) ++ /* enable TSO mode */ ++ if (hvf_state->tso_mode) { ++ uint64_t actlr; ++ ret = _hv_vcpu_get_actlr(cpu->hvf->fd, &actlr); ++ assert_hvf_ok(ret); ++ actlr |= ACTLR_EL1_TSO_ENABLE_MASK; ++ ret = _hv_vcpu_set_actlr(cpu->hvf->fd, actlr); ++ assert_hvf_ok(ret); ++ } ++#endif ++ + return 0; + } + +@@ -1343,6 +1355,22 @@ static void hvf_vm_state_change(void *opaque, bool running, RunState state) + } + } + ++hv_return_t hvf_arch_vm_create(HVFState *s) ++{ ++#if defined(CONFIG_HVF_PRIVATE) ++ hv_return_t ret; ++ hv_vm_config_t config = hv_vm_config_create(); ++ if (s->tso_mode) { ++ _hv_vm_config_set_isa(config, HV_VM_CONFIG_ISA_PRIVATE); ++ } ++ ret = hv_vm_create(config); ++ os_release(config); ++ return ret; ++#else ++ return hv_vm_create(NULL); ++#endif ++} ++ + int hvf_arch_init(void) + { + hvf_state->vtimer_offset = mach_absolute_time(); +diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c +index 8d2248bb3f..8283a9b761 100644 +--- a/target/i386/hvf/hvf.c ++++ b/target/i386/hvf/hvf.c +@@ -212,6 +212,11 @@ void hvf_kick_vcpu_thread(CPUState *cpu) + cpus_kick_thread(cpu); + } + ++hv_return_t hvf_arch_vm_create(HVFState *s) ++{ ++ return hv_vm_create(HV_VM_DEFAULT); ++} ++ + int hvf_arch_init(void) + { + return 0; +-- +2.28.0 + diff --git a/patches/sources b/patches/sources index 44edd54c3..a1db85eaa 100644 --- a/patches/sources +++ b/patches/sources @@ -45,4 +45,4 @@ VIRGLRENDERER_COMMIT="d46413cf4797a33cfbe1c9f14e6d22ce563ef700" # Decompiled Hypervisor for iOS HYPERVISOR_REPO="https://github.com/utmapp/Hypervisor.git" -HYPERVISOR_COMMIT="c694e42468d2794b962714cdf76f180125e69f36" +HYPERVISOR_COMMIT="b4eb0e00c03692016944fad3e8e3a6613839912e" diff --git a/scripts/build_dependencies.sh b/scripts/build_dependencies.sh index 8befeddfe..91577aff9 100755 --- a/scripts/build_dependencies.sh +++ b/scripts/build_dependencies.sh @@ -671,7 +671,7 @@ ios* ) SDK=iphoneos CFLAGS_MINVER="-miphoneos-version-min=$SDKMINVER" PLATFORM_FAMILY_PREFIX="iOS" - HVF_FLAGS="" + HVF_FLAGS="--enable-hvf-private" ;; esac CFLAGS_TARGET= From 803b39c9dc2142a4f35e548450da107197ba0adb Mon Sep 17 00:00:00 2001 From: osy <50960678+osy@users.noreply.github.com> Date: Fri, 30 Dec 2022 22:54:32 -0800 Subject: [PATCH 2/2] config: add option to enable TSO --- Configuration/QEMUConstant.swift | 9 +++++++++ Configuration/UTMQemuConfiguration+Arguments.swift | 10 +++++++++- Configuration/UTMQemuConfigurationQEMU.swift | 3 +++ Platform/Shared/VMConfigQEMUView.swift | 8 ++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Configuration/QEMUConstant.swift b/Configuration/QEMUConstant.swift index e31a87626..e628091d1 100644 --- a/Configuration/QEMUConstant.swift +++ b/Configuration/QEMUConstant.swift @@ -428,6 +428,15 @@ extension QEMUArchitecture { return false #endif } + + /// TSO is supported on jailbroken iOS devices with Hypervisor support + var hasTSOSupport: Bool { + #if os(iOS) + return hasHypervisorSupport + #else + return false + #endif + } } extension QEMUTarget { diff --git a/Configuration/UTMQemuConfiguration+Arguments.swift b/Configuration/UTMQemuConfiguration+Arguments.swift index ca8dbb9ad..585a32213 100644 --- a/Configuration/UTMQemuConfiguration+Arguments.swift +++ b/Configuration/UTMQemuConfiguration+Arguments.swift @@ -273,6 +273,10 @@ import Foundation system.architecture.hasHypervisorSupport && qemu.hasHypervisor } + private var isTSOUsed: Bool { + system.architecture.hasTSOSupport && qemu.hasTSO + } + private var isUsbUsed: Bool { system.architecture.hasUsbSupport && system.target.hasUsbSupport && input.usbBusSupport != .disabled } @@ -283,7 +287,11 @@ import Foundation f(machineProperties) if isHypervisorUsed { f("-accel") - f("hvf") + "hvf" + if isTSOUsed { + "tso=on" + } + f() } else { f("-accel") "tcg" diff --git a/Configuration/UTMQemuConfigurationQEMU.swift b/Configuration/UTMQemuConfigurationQEMU.swift index c0982e174..e93ae4350 100644 --- a/Configuration/UTMQemuConfigurationQEMU.swift +++ b/Configuration/UTMQemuConfigurationQEMU.swift @@ -42,6 +42,9 @@ struct UTMQemuConfigurationQEMU: Codable { /// If true, use HVF hypervisor instead of TCG emulation. var hasHypervisor: Bool = false + /// If true, enable total store ordering. + var hasTSO: Bool = false + /// If true, attempt to sync RTC with the local time. var hasRTCLocalTime: Bool = false diff --git a/Platform/Shared/VMConfigQEMUView.swift b/Platform/Shared/VMConfigQEMUView.swift index af8bed018..4fdc16b38 100644 --- a/Platform/Shared/VMConfigQEMUView.swift +++ b/Platform/Shared/VMConfigQEMUView.swift @@ -82,6 +82,14 @@ struct VMConfigQEMUView: View { #endif Toggle("Use Hypervisor", isOn: $config.hasHypervisor) .help("Only available if host architecture matches the target. Otherwise, TCG emulation is used.") + .disabled(!system.architecture.hasHypervisorSupport) + #if os(iOS) + if config.hasHypervisor { + Toggle("Use TSO", isOn: $config.hasTSO) + .help("Only available when Hypervisor is used on supported hardware. TSO speeds up Intel emulation in the guest at the cost of decreased performance in general.") + .disabled(!system.architecture.hasTSOSupport) + } + #endif Toggle("Use local time for base clock", isOn: $config.hasRTCLocalTime) .help("If checked, use local time for RTC which is required for Windows. Otherwise, use UTC clock.") Toggle("Force PS/2 controller", isOn: $config.hasPS2Controller)