summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWeiming Shi <bestswngs@gmail.com>2026-06-17 12:08:21 +0800
committerMarc Zyngier <maz@kernel.org>2026-06-17 12:49:11 +0100
commitff1022c3de46753eb7eba2f6efd990569e66ff95 (patch)
treeeffc0606df41f27698ec4614c47c00ab99d536fd
parent0074b82cdfcb5fd13710a0ac308ade68ac6f6fbe (diff)
downloadlinux-stable-ff1022c3de46753eb7eba2f6efd990569e66ff95.tar.gz
linux-stable-ff1022c3de46753eb7eba2f6efd990569e66ff95.zip
KVM: arm64: nv: Fix SPSR_EL2 restore in kvm_hyp_handle_mops()
kvm_hyp_handle_mops() resets the single-step state machine as part of rewinding state for a MOPS exception by modifying vcpu_cpsr() and writing the result directly into hardware. In the case of nested virtualization, vcpu_cpsr() is a synthetic value such that the rest of KVM can deal with vEL2 cleanly. That means the value requires translation before being written into hardware, which is unfortunately missing from the MOPS handler. Fix it by directly modifying SPSR_EL2 and avoiding the synthetic state altogether, which will be resynchronized on the next 'full' exit back to KVM. Fixes: 2de451a329cf ("KVM: arm64: Add handler for MOPS exceptions") Reported-by: Zhong Wang <wangzhong.c0ss4ck@bytedance.com> Reported-by: Xuanqing Shi <shixuanqing.11@bytedance.com> Link: https://lore.kernel.org/all/ajE4lHQevXNHpl1M@Air.local/ Cc: stable@vger.kernel.org Signed-off-by: Weiming Shi <bestswngs@gmail.com> Link: https://patch.msgid.link/20260617040820.2194831-2-bestswngs@gmail.com Signed-off-by: Marc Zyngier <maz@kernel.org>
-rw-r--r--arch/arm64/kvm/hyp/include/hyp/switch.h9
1 files changed, 6 insertions, 3 deletions
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 161bb2a3e1d9..d56371b189bf 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -446,16 +446,19 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
{
+ u64 spsr;
+
*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
write_sysreg_el2(*vcpu_pc(vcpu), SYS_ELR);
/*
* Finish potential single step before executing the prologue
- * instruction.
+ * instruction. Modify the hardware SPSR_EL2 directly, as vcpu_cpsr()
+ * may hold a synthetic (vEL2) value for a guest hypervisor.
*/
- *vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
- write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
+ spsr = read_sysreg_el2(SYS_SPSR);
+ write_sysreg_el2(spsr & ~DBG_SPSR_SS, SYS_SPSR);
return true;
}