mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
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: 47f3a2fc76 ("KVM: arm64: nv: Support virtual EL2 exceptions")
Suggested-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/all/86wlvxs5r0.wl-maz@kernel.org/
Signed-off-by: Fuad Tabba <tabba@google.com>
Link: https://patch.msgid.link/20260617144907.2972095-1-tabba@google.com
[maz: tidied things a bit]
Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
ec40342aac
commit
0e8e955b9b
|
|
@ -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))) {
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
spsr = *vcpu_cpsr(vcpu);
|
||||
u64 mask;
|
||||
|
||||
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);
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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 |= *vcpu_cpsr(vcpu) & mask;
|
||||
spsr |= PSR_IL_BIT;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user