From patchwork Fri Sep 21 22:16:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Morse X-Patchwork-Id: 10611083 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 84A9C5A4 for ; Fri, 21 Sep 2018 22:21:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 740892DDD4 for ; Fri, 21 Sep 2018 22:21:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 67E9E2E1EC; Fri, 21 Sep 2018 22:21:20 +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=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B5F302DDD4 for ; Fri, 21 Sep 2018 22:21:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=pKx4j/Q0qqo5Znn3wGi0vPZz+TbC8PNqf1RzJ0IalQU=; b=QpoRmMiJlOMf3R MSLL1VWrrds6ckdQeZs7ui1sG64LLtbV5kwvM62y5dqa0nHj7y+X5G/xPv/O6I5Y2vPjAK1cDudbt RiFs7ptbx/0qNkVHaskKQws2Ba6Fb8yyvMYiC/X2nnNtt35iXdw2l9tRiIroPEeKbd6ctnJVw9r+8 cqq4ZJ0h86UoA++8L29A42NhkIx9DPkOeb3f3emeAzFrxbv5TCxuh3WOY6/9hfuZgyt8Ofpox/ivX zTZ1qyh895ZIbKfDiZy5772nWLriajw7kLZpJh3LjvreXj9kBvMkzZdnp9g9havSTJBApRgvyl0ZS CcGs+C8rLBuA08pkQK3Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g3TnP-00076K-Or; Fri, 21 Sep 2018 22:21:07 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g3Tkm-0004iH-B0 for linux-arm-kernel@lists.infradead.org; Fri, 21 Sep 2018 22:20:19 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0012A15AD; Fri, 21 Sep 2018 15:18:13 -0700 (PDT) Received: from melchizedek.Emea.Arm.com (melchizedek.emea.arm.com [10.4.12.81]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id DEE6E3F557; Fri, 21 Sep 2018 15:18:10 -0700 (PDT) From: James Morse To: linux-acpi@vger.kernel.org Subject: [PATCH v6 07/18] arm64: KVM/mm: Move SEA handling behind a single 'claim' interface Date: Fri, 21 Sep 2018 23:16:54 +0100 Message-Id: <20180921221705.6478-8-james.morse@arm.com> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20180921221705.6478-1-james.morse@arm.com> References: <20180921221705.6478-1-james.morse@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180921_151824_439540_D4A496C8 X-CRM114-Status: GOOD ( 21.31 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jonathan.zhang@cavium.com, Rafael Wysocki , Tony Luck , Punit Agrawal , Xie XiuQi , Marc Zyngier , Catalin Marinas , Tyler Baicar , Will Deacon , Christoffer Dall , Dongjiu Geng , linux-mm@kvack.org, Borislav Petkov , James Morse , Naoya Horiguchi , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, Len Brown Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP To split up APEIs in_nmi() path, we need the nmi-like callers to always be in_nmi(). Add a helper to do the work and claim the notification. When KVM or the arch code takes an exception that might be a RAS notification, it asks the APEI firmware-first code whether it wants to claim the exception. We can then go on to see if (a future) kernel-first mechanism wants to claim the notification, before falling through to the existing default behaviour. The NOTIFY_SEA code was merged before we had multiple, possibly interacting, NMI-like notifications and the need to consider kernel first in the future. Make the 'claiming' behaviour explicit. As we're restructuring the APEI code to allow multiple NMI-like notifications, any notification that might interrupt interrupts-masked code must always be wrapped in nmi_enter()/nmi_exit(). This allows APEI to use in_nmi() to use the right fixmap entries. We mask SError over this window to prevent an asynchronous RAS error arriving and tripping 'nmi_enter()'s BUG_ON(in_nmi()). Signed-off-by: James Morse Acked-by: Marc Zyngier Tested-by: Tyler Baicar --- Why does apei_claim_sea() take a pt_regs? This gets used later to take APEI by the hand through NMI->IRQ context, depending on what we interrupted. Changes since v4: * Made irqs-unmasked comment a lockdep assert. Changes since v3: * Removed spurious whitespace change * Updated comment in acpi.c to cover SError masking Changes since v2: * Added dummy definition for !ACPI and culled IS_ENABLED() checks. squash: make 'call with irqs unmaksed' a lockdep assert, much better --- arch/arm64/include/asm/acpi.h | 4 ++++ arch/arm64/include/asm/daifflags.h | 1 + arch/arm64/include/asm/kvm_ras.h | 16 +++++++++++++++- arch/arm64/kernel/acpi.c | 29 +++++++++++++++++++++++++++++ arch/arm64/mm/fault.c | 24 +++++------------------- 5 files changed, 54 insertions(+), 20 deletions(-) diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 709208dfdc8b..f722d2d6bf2b 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -139,6 +140,9 @@ static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr) { return __acpi_get_mem_attribute(addr); } +int apei_claim_sea(struct pt_regs *regs); +#else +static inline int apei_claim_sea(struct pt_regs *regs) { return -ENOENT; } #endif /* CONFIG_ACPI_APEI */ #ifdef CONFIG_ACPI_NUMA diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h index 22e4c83de5a5..cbd753855bf3 100644 --- a/arch/arm64/include/asm/daifflags.h +++ b/arch/arm64/include/asm/daifflags.h @@ -20,6 +20,7 @@ #define DAIF_PROCCTX 0 #define DAIF_PROCCTX_NOIRQ PSR_I_BIT +#define DAIF_ERRCTX (PSR_I_BIT | PSR_A_BIT) /* mask/save/unmask/restore all exceptions, including interrupts. */ static inline void local_daif_mask(void) diff --git a/arch/arm64/include/asm/kvm_ras.h b/arch/arm64/include/asm/kvm_ras.h index 5f72b07b7912..5b56e7e297b1 100644 --- a/arch/arm64/include/asm/kvm_ras.h +++ b/arch/arm64/include/asm/kvm_ras.h @@ -4,8 +4,22 @@ #ifndef __ARM64_KVM_RAS_H__ #define __ARM64_KVM_RAS_H__ +#include +#include #include -int kvm_handle_guest_sea(phys_addr_t addr, unsigned int esr); +#include + +/* + * 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(phys_addr_t addr, unsigned int esr) +{ + /* apei_claim_sea(NULL) expects to mask interrupts itself */ + lockdep_assert_irqs_enabled(); + + return apei_claim_sea(NULL); +} #endif /* __ARM64_KVM_RAS_H__ */ diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index ed46dc188b22..a9b8bba014b5 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -28,8 +28,10 @@ #include #include +#include #include #include +#include #include #include @@ -257,3 +259,30 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr) return __pgprot(PROT_NORMAL_NC); return __pgprot(PROT_DEVICE_nGnRnE); } + +/* + * Claim Synchronous External Aborts as a firmware first notification. + * + * Used by KVM and the arch do_sea handler. + * @regs may be NULL when called from process context. + */ +int apei_claim_sea(struct pt_regs *regs) +{ + int err = -ENOENT; + unsigned long current_flags = arch_local_save_flags(); + + if (!IS_ENABLED(CONFIG_ACPI_APEI_SEA)) + return err; + + /* + * SEA can interrupt SError, mask it and describe this as an NMI so + * that APEI defers the handling. + */ + local_daif_restore(DAIF_ERRCTX); + nmi_enter(); + err = ghes_notify_sea(); + nmi_exit(); + local_daif_restore(current_flags); + + return err; +} diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 1a30d7a8c9bf..2c38776bb71f 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -33,6 +34,7 @@ #include #include +#include #include #include #include @@ -45,8 +47,6 @@ #include #include -#include - struct fault_info { int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); @@ -631,19 +631,10 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) inf = esr_to_fault_info(esr); /* - * Synchronous aborts may interrupt code which had interrupts masked. - * Before calling out into the wider kernel tell the interested - * subsystems. + * Return value ignored as we rely on signal merging. + * Future patches will make this more robust. */ - if (IS_ENABLED(CONFIG_ACPI_APEI_SEA)) { - if (interrupts_enabled(regs)) - nmi_enter(); - - ghes_notify_sea(); - - if (interrupts_enabled(regs)) - nmi_exit(); - } + apei_claim_sea(regs); clear_siginfo(&info); info.si_signo = inf->sig; @@ -725,11 +716,6 @@ static const struct fault_info fault_info[] = { { do_bad, SIGKILL, SI_KERNEL, "unknown 63" }, }; -int kvm_handle_guest_sea(phys_addr_t addr, unsigned int esr) -{ - return ghes_notify_sea(); -} - asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) {