Skip to content

Commit 41011e2

Browse files
author
Marc Zyngier
committed
KVM: arm64: nv: Fix relative priorities of exceptions generated by ERETAx
ERETAx can fail in multiple ways: (1) ELR_EL2 points lalaland (2) we get a PAC failure (3) SPSR_EL2 has the wrong mode (1) is easy, as we just let the CPU do its thing and deliver an Instruction Abort. However, (2) and (3) are interesting, because the PAC failure priority is way below that of the Illegal Execution State exception. Which means that if we have detected a PAC failure (and that we have FPACCOMBINE), we must be careful to give priority to the Illegal Execution State exception, should one be pending. Solving this involves hoisting the SPSR calculation earlier and testing for the IL bit before injecting the FPAC exception. In the extreme case of a ERETAx returning to an invalid mode *and* failing its PAC check, we end up with an Instruction Abort (due to the new PC being mangled by the failed Auth) *and* PSTATE.IL being set. Which matches the requirements of the architecture. Whilst we're at it, remove a stale comment that states the obvious and only confuses the reader. Fixes: 213b3d1 ("KVM: arm64: nv: Handle ERETA[AB] instructions") Reviewed-by: Joey Gouly <[email protected]> Reviewed-by: Oliver Upton <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]>
1 parent c92e8b9 commit 41011e2

File tree

1 file changed

+11
-10
lines changed

1 file changed

+11
-10
lines changed

arch/arm64/kvm/emulate-nested.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2181,16 +2181,23 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
21812181
if (forward_traps(vcpu, HCR_NV))
21822182
return;
21832183

2184+
spsr = vcpu_read_sys_reg(vcpu, SPSR_EL2);
2185+
spsr = kvm_check_illegal_exception_return(vcpu, spsr);
2186+
21842187
/* Check for an ERETAx */
21852188
esr = kvm_vcpu_get_esr(vcpu);
21862189
if (esr_iss_is_eretax(esr) && !kvm_auth_eretax(vcpu, &elr)) {
21872190
/*
2188-
* Oh no, ERETAx failed to authenticate. If we have
2189-
* FPACCOMBINE, deliver an exception right away. If we
2190-
* don't, then let the mangled ELR value trickle down the
2191+
* Oh no, ERETAx failed to authenticate.
2192+
*
2193+
* If we have FPACCOMBINE and we don't have a pending
2194+
* Illegal Execution State exception (which has priority
2195+
* over FPAC), deliver an exception right away.
2196+
*
2197+
* Otherwise, let the mangled ELR value trickle down the
21912198
* ERET handling, and the guest will have a little surprise.
21922199
*/
2193-
if (kvm_has_pauth(vcpu->kvm, FPACCOMBINE)) {
2200+
if (kvm_has_pauth(vcpu->kvm, FPACCOMBINE) && !(spsr & PSR_IL_BIT)) {
21942201
esr &= ESR_ELx_ERET_ISS_ERETA;
21952202
esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_FPAC);
21962203
kvm_inject_nested_sync(vcpu, esr);
@@ -2201,17 +2208,11 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
22012208
preempt_disable();
22022209
kvm_arch_vcpu_put(vcpu);
22032210

2204-
spsr = __vcpu_sys_reg(vcpu, SPSR_EL2);
2205-
spsr = kvm_check_illegal_exception_return(vcpu, spsr);
22062211
if (!esr_iss_is_eretax(esr))
22072212
elr = __vcpu_sys_reg(vcpu, ELR_EL2);
22082213

22092214
trace_kvm_nested_eret(vcpu, elr, spsr);
22102215

2211-
/*
2212-
* Note that the current exception level is always the virtual EL2,
2213-
* since we set HCR_EL2.NV bit only when entering the virtual EL2.
2214-
*/
22152216
*vcpu_pc(vcpu) = elr;
22162217
*vcpu_cpsr(vcpu) = spsr;
22172218

0 commit comments

Comments
 (0)