Skip to contentSkip to conversation

KVM: arm64: Use shadow SPSR_EL1 when injecting exceptions on !VHE

PATCH In review Marc Zyngier 2 participants 2 messages Jan 21, 2022 – Jan 24, 2022

Subsystems (4)
lore
Share & tools
lore

Marc Zyngier

author maintainer
#0 lore raw

PATCH 1/1 KVM: arm64: Use shadow SPSR_EL1 when injecting exceptions on !VHE

Injecting an exception into a guest with non-VHE is risky business. Instead of writing in the shadow register for the switch code to restore it, we override the CPU register instead. Which gets overriden a few instructions later by said restore code.

The result is that although the guest correctly gets the exception, it will return to the original context in some random state, depending on what was there the first place... Boo.

Fix the issue by writing to the shadow register. The original code is absolutely fine on VHE, as the state is already loaded, and writing to the shadow register in that case would actually be a bug.

Fixes bb666c472ca2 ("KVM: arm64: Inject AArch64 exceptions from HYP")
---
 arch/arm64/kvm/hyp/exception.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
arch/arm64/kvm/hyp/exception.c +4 -1
index 0418399e0a20..c5d009715402 100644
@@ -38,7 +38,10 @@ static inline void __vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
 
 static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, u64 val)
 {
-	write_sysreg_el1(val, SYS_SPSR);
+	if (has_vhe())
+		write_sysreg_el1(val, SYS_SPSR);
+	else
+		__vcpu_sys_reg(vcpu, SPSR_EL1) = val;
 }
 
 static void __vcpu_write_spsr_abt(struct kvm_vcpu *vcpu, u64 val)
Signature · 1 line
2.34.1
Reviewed-by on v1 1/1
#1 lore raw

Hi Marc,

Quoted 5 lines · Marc Zyngier

Injecting an exception into a guest with non-VHE is risky business. Instead of writing in the shadow register for the switch code to restore it, we override the CPU register instead. Which gets overriden a few instructions later by said restore code.

I see that in __sysreg_restore_el1_state(), which as you said is called after __vcpu_write_spsr().

Quoted 7 lines

The result is that although the guest correctly gets the exception, it will return to the original context in some random state, depending on what was there the first place... Boo.

Fix the issue by writing to the shadow register. The original code is absolutely fine on VHE, as the state is already loaded, and writing to the shadow register in that case would actually be a bug.

Which happens via kvm_vcpu_load_sysregs_vhe() calling __sysreg_restore_el1_state() before __vcpu_write_spsr() in this case.

Cheers,
/fuad

Quoted 26 lines
Fixes bb666c472ca2 ("KVM: arm64: Inject AArch64 exceptions from HYP")
---
 arch/arm64/kvm/hyp/exception.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
arch/arm64/kvm/hyp/exception.c +4 -2
index 0418399e0a20..c5d009715402 100644
@@ -38,7 +38,10 @@ static inline void __vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
 
 static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, u64 val)
 {
-       write_sysreg_el1(val, SYS_SPSR);
+       if (has_vhe())
+               write_sysreg_el1(val, SYS_SPSR);
+       else
+               __vcpu_sys_reg(vcpu, SPSR_EL1) = val;
 }
 
 static void __vcpu_write_spsr_abt(struct kvm_vcpu *vcpu, u64 val)
--

2.34.1