]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
KVM: arm64: nv: Handle SEAs due to VNCR redirection
authorOliver Upton <oliver.upton@linux.dev>
Tue, 29 Jul 2025 18:23:42 +0000 (11:23 -0700)
committerOliver Upton <oliver.upton@linux.dev>
Tue, 5 Aug 2025 05:16:10 +0000 (22:16 -0700)
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: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250729182342.3281742-1-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/kvm_ras.h [deleted file]
arch/arm64/kvm/mmu.c
arch/arm64/kvm/nested.c

index ae563ebd6aee211af22185e9af1090ba64278d57..e4069f2ce64232616688a2e67e4ac4b93f71bffb 100644 (file)
@@ -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);
diff --git a/arch/arm64/include/asm/kvm_ras.h b/arch/arm64/include/asm/kvm_ras.h
deleted file mode 100644 (file)
index 9398ade..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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__ */
index 1c78864767c5ce73445421447d3690326cd26833..9a45daf817bfd2f5fe6d479720be19b43857f61c 100644 (file)
@@ -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);
 
index 74a2a94dad9bafbeb6c6a13ad006c7884eb2834c..64b980dbfbf82430c847baed650eef0270ca663c 100644 (file)
@@ -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)) {