From: Fuad Tabba Date: Wed, 17 Jun 2026 14:49:07 +0000 (+0100) Subject: KVM: arm64: nv: Fix PSTATE construction on illegal exception return X-Git-Tag: v7.2-rc4~28^2~5^2~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0e8e955b9bcf84a70f20079390e19971fec1586d;p=thirdparty%2Fkernel%2Flinux.git KVM: arm64: nv: Fix PSTATE construction on illegal exception return kvm_check_illegal_exception_return() sourced the flags {N,Z,C,V} and masks {D,A,I,F} of the resulting PSTATE from the current PSTATE, but R_VWJHB takes them from the SPSR being returned to and leaves PSTATE.{EL,SP,nRW} (and EXLOCK when FEAT_GCS) unchanged. PAN, ALLINT and PM were not applied at all. Build the PSTATE by taking those fields from the SPSR while preserving EL, SP, nRW and EXLOCK from the current PSTATE, then set IL. Fixes: 47f3a2fc765a ("KVM: arm64: nv: Support virtual EL2 exceptions") Suggested-by: Marc Zyngier Link: https://lore.kernel.org/all/86wlvxs5r0.wl-maz@kernel.org/ Signed-off-by: Fuad Tabba Link: https://patch.msgid.link/20260617144907.2972095-1-tabba@google.com [maz: tidied things a bit] Signed-off-by: Marc Zyngier --- diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c index 76c3e6c1144c..96ebe7e3b408 100644 --- a/arch/arm64/kvm/emulate-nested.c +++ b/arch/arm64/kvm/emulate-nested.c @@ -2746,17 +2746,33 @@ static u64 kvm_check_illegal_exception_return(struct kvm_vcpu *vcpu, u64 spsr) (spsr & PSR_MODE32_BIT) || (vcpu_el2_tge_is_set(vcpu) && (mode == PSR_MODE_EL1t || mode == PSR_MODE_EL1h))) { + u64 mask; + /* - * The guest is playing with our nerves. Preserve EL, SP, - * masks, flags from the existing PSTATE, and set IL. - * The HW will then generate an Illegal State Exception - * immediately after ERET. + * On an illegal exception return, the flags and masks are + * taken from the SPSR while PSTATE.{EL,SP,nRW} and, if + * FEAT_GCS, PSTATE.EXLOCK are unchanged (R_VWJHB). Set IL + * so the HW generates an Illegal State Exception right + * after ERET. */ - spsr = *vcpu_cpsr(vcpu); + mask = PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | + PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT; + + if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR1_EL1, PAN, IMP)) + mask |= PSR_PAN_BIT; + if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, NMI, IMP)) + mask |= ALLINT_ALLINT; + /* FEAT_SPE_EXC and FEAT_TRBE_EXC also gate PSTATE.PM one day... */ + if (kvm_has_feat(vcpu->kvm, ID_AA64DFR1_EL1, EBEP, IMP)) + mask |= BIT_ULL(32); /* SPSR_ELx.PM */ + + spsr &= mask; + + mask = PSR_MODE_MASK | PSR_MODE32_BIT; + if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, GCS, IMP)) + mask |= BIT_ULL(34); /* PSTATE.EXLOCK */ - spsr &= (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | - PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT | - PSR_MODE_MASK | PSR_MODE32_BIT); + spsr |= *vcpu_cpsr(vcpu) & mask; spsr |= PSR_IL_BIT; }