@@ -59,5 +59,6 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
#endif /* __ASSEMBLY__ */
int handle_guest_sea(unsigned long addr, unsigned int esr);
+int handle_guest_sei(unsigned long addr, unsigned int esr);
#endif /* __ASM_SYSTEM_MISC_H */
@@ -618,6 +618,20 @@ const char *esr_get_class_string(u32 esr)
DEFINE_PER_CPU(int, sei_in_process);
/*
+ * Handle asynchronous SError interrupt that occur in a guest kernel.
+ */
+int handle_guest_sei(unsigned long addr, unsigned int esr)
+{
+ int ret = -ENOENT;
+
+ if(IS_ENABLED(CONFIG_ACPI_APEI_SEI)) {
+ ret = ghes_notify_sei();
+ }
+
+ return ret;
+}
+
+/*
* bad_mode handles the impossible case in the exception vector. This is always
* fatal.
*/
@@ -28,6 +28,7 @@
#include <asm/kvm_emulate.h>
#include <asm/kvm_mmu.h>
#include <asm/kvm_psci.h>
+#include <asm/system_misc.h>
#define CREATE_TRACE_POINTS
#include "trace.h"
@@ -177,6 +178,23 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
return arm_exit_handlers[hsr_ec];
}
+static int kvm_handle_guest_sei(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ unsigned long fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
+
+ if (handle_guest_sei((unsigned long)fault_ipa,
+ kvm_vcpu_get_hsr(vcpu))) {
+ kvm_err("Failed to handle guest SEI, FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
+ kvm_vcpu_trap_get_class(vcpu),
+ (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
+ (unsigned long)kvm_vcpu_get_hsr(vcpu));
+
+ kvm_inject_vabt(vcpu);
+ }
+
+ return 0;
+}
+
/*
* Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
* proper exit to userspace.
@@ -200,7 +218,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
*vcpu_pc(vcpu) -= adj;
}
- kvm_inject_vabt(vcpu);
+ kvm_handle_guest_sei(vcpu, run);
return 1;
}
@@ -210,7 +228,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
case ARM_EXCEPTION_IRQ:
return 1;
case ARM_EXCEPTION_EL1_SERROR:
- kvm_inject_vabt(vcpu);
+ kvm_handle_guest_sei(vcpu, run);
return 1;
case ARM_EXCEPTION_TRAP:
/*
Add ghes handling for SEI so that the host kernel could parse and report detailed error information for SEI which occur in the guest kernel. If there were no CPER records, (or the system doesn't support SEI as a GHES notification mechanism), then yes we should still call kvm_inject_vabt(). Signed-off-by: Xie XiuQi <xiexiuqi@huawei.com> --- arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kernel/traps.c | 14 ++++++++++++++ arch/arm64/kvm/handle_exit.c | 22 ++++++++++++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-)