From patchwork Tue Oct 17 14:14:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dongjiu Geng X-Patchwork-Id: 10012121 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5054B601E7 for ; Tue, 17 Oct 2017 13:52:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4885127FE4 for ; Tue, 17 Oct 2017 13:52:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3CCEF288E7; Tue, 17 Oct 2017 13:52:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 86B48288CB for ; Tue, 17 Oct 2017 13:52:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1762600AbdJQNvp (ORCPT ); Tue, 17 Oct 2017 09:51:45 -0400 Received: from szxga05-in.huawei.com ([45.249.212.191]:8507 "EHLO szxga05-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752559AbdJQNuP (ORCPT ); Tue, 17 Oct 2017 09:50:15 -0400 Received: from 172.30.72.59 (EHLO DGGEMS401-HUB.china.huawei.com) ([172.30.72.59]) by dggrg05-dlp.huawei.com (MOS 4.4.6-GA FastPath queued) with ESMTP id DJH70333; Tue, 17 Oct 2017 21:49:02 +0800 (CST) Received: from linux.huawei.com (10.67.187.203) by DGGEMS401-HUB.china.huawei.com (10.3.19.201) with Microsoft SMTP Server id 14.3.301.0; Tue, 17 Oct 2017 21:48:49 +0800 From: Dongjiu Geng To: , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 4/4] arm64: kvm: handle SEI notification for guest Date: Tue, 17 Oct 2017 22:14:49 +0800 Message-ID: <1508249689-10350-5-git-send-email-gengdongjiu@huawei.com> X-Mailer: git-send-email 1.7.7 In-Reply-To: <1508249689-10350-1-git-send-email-gengdongjiu@huawei.com> References: <1508249689-10350-1-git-send-email-gengdongjiu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.187.203] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020206.59E60A4F.012E, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: a2f334fd14825db03da674dfe306db53 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP when KVM received SError, it firstly classified the error according to [ESR_ELx.AET]. If the SEI is Uncategorized or IMPLEMENTATION DEFINED directly inject virtual SError with IMPLEMENTATION DEFINED syndrome. If the SError error is not propagated, then let host to handle it. Because usually the address recorded by APEI table is not accurate, so can not identify the address to hwpoison memory and can not notify guest to do the recovery, so at the same time, let user space specify a valid ESR and inject virtual SError. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- arch/arm64/include/asm/esr.h | 15 +++++++++ arch/arm64/include/asm/kvm_asm.h | 1 + arch/arm64/include/asm/kvm_host.h | 6 ++++ arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kvm/handle_exit.c | 62 +++++++++++++++++++++++++++++++++--- arch/arm64/mm/fault.c | 16 ++++++++++ 6 files changed, 97 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 8cabd57..e5d23a8f 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -95,6 +95,7 @@ #define ESR_ELx_FSC_ACCESS (0x08) #define ESR_ELx_FSC_FAULT (0x04) #define ESR_ELx_FSC_PERM (0x0C) +#define ESR_ELx_FSC_SERROR (0x11) /* ISS field definitions for Data Aborts */ #define ESR_ELx_ISV (UL(1) << 24) @@ -107,6 +108,20 @@ #define ESR_ELx_AR (UL(1) << 14) #define ESR_ELx_CM (UL(1) << 8) +/* ISS field definitions for SError interrupt */ +#define ESR_ELx_AET_SHIFT (10) +#define ESR_ELx_AET (UL(0x7) << ESR_ELx_AET_SHIFT) +/* Uncontainable error */ +#define ESR_ELx_AET_UC (UL(0) << ESR_ELx_AET_SHIFT) +/* Unrecoverable error */ +#define ESR_ELx_AET_UEU (UL(1) << ESR_ELx_AET_SHIFT) +/* Restartable error */ +#define ESR_ELx_AET_UEO (UL(2) << ESR_ELx_AET_SHIFT) +/* Recoverable error */ +#define ESR_ELx_AET_UER (UL(3) << ESR_ELx_AET_SHIFT) +/* Corrected */ +#define ESR_ELx_AET_CE (UL(6) << ESR_ELx_AET_SHIFT) + /* ISS field definitions for exceptions taken in to Hyp */ #define ESR_ELx_CV (UL(1) << 24) #define ESR_ELx_COND_SHIFT (20) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 26a64d0..d167ed3 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -27,6 +27,7 @@ #define ARM_EXCEPTION_IRQ 0 #define ARM_EXCEPTION_EL1_SERROR 1 #define ARM_EXCEPTION_TRAP 2 + /* The hyp-stub will return this for any kvm_call_hyp() call */ #define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 1a0c07e..c0da350 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -395,4 +395,10 @@ static inline void __cpu_init_stage2(void) "PARange is %d bits, unsupported configuration!", parange); } +enum { + KVM_SEI_SEV_RECOVERABLE = 1, + KVM_SEI_SEV_FATAL, + KVM_SEI_SEV_CORRECTED, +}; + #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index e70cb61..73b45fb 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -57,6 +57,7 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); }) int handle_guest_sea(phys_addr_t addr, unsigned int esr); +int handle_guest_sei(unsigned int esr); #endif /* __ASSEMBLY__ */ #endif /* __ASM_SYSTEM_MISC_H */ diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 17d8a16..d546d55 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -28,6 +28,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include "trace.h" @@ -178,6 +179,61 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) return arm_exit_handlers[hsr_ec]; } +/** + * kvm_handle_guest_sei - handles SError interrupt or asynchronous aborts + * @vcpu: the VCPU pointer + * + * For RAS SError interrupt, if the AET is [ESR_ELx_AET_UEU] or + * [ESR_ELx_AET_UER], then let host user space do the recovery, + * otherwise, directly inject virtual SError to guest or panic. + */ +static int kvm_handle_guest_sei(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + unsigned int esr = kvm_vcpu_get_hsr(vcpu); + bool impdef_syndrome = esr & ESR_ELx_ISV; /* aka IDS */ + unsigned int aet = esr & ESR_ELx_AET; + + run->exit_reason = KVM_EXIT_EXCEPTION; + run->ex.exception = ARM_EXCEPTION_EL1_SERROR; + + /* + * In below three conditions, it will directly inject the + * virtual SError: + * 1. Not support RAS extension + * 2. The Syndrome is IMPLEMENTATION DEFINED + * 3. It is Uncategorized SEI + */ + if (!cpus_have_const_cap(ARM64_HAS_RAS_EXTN) || impdef_syndrome || + ((esr & ESR_ELx_FSC) != ESR_ELx_FSC_SERROR)) { + kvm_inject_vabt(vcpu); + return 1; + } + + switch (aet) { + case ESR_ELx_AET_CE: /* corrected error */ + case ESR_ELx_AET_UEO: /* restartable error, not yet consumed */ + break; /* continue processing the guest exit */ + case ESR_ELx_AET_UEU: + case ESR_ELx_AET_UER: /* The error has not been propagated */ + /* + * Only handle the guest SEI if the error has not been propagated + */ + if (!handle_guest_sei(kvm_vcpu_get_hsr(vcpu))) { + run->ex.error_code = KVM_SEI_SEV_RECOVERABLE; + return 0; + } + /* If SError handling is failed, continue run, panic */ + default: + /* + * Until now, the CPU supports RAS and SEI is fatal, or host + * does not support to handle the SError. + */ + panic("This Asynchronous SError interrupt is dangerous, panic"); + } + + return 0; +} + /* * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on * proper exit to userspace. @@ -201,8 +257,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, *vcpu_pc(vcpu) -= adj; } - kvm_inject_vabt(vcpu); - return 1; + return kvm_handle_guest_sei(vcpu, run); } exception_index = ARM_EXCEPTION_CODE(exception_index); @@ -211,8 +266,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); - return 1; + return kvm_handle_guest_sei(vcpu, run); case ARM_EXCEPTION_TRAP: /* * See ARM ARM B1.14.1: "Hyp traps on instructions diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index c98c1b3..dce7ab9 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -688,6 +688,22 @@ int handle_guest_sea(phys_addr_t addr, unsigned int esr) } /* + * Handle SError interrupt that occurred in guest OS. + * + * The return value will be zero if the SEI was successfully handled + * and non-zero if handling is failed. + */ +int handle_guest_sei(unsigned int esr) +{ + int ret = -ENOENT; + + if (IS_ENABLED(CONFIG_ACPI_APEI_SEI)) + ret = ghes_notify_abort(ACPI_HEST_NOTIFY_SEI); + + return ret; +} + +/* * Dispatch a data abort to the relevant handler. */ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,