diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S --- a/sys/arm64/arm64/locore.S +++ b/sys/arm64/arm64/locore.S @@ -263,6 +263,10 @@ ldr x2, =(HCR_RW | HCR_APK | HCR_API) msr hcr_el2, x2 + /* Stash value of HCR_EL2 for later */ + isb + mrs x4, hcr_el2 + /* Load the Virtualization Process ID Register */ mrs x2, midr_el1 msr vpidr_el2, x2 @@ -275,8 +279,22 @@ ldr x2, .Lsctlr_res1 msr sctlr_el1, x2 + /* + * On some hardware, e.g., Apple M1, we can't clear E2H, so make sure we + * don't trap to EL2 for SIMD register usage to have at least a + * minimally usable system. + */ + tbnz x4, #HCR_E2H_SHIFT, hostmode + /* HCR_EL2.E2H == 0 */ /* Don't trap to EL2 for exceptions */ mov x2, #CPTR_RES1 + b setcptr + +hostmode: + /* HCR_EL2.E2H == 1 */ + mov x2, #CPTR_FPEN + +setcptr: msr cptr_el2, x2 /* Don't trap to EL2 for CP15 traps */ diff --git a/sys/arm64/include/hypervisor.h b/sys/arm64/include/hypervisor.h --- a/sys/arm64/include/hypervisor.h +++ b/sys/arm64/include/hypervisor.h @@ -45,9 +45,13 @@ #define CNTHCTL_EL1PCTEN (1 << 0) /*Allow EL0/1 physical counter access*/ /* CPTR_EL2 - Architecture feature trap register */ +/* Valid if HCR_EL2.E2H == 0 */ #define CPTR_RES0 0x7fefc800 #define CPTR_RES1 0x000033ff #define CPTR_TFP 0x00000400 +/* Valid if HCR_EL2.E2H == 1 */ +#define CPTR_FPEN 0x00300000 +/* Unconditionally valid */ #define CPTR_TTA 0x00100000 #define CPTR_TCPAC 0x80000000 @@ -88,7 +92,8 @@ #define HCR_RW (UL(0x1) << 31) #define HCR_CD (UL(0x1) << 32) #define HCR_ID (UL(0x1) << 33) -#define HCR_E2H (UL(0x1) << 34) +#define HCR_E2H_SHIFT 34 +#define HCR_E2H (UL(0x1) << HCR_E2H_SHIFT) #define HCR_TLOR (UL(0x1) << 35) #define HCR_TERR (UL(0x1) << 36) #define HCR_TEA (UL(0x1) << 37)