KVM: arm64: Only emulate an SError's entry for vCPUs with NV

kvm_inject_serror_esr() emulates an SError's exception entry when the
host's copy of PSTATE says SErrors are unmasked, although only NV needs
this, for a nested context whose guest hypervisor owns the vSError. A
protected vCPU's PSTATE lives at EL2, and the VMM can unmask SErrors in
the host's copy before the first run, so KVM emulates the entry on that
copy and the guest never takes the SError.

Emulate the entry only for a vCPU with NV, which protected VMs don't
support, and otherwise pend the SError through HCR_EL2.VSE, as KVM did
before commit ce66109cec ("KVM: arm64: nv: Take "masked" aborts to
EL2 when HCRX_EL2.TMEA is set").

Fixes: 872383bd12 ("KVM: arm64: Add per-EC entry/exit state marshalling for protected guests")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20261001142109.794CA1F000FF@smtp.kernel.org/
Suggested-by: Oliver Upton <oupton@kernel.org>
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
Reviewed-by: Oliver Upton <oupton@kernel.org>
Link: https://patch.msgid.link/20261007080833.371899-1-fuad.tabba@linux.dev
Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
Fuad Tabba 2026-10-07 09:08:33 +01:00 committed by Marc Zyngier
parent 61ace86519
commit 3bd107ed6b

View File

@ -371,15 +371,15 @@ int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr)
}
/*
* Emulate the exception entry if SErrors are unmasked. This is useful if
* the vCPU is in a nested context w/ vSErrors enabled then we've already
* delegated he hardware vSError context (i.e. HCR_EL2.VSE, VSESR_EL2,
* VDISR_EL2) to the guest hypervisor.
* With NV, emulate the exception entry if SErrors are unmasked: in a
* nested context with vSErrors enabled, the hardware vSError context
* (i.e. HCR_EL2.VSE, VSESR_EL2, VDISR_EL2) is delegated to the guest
* hypervisor. Otherwise, HCR_EL2.VSE delivers it once it is unmasked.
*
* As we're emulating the SError injection we need to explicitly populate
* ESR_ELx.EC because hardware will not do it on our behalf.
*/
if (!serror_is_masked(vcpu)) {
if (vcpu_has_nv(vcpu) && !serror_is_masked(vcpu)) {
pend_serror_exception(vcpu);
esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR) | ESR_ELx_IL;
vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));