summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortabba@google.com <tabba@google.com>2026-05-31 18:45:48 +0300
committerMarc Zyngier <maz@kernel.org>2026-06-07 16:34:53 +0300
commit832dfa237f836549b202d3eebc0bc29b8a719608 (patch)
treecedb2d19be2c91da469901775f79ffd990f9394c
parent8cc8bbbfab14c22c5551d0dd19b208a44b141c76 (diff)
downloadlinux-832dfa237f836549b202d3eebc0bc29b8a719608.tar.xz
KVM: arm64: Flush HCR_EL2.VSE to deliver SErrors to pKVM guests
With pKVM enabled, the host injects a virtual SError by setting HCR_EL2.VSE on its vCPU copy, but flush_hyp_vcpu() only flows TWI/TWE into the hyp vCPU that runs, so VSE never reaches it and a deferred (masked) SError is never delivered. VSE is a host-owned injection control, not a trap-configuration bit, so restricting the host's trap-register values should not have dropped it. Flow it on entry; sync_hyp_vcpu() already copies hcr_el2 back, so delivery is reflected to the host. THis makes it consistent with the existing forwarding of VSESR_EL2, which qualifies the Serror. Fixes: b56680de9c648 ("KVM: arm64: Initialize trap register values in hyp in pKVM") Reported-by: Sashiko (local):gemini-3.1-pro Signed-off-by: Fuad Tabba <tabba@google.com> Reviewed-by: Oliver Upton <oupton@kernel.org> Link: https://patch.msgid.link/20260531154548.1505799-1-tabba@google.com Signed-off-by: Marc Zyngier <maz@kernel.org>
-rw-r--r--arch/arm64/kvm/hyp/nvhe/hyp-main.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index a0da08caa6c2..1d01c6e547f5 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -135,9 +135,14 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL;
hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
- hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE);
+ /*
+ * HCR_EL2.VSE is host-owned (a pending virtual SError to inject), not a
+ * trap-control bit, so it must flow to the hyp vCPU alongside TWI/TWE
+ * for the vSError to be delivered. sync_hyp_vcpu() reflects it back.
+ */
+ hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE | HCR_VSE);
hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) &
- (HCR_TWI | HCR_TWE);
+ (HCR_TWI | HCR_TWE | HCR_VSE);
hyp_vcpu->vcpu.arch.iflags = host_vcpu->arch.iflags;