aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kvm/emulate-nested.c
diff options
context:
space:
mode:
authorOliver Upton <[email protected]>2025-07-08 17:25:11 +0000
committerOliver Upton <[email protected]>2025-07-08 18:36:31 +0000
commit77ee70a073575977b403e9add25f185d614217d8 (patch)
tree8a727a6e591ab61cc26230a9d8cd309ececbd642 /arch/arm64/kvm/emulate-nested.c
parentKVM: arm64: nv: Respect exception routing rules for SEAs (diff)
downloadkernel-77ee70a073575977b403e9add25f185d614217d8.tar.gz
kernel-77ee70a073575977b403e9add25f185d614217d8.zip
KVM: arm64: nv: Honor SError exception routing / masking
To date KVM has used HCR_EL2.VSE to track the state of a pending SError for the guest. With this bit set, hardware respects the EL1 exception routing / masking rules and injects the vSError when appropriate. This isn't correct for NV guests as hardware is oblivious to vEL2's intentions for SErrors. Better yet, with FEAT_NV2 the guest can change the routing behind our back as HCR_EL2 is redirected to memory. Cope with this mess by: - Using a flag (instead of HCR_EL2.VSE) to track the pending SError state when SErrors are unconditionally masked for the current context - Resampling the routing / masking of a pending SError on every guest entry/exit - Emulating exception entry when SError routing implies a translation regime change Reviewed-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
Diffstat (limited to 'arch/arm64/kvm/emulate-nested.c')
-rw-r--r--arch/arm64/kvm/emulate-nested.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 65a2471c5638..b01a482b41be 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -2714,6 +2714,9 @@ static void kvm_inject_el2_exception(struct kvm_vcpu *vcpu, u64 esr_el2,
case except_type_irq:
kvm_pend_exception(vcpu, EXCEPT_AA64_EL2_IRQ);
break;
+ case except_type_serror:
+ kvm_pend_exception(vcpu, EXCEPT_AA64_EL2_SERR);
+ break;
default:
WARN_ONCE(1, "Unsupported EL2 exception injection %d\n", type);
}
@@ -2821,3 +2824,14 @@ int kvm_inject_nested_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr)
vcpu_write_sys_reg(vcpu, FAR_EL2, addr);
return kvm_inject_nested_sync(vcpu, esr);
}
+
+int kvm_inject_nested_serror(struct kvm_vcpu *vcpu, u64 esr)
+{
+ /*
+ * Hardware sets up the EC field when propagating ESR as a result of
+ * vSError injection. Manually populate EC for an emulated SError
+ * exception.
+ */
+ esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR);
+ return kvm_inject_nested(vcpu, esr, except_type_serror);
+}