mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
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 <maz@kernel.org> Link: https://lore.kernel.org/r/20250708172532.1699409-7-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user