| From 2d44c06ef2d02afa027298b709db3ff01ee53b52 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 16 Nov 2021 10:20:06 +0000 |
| Subject: KVM: arm64: Save PSTATE early on exit |
| |
| From: Marc Zyngier <maz@kernel.org> |
| |
| [ Upstream commit 83bb2c1a01d7127d5adc7d69d7aaa3f7072de2b4 ] |
| |
| In order to be able to use primitives such as vcpu_mode_is_32bit(), |
| we need to synchronize the guest PSTATE. However, this is currently |
| done deep into the bowels of the world-switch code, and we do have |
| helpers evaluating this much earlier (__vgic_v3_perform_cpuif_access |
| and handle_aarch32_guest, for example). |
| |
| Move the saving of the guest pstate into the early fixups, which |
| cures the first issue. The second one will be addressed separately. |
| |
| Tested-by: Fuad Tabba <tabba@google.com> |
| Reviewed-by: Fuad Tabba <tabba@google.com> |
| Signed-off-by: Marc Zyngier <maz@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/arm64/kvm/hyp/include/hyp/switch.h | 6 ++++++ |
| arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 7 ++++++- |
| 2 files changed, 12 insertions(+), 1 deletion(-) |
| |
| diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h |
| index a0e78a6027be0..c75e84489f57b 100644 |
| --- a/arch/arm64/kvm/hyp/include/hyp/switch.h |
| +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h |
| @@ -416,6 +416,12 @@ static inline bool __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) |
| */ |
| static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) |
| { |
| + /* |
| + * Save PSTATE early so that we can evaluate the vcpu mode |
| + * early on. |
| + */ |
| + vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR); |
| + |
| if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) |
| vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); |
| |
| diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h |
| index de7e14c862e6c..7ecca8b078519 100644 |
| --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h |
| +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h |
| @@ -70,7 +70,12 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) |
| static inline void __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) |
| { |
| ctxt->regs.pc = read_sysreg_el2(SYS_ELR); |
| - ctxt->regs.pstate = read_sysreg_el2(SYS_SPSR); |
| + /* |
| + * Guest PSTATE gets saved at guest fixup time in all |
| + * cases. We still need to handle the nVHE host side here. |
| + */ |
| + if (!has_vhe() && ctxt->__hyp_running_vcpu) |
| + ctxt->regs.pstate = read_sysreg_el2(SYS_SPSR); |
| |
| if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN)) |
| ctxt_sys_reg(ctxt, DISR_EL1) = read_sysreg_s(SYS_VDISR_EL2); |
| -- |
| 2.33.0 |
| |