Commit 69f8fe95 authored by Oliver Upton's avatar Oliver Upton
Browse files

KVM: arm64: nv: Handle SEAs due to VNCR redirection



System register accesses redirected to the VNCR page can also generate
external aborts just like any other form of memory access. Route to
kvm_handle_guest_sea() for potential APEI handling, falling back to a
vSError if the kernel didn't handle the abort.

Take the opportunity to throw out the useless kvm_ras.h which provided a
helper with a single callsite...

Cc: Jiaqi Yan <jiaqiyan@google.com>
Reviewed-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250729182342.3281742-1-oliver.upton@linux.dev


Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parent 07f557f6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu);
int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
			  phys_addr_t pa, unsigned long size, bool writable);

int kvm_handle_guest_sea(struct kvm_vcpu *vcpu);
int kvm_handle_guest_abort(struct kvm_vcpu *vcpu);

phys_addr_t kvm_mmu_get_httbr(void);

arch/arm64/include/asm/kvm_ras.h

deleted100644 → 0
+0 −25
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2018 - Arm Ltd */

#ifndef __ARM64_KVM_RAS_H__
#define __ARM64_KVM_RAS_H__

#include <linux/acpi.h>
#include <linux/errno.h>
#include <linux/types.h>

#include <asm/acpi.h>

/*
 * Was this synchronous external abort a RAS notification?
 * Returns '0' for errors handled by some RAS subsystem, or -ENOENT.
 */
static inline int kvm_handle_guest_sea(void)
{
	/* apei_claim_sea(NULL) expects to mask interrupts itself */
	lockdep_assert_irqs_enabled();

	return apei_claim_sea(NULL);
}

#endif /* __ARM64_KVM_RAS_H__ */
+17 −12
Original line number Diff line number Diff line
@@ -4,19 +4,20 @@
 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
 */

#include <linux/acpi.h>
#include <linux/mman.h>
#include <linux/kvm_host.h>
#include <linux/io.h>
#include <linux/hugetlb.h>
#include <linux/sched/signal.h>
#include <trace/events/kvm.h>
#include <asm/acpi.h>
#include <asm/pgalloc.h>
#include <asm/cacheflush.h>
#include <asm/kvm_arm.h>
#include <asm/kvm_mmu.h>
#include <asm/kvm_pgtable.h>
#include <asm/kvm_pkvm.h>
#include <asm/kvm_ras.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_emulate.h>
#include <asm/virt.h>
@@ -1811,6 +1812,19 @@ static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
	read_unlock(&vcpu->kvm->mmu_lock);
}

int kvm_handle_guest_sea(struct kvm_vcpu *vcpu)
{
	/*
	 * Give APEI the opportunity to claim the abort before handling it
	 * within KVM. apei_claim_sea() expects to be called with IRQs enabled.
	 */
	lockdep_assert_irqs_enabled();
	if (apei_claim_sea(NULL) == 0)
		return 1;

	return kvm_inject_serror(vcpu);
}

/**
 * kvm_handle_guest_abort - handles all 2nd stage aborts
 * @vcpu:	the VCPU pointer
@@ -1834,17 +1848,8 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
	gfn_t gfn;
	int ret, idx;

	/* Synchronous External Abort? */
	if (kvm_vcpu_abt_issea(vcpu)) {
		/*
		 * For RAS the host kernel may handle this abort.
		 * There is no need to pass the error into the guest.
		 */
		if (kvm_handle_guest_sea())
			return kvm_inject_serror(vcpu);

		return 1;
	}
	if (kvm_vcpu_abt_issea(vcpu))
		return kvm_handle_guest_sea(vcpu);

	esr = kvm_vcpu_get_esr(vcpu);

+3 −0
Original line number Diff line number Diff line
@@ -1289,6 +1289,9 @@ int kvm_handle_vncr_abort(struct kvm_vcpu *vcpu)

	WARN_ON_ONCE(!(esr & ESR_ELx_VNCR));

	if (kvm_vcpu_abt_issea(vcpu))
		return kvm_handle_guest_sea(vcpu);

	if (esr_fsc_is_permission_fault(esr)) {
		inject_vncr_perm(vcpu);
	} else if (esr_fsc_is_translation_fault(esr)) {