diff mbox series

[v1,2/6] KVM: arm64: Set FnV for VCPU when FAR_EL2 is invalid

Message ID 20250505161412.1926643-3-jiaqiyan@google.com
State New
Headers show
Series VMM can handle guest SEA via KVM_EXIT_ARM_SEA | expand

Commit Message

Jiaqi Yan May 5, 2025, 4:14 p.m. UTC
Certain microarchitectures (e.g. Neoverse V2) do not keep track of
the faulting address for a memory load that consumes poisoned data
and results in a synchronous external abort (SEA). This means the
faulting guest physical address is unavailable when KVM handles such
SEA in EL2, and FAR_EL2 just holds a garbage value.

In case VMM later asks KVM to synchronously inject a SEA into the
guest, KVM should set FnV bit
- in VCPU's ESR_EL1 to let guest kernel know that FAR_EL1 is invalid
  and holds garbage value
- in VCPU's ESR_EL2 to let nested virtualization know that FAR_EL2
  is invalid and holds garbage value

Signed-off-by: Jiaqi Yan <jiaqiyan@google.com>
---
 arch/arm64/kvm/inject_fault.c | 3 +++
 1 file changed, 3 insertions(+)

Comments

Marc Zyngier May 16, 2025, 3:33 p.m. UTC | #1
On Mon, 05 May 2025 17:14:08 +0100,
Jiaqi Yan <jiaqiyan@google.com> wrote:
> 
> Certain microarchitectures (e.g. Neoverse V2) do not keep track of
> the faulting address for a memory load that consumes poisoned data
> and results in a synchronous external abort (SEA). This means the
> faulting guest physical address is unavailable when KVM handles such
> SEA in EL2, and FAR_EL2 just holds a garbage value.

I don't understand. FAR_ELx holds a *virtual* address, and never a
physical address (that'd be PFAR_ELx).

> 
> In case VMM later asks KVM to synchronously inject a SEA into the
> guest, KVM should set FnV bit
> - in VCPU's ESR_EL1 to let guest kernel know that FAR_EL1 is invalid
>   and holds garbage value
> - in VCPU's ESR_EL2 to let nested virtualization know that FAR_EL2
>   is invalid and holds garbage value
>
> Signed-off-by: Jiaqi Yan <jiaqiyan@google.com>
> ---
>  arch/arm64/kvm/inject_fault.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
> index a640e839848e6..b4f9a09952ead 100644
> --- a/arch/arm64/kvm/inject_fault.c
> +++ b/arch/arm64/kvm/inject_fault.c
> @@ -81,6 +81,9 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
>  	if (!is_iabt)
>  		esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
>  
> +	if (!kvm_vcpu_sea_far_valid(vcpu))
> +		esr |= ESR_ELx_FnV;
> +

I don't understand what this has anything to do with the uarch details
you talk about in the commit message. If the VMM inject an exception,
surely it has populated the exception context itself. I don't even see
how we'd end-up here (__kvm_arm_vcpu_set_events? seems unlikely).

	M.
diff mbox series

Patch

diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index a640e839848e6..b4f9a09952ead 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -81,6 +81,9 @@  static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
 	if (!is_iabt)
 		esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
 
+	if (!kvm_vcpu_sea_far_valid(vcpu))
+		esr |= ESR_ELx_FnV;
+
 	esr |= ESR_ELx_FSC_EXTABT;
 
 	if (match_target_el(vcpu, unpack_vcpu_flag(EXCEPT_AA64_EL1_SYNC))) {