]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps
authorOliver Upton <oliver.upton@linux.dev>
Wed, 5 Mar 2025 20:26:36 +0000 (12:26 -0800)
committerOliver Upton <oliver.upton@linux.dev>
Tue, 11 Mar 2025 19:54:29 +0000 (12:54 -0700)
Apple M* CPUs provide an IMPDEF trap for PMUv3 sysregs, where ESR_EL2.EC
is a reserved value (0x3F) and a sysreg-like ISS is reported in
AFSR1_EL2.

Compute a synthetic ESR for these PMUv3 traps, giving the illusion of
something architectural to the rest of KVM.

Tested-by: Janne Grunau <j@jannau.net>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250305202641.428114-10-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/hyp/vhe/switch.c
arch/arm64/tools/cpucaps

index 647737d6e8d0b5f41b2a8d25a06265e4703126b3..731a0378ed1328c6929c9b82e5d7fbc6e4b2b0d4 100644 (file)
@@ -527,6 +527,25 @@ static bool kvm_hyp_handle_sysreg_vhe(struct kvm_vcpu *vcpu, u64 *exit_code)
        return kvm_hyp_handle_sysreg(vcpu, exit_code);
 }
 
+static bool kvm_hyp_handle_impdef(struct kvm_vcpu *vcpu, u64 *exit_code)
+{
+       u64 iss;
+
+       if (!cpus_have_final_cap(ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS))
+               return false;
+
+       /*
+        * Compute a synthetic ESR for a sysreg trap. Conveniently, AFSR1_EL2
+        * is populated with a correct ISS for a sysreg trap. These fruity
+        * parts are 64bit only, so unconditionally set IL.
+        */
+       iss = ESR_ELx_ISS(read_sysreg_s(SYS_AFSR1_EL2));
+       vcpu->arch.fault.esr_el2 = FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SYS64) |
+                                  FIELD_PREP(ESR_ELx_ISS_MASK, iss) |
+                                  ESR_ELx_IL;
+       return false;
+}
+
 static const exit_handler_fn hyp_exit_handlers[] = {
        [0 ... ESR_ELx_EC_MAX]          = NULL,
        [ESR_ELx_EC_CP15_32]            = kvm_hyp_handle_cp15_32,
@@ -538,6 +557,9 @@ static const exit_handler_fn hyp_exit_handlers[] = {
        [ESR_ELx_EC_WATCHPT_LOW]        = kvm_hyp_handle_watchpt_low,
        [ESR_ELx_EC_ERET]               = kvm_hyp_handle_eret,
        [ESR_ELx_EC_MOPS]               = kvm_hyp_handle_mops,
+
+       /* Apple shenanigans */
+       [0x3F]                          = kvm_hyp_handle_impdef,
 };
 
 static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
index ee4316cb36905f993828ca1333f1c5c2b3c39cba..772c1b008e437ed34cedb1c0f663c4dcea8f6759 100644 (file)
@@ -105,6 +105,7 @@ WORKAROUND_CAVIUM_TX2_219_TVM
 WORKAROUND_CLEAN_CACHE
 WORKAROUND_DEVICE_LOAD_ACQUIRE
 WORKAROUND_NVIDIA_CARMEL_CNP
+WORKAROUND_PMUV3_IMPDEF_TRAPS
 WORKAROUND_QCOM_FALKOR_E1003
 WORKAROUND_QCOM_ORYON_CNTVOFF
 WORKAROUND_REPEAT_TLBI