Apple M4 removes FEAT_SSBS. However, older macOS releases do misbehave in such a configuration and do not boot.
Use private API to trap SCTLR_EL1 accesses through FGT. Signed-off-by: Mohamed Mediouni <[email protected]> --- accel/hvf/hvf-accel-ops.c | 4 +-- include/system/hvf_int.h | 4 +++ target/arm/hvf/hvf.c | 71 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c index 8b794c2d41..64d7afc3bf 100644 --- a/accel/hvf/hvf-accel-ops.c +++ b/accel/hvf/hvf-accel-ops.c @@ -152,8 +152,8 @@ static int hvf_init_vcpu(CPUState *cpu) sigdelset(&cpu->accel->unblock_ipi_mask, SIG_IPI); #ifdef __aarch64__ - r = hv_vcpu_create(&cpu->accel->fd, - (hv_vcpu_exit_t **)&cpu->accel->exit, NULL); + r = hvf_vcpu_create(&cpu->accel->fd, + (hv_vcpu_exit_t **)&cpu->accel->exit); #else r = hv_vcpu_create(&cpu->accel->fd, HV_VCPU_DEFAULT); #endif diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index a3b06a3e75..baee11d478 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -111,4 +111,8 @@ void hvf_arch_update_guest_debug(CPUState *cpu); */ bool hvf_arch_supports_guest_debug(void); +#ifdef __aarch64__ +hv_return_t hvf_vcpu_create(hv_vcpu_t* vcpu_ptr, hv_vcpu_exit_t ** exit); +#endif + #endif diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 0658a99a2d..99daba036b 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 <sys/sysctl.h> #include "system/address-spaces.h" #include "system/memory.h" @@ -138,11 +139,14 @@ static inline int hvf_arm_num_wrps(hv_vcpu_config_t config) return FIELD_EX64(val, ID_AA64DFR0, WRPS) + 1; } +void _hv_vcpu_config_set_fgt_enabled(hv_vcpu_config_t cfg, bool enabled); void hvf_arm_init_debug(void) { hv_vcpu_config_t config; config = hv_vcpu_config_create(); + _hv_vcpu_config_set_fgt_enabled(config, true); + max_hw_bps = hvf_arm_num_brps(config); hw_breakpoints = g_array_sized_new(true, true, sizeof(HWBreakpoint), max_hw_bps); @@ -292,6 +296,8 @@ void hvf_arm_init_debug(void) #define SYSREG_DBGWVR15_EL1 SYSREG(2, 0, 0, 15, 6) #define SYSREG_DBGWCR15_EL1 SYSREG(2, 0, 0, 15, 7) +#define SYSREG_SCTLR_EL1 SYSREG(3, 0, 1, 0, 0) + #define WFX_IS_WFE (1 << 0) #define TMR_CTL_ENABLE (1 << 0) @@ -1320,6 +1326,9 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint64_t *val) case SYSREG_DBGWCR15_EL1: *val = env->cp15.dbgwcr[SYSREG_CRM(reg)]; return 0; + case SYSREG_SCTLR_EL1: + *val = env->cp15.sctlr_el[1] | SCTLR_DSSBS_64; + return 0; default: if (is_id_sysreg(reg)) { /* ID system registers read as RES0 */ @@ -1643,6 +1652,10 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val) case SYSREG_DBGWCR15_EL1: env->cp15.dbgwcr[SYSREG_CRM(reg)] = val; return 0; + case SYSREG_SCTLR_EL1: + env->cp15.sctlr_el[1] = val; + assert_hvf_ok(hv_vcpu_set_sys_reg(cpu->accel->fd, HV_SYS_REG_SCTLR_EL1, val & ~SCTLR_DSSBS_64)); + return 0; } cpu_synchronize_state(cpu); @@ -2244,3 +2257,61 @@ bool hvf_arch_supports_guest_debug(void) { return true; } + +/* + * Apple M4 removes FEAT_SSBS. However, older macOS releases + * do misbehave in such a configuration and do not boot. + * + * Using private API to trap SCTLR_EL1 accesses through FGT. + */ + +void _hv_vcpu_config_set_fgt_enabled(hv_vcpu_config_t cfg, bool enabled); +#define HV_CONTROL_FIELD_HFGRTR 0xb +#define HV_CONTROL_FIELD_HFGWTR 0xc +hv_return_t _hv_vcpu_get_control_field(hv_vcpu_t vcpu, int field, uint64_t* value); +hv_return_t _hv_vcpu_set_control_field(hv_vcpu_t vcpu, int field, uint64_t value); + +static bool hvf_is_ssbs_implemented(void) { + int has_ssbs = -1; + size_t has_ssbs_sz = sizeof(has_ssbs); + if (sysctlbyname("hw.optional.arm.FEAT_SSBS", &has_ssbs, &has_ssbs_sz, NULL, 0) == -1) { + has_ssbs = 0; + } + return has_ssbs; +} + +hv_return_t hvf_vcpu_create(hv_vcpu_t* vcpu_ptr, hv_vcpu_exit_t ** exit) +{ + hv_return_t r; + hv_vcpu_t vcpu; + uint64_t hfgwtr_el1, hfgrtr_el1; + + hv_vcpu_config_t config; + config = hv_vcpu_config_create(); + if (!hvf_is_ssbs_implemented()) { + _hv_vcpu_config_set_fgt_enabled(config, true); + } + + r = hv_vcpu_create(&vcpu, (hv_vcpu_exit_t **)exit, config); + + if (hvf_is_ssbs_implemented()) { + return r; + } + + assert_hvf_ok(_hv_vcpu_get_control_field(vcpu, HV_CONTROL_FIELD_HFGWTR,&hfgwtr_el1)); + assert_hvf_ok(_hv_vcpu_set_control_field(vcpu, HV_CONTROL_FIELD_HFGWTR, + hfgwtr_el1 | R_HFGWTR_EL2_SCTLR_EL1_MASK)); + assert_hvf_ok(_hv_vcpu_get_control_field(vcpu, HV_CONTROL_FIELD_HFGWTR, + &hfgwtr_el1)); + + assert_hvf_ok(_hv_vcpu_get_control_field(vcpu, HV_CONTROL_FIELD_HFGRTR, + &hfgrtr_el1)); + assert_hvf_ok(_hv_vcpu_set_control_field(vcpu, HV_CONTROL_FIELD_HFGRTR, + hfgrtr_el1 | R_HFGRTR_EL2_SCTLR_EL1_MASK)); + assert_hvf_ok(_hv_vcpu_get_control_field(vcpu, HV_CONTROL_FIELD_HFGRTR, + &hfgrtr_el1)); + + *vcpu_ptr = vcpu; + + return r; +} -- 2.50.1 (Apple Git-155)
