From patchwork Fri Aug 18 14:11:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dongjiu Geng X-Patchwork-Id: 9908927 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 01E9560382 for ; Fri, 18 Aug 2017 13:51:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EBF3528CB8 for ; Fri, 18 Aug 2017 13:51:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DE8B128CCC; Fri, 18 Aug 2017 13:51:56 +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.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.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 778C128CB8 for ; Fri, 18 Aug 2017 13:51:55 +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=5ivL0hZ3TMV4r0pIGMjGstW8O+/fAKt7FodoCrNcojY=; b=tuaKq6GgZdJnwR rbGus1XZRAnDBIZD6NEbOI5Ernr7tPwLpkuRNJLn/8QnZxGopWpnaZTBXRKrzTWiOOUVHLzvr2trp hB297dAIfa+wp1o7t7L2KehxarTux6mrJnKR9+uUMeUSrmTTU8tSYPCzQujoqlaJnn1yeERGdEaXx 9zGeDncECidKqLuNkbJSY9TBeONixydh4vCH+fG/t7EMzXSXjbJcKW2u8INpmnhvJWZjlW7HAj3Gh AJizHD7SQtyISkvDtfOHh7lGBYVNKMYf7E7ayXcD/ocFHFlyFp7KrP7TqKXZGj9RKReL9LFyBRCTV LeKohRwJujKdMXsjy4nw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dihgk-00058e-Q1; Fri, 18 Aug 2017 13:51:50 +0000 Received: from szxga04-in.huawei.com ([45.249.212.190]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1diheA-00023r-BT for linux-arm-kernel@lists.infradead.org; Fri, 18 Aug 2017 13:49:15 +0000 Received: from 172.30.72.59 (EHLO DGGEMS414-HUB.china.huawei.com) ([172.30.72.59]) by dggrg04-dlp.huawei.com (MOS 4.4.6-GA FastPath queued) with ESMTP id DFK73381; Fri, 18 Aug 2017 21:48:36 +0800 (CST) Received: from linux.huawei.com (10.67.187.203) by DGGEMS414-HUB.china.huawei.com (10.3.19.214) with Microsoft SMTP Server id 14.3.301.0; Fri, 18 Aug 2017 21:48:23 +0800 From: Dongjiu Geng To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v5 3/7] acpi: apei: Add SEI notification type support for ARMv8 Date: Fri, 18 Aug 2017 22:11:53 +0800 Message-ID: <1503065517-7920-4-git-send-email-gengdongjiu@huawei.com> X-Mailer: git-send-email 1.7.7 In-Reply-To: <1503065517-7920-1-git-send-email-gengdongjiu@huawei.com> References: <1503065517-7920-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.0A090202.5996F035.002A, 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: 2507e6b892137095dcb0f8436a805e78 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170818_064911_021708_09AEB834 X-CRM114-Status: GOOD ( 19.23 ) 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: zhengqiang10@huawei.com, wuquanming@huawei.com, huangshaoyu@huawei.com, linuxarm@huawei.com, gengdongjiu@huawei.com 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 ARMV8.2 requires implementation of the RAS extension, in this extension it adds SEI(SError Interrupt) notification type, this patch addes a new GHES error source handling function for SEI. Because this error source parse and handling method are similar with the SEA. so use one function to handle them. In current code logic, The two functions ghes_sea_add() and ghes_sea_remove() are only called when CONFIG_ACPI_APEI_SEA and CONFIG_ACPI_APEI_SEI are defined. If not, it will return errors in the ghes_probe() and do not continue, so remove the useless code that handling CONFIG_ACPI_APEI_SEA and CONFIG_ACPI_APEI_SEI do not defined. Expose one API ghes_notify_sex() to external, external modules can call this exposed APIs to parse and handling the SEA/SEI. Signed-off-by: Dongjiu Geng --- arch/arm64/mm/fault.c | 21 +++++++++++++++-- drivers/acpi/apei/Kconfig | 15 ++++++++++++ drivers/acpi/apei/ghes.c | 60 ++++++++++++++++++++++++++++++----------------- include/acpi/ghes.h | 2 +- 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 2509e4fe6992..0aa92a69c280 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -585,7 +585,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) if (interrupts_enabled(regs)) nmi_enter(); - ret = ghes_notify_sea(); + ret = ghes_notify_sex(ACPI_HEST_NOTIFY_SEA); if (interrupts_enabled(regs)) nmi_exit(); @@ -682,7 +682,24 @@ int handle_guest_sea(phys_addr_t addr, unsigned int esr) int ret = -ENOENT; if (IS_ENABLED(CONFIG_ACPI_APEI_SEA)) - ret = ghes_notify_sea(); + ret = ghes_notify_sex(ACPI_HEST_NOTIFY_SEA); + + return ret; +} + +/* + * Handle SError interrupt that occur in a guest kernel. + * + * The return value will be zero if the SEI was successfully handled + * and non-zero if there was an error processing the error or there was + * no error to process. + */ +int handle_guest_sei(phys_addr_t addr, unsigned int esr) +{ + int ret = -ENOENT; + + if (IS_ENABLED(CONFIG_ACPI_APEI_SEI)) + ret = ghes_notify_sex(ACPI_HEST_NOTIFY_SEI); return ret; } diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index de14d49a5c90..556370c763ec 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -54,6 +54,21 @@ config ACPI_APEI_SEA option allows the OS to look for such hardware error record, and take appropriate action. +config ACPI_APEI_SEI + bool "APEI Asynchronous SError Interrupt logging/recovering support" + depends on ARM64 && ACPI_APEI_GHES + default y + help + This option should be enabled if the system supports + firmware first handling of SEI (asynchronous SError interrupt). + + SEI happens with invalid instruction access or asynchronous exceptions + on ARMv8 systems. If a system supports firmware first handling of SEI, + the platform analyzes and handles hardware error notifications from + SEI, and it may then form a HW error record for the OS to parse and + handle. This option allows the OS to look for such hardware error + record, and take appropriate action. + config ACPI_APEI_MEMORY_FAILURE bool "APEI memory error recovering support" depends on ACPI_APEI && MEMORY_FAILURE diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index d661d452b238..705738aa48b8 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -813,20 +813,21 @@ static struct notifier_block ghes_notifier_hed = { .notifier_call = ghes_notify_hed, }; -#ifdef CONFIG_ACPI_APEI_SEA static LIST_HEAD(ghes_sea); +static LIST_HEAD(ghes_sei); /* * Return 0 only if one of the SEA error sources successfully reported an error * record sent from the firmware. */ -int ghes_notify_sea(void) + +int ghes_handle_sex(struct list_head *head) { struct ghes *ghes; int ret = -ENOENT; rcu_read_lock(); - list_for_each_entry_rcu(ghes, &ghes_sea, list) { + list_for_each_entry_rcu(ghes, head, list) { if (!ghes_proc(ghes)) ret = 0; } @@ -834,33 +835,41 @@ int ghes_notify_sea(void) return ret; } -static void ghes_sea_add(struct ghes *ghes) +int ghes_notify_sex(u8 type) +{ + if (type == ACPI_HEST_NOTIFY_SEA) + return ghes_handle_sex(&ghes_sea); + else if (type == ACPI_HEST_NOTIFY_SEI) + return ghes_handle_sex(&ghes_sei); + + return -ENOENT; +} + +/* + * This function is only called when the CONFIG_HAVE_ACPI_APEI_SEA or + * CONFIG_HAVE_ACPI_APEI_SEA is enabled. when disabled, it will return + * error in the ghes_probe + */ +static void ghes_sex_add(struct ghes *ghes) { + u8 notify_type = ghes->generic->notify.type; + mutex_lock(&ghes_list_mutex); - list_add_rcu(&ghes->list, &ghes_sea); + if (notify_type == ACPI_HEST_NOTIFY_SEA) + list_add_rcu(&ghes->list, &ghes_sea); + else if (notify_type == ACPI_HEST_NOTIFY_SEI) + list_add_rcu(&ghes->list, &ghes_sei); + mutex_unlock(&ghes_list_mutex); } -static void ghes_sea_remove(struct ghes *ghes) +static void ghes_sex_remove(struct ghes *ghes) { mutex_lock(&ghes_list_mutex); list_del_rcu(&ghes->list); mutex_unlock(&ghes_list_mutex); synchronize_rcu(); } -#else /* CONFIG_ACPI_APEI_SEA */ -static inline void ghes_sea_add(struct ghes *ghes) -{ - pr_err(GHES_PFX "ID: %d, trying to add SEA notification which is not supported\n", - ghes->generic->header.source_id); -} - -static inline void ghes_sea_remove(struct ghes *ghes) -{ - pr_err(GHES_PFX "ID: %d, trying to remove SEA notification which is not supported\n", - ghes->generic->header.source_id); -} -#endif /* CONFIG_ACPI_APEI_SEA */ #ifdef CONFIG_HAVE_ACPI_APEI_NMI /* @@ -1107,6 +1116,13 @@ static int ghes_probe(struct platform_device *ghes_dev) goto err; } break; + case ACPI_HEST_NOTIFY_SEI: + if (!IS_ENABLED(CONFIG_ACPI_APEI_SEI)) { + pr_warn(GHES_PFX "Generic hardware error source: %d notified via SEI is not supported!\n", + generic->header.source_id); + goto err; + } + break; case ACPI_HEST_NOTIFY_NMI: if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) { pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n", @@ -1176,7 +1192,8 @@ static int ghes_probe(struct platform_device *ghes_dev) break; case ACPI_HEST_NOTIFY_SEA: - ghes_sea_add(ghes); + case ACPI_HEST_NOTIFY_SEI: + ghes_sex_add(ghes); break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_add(ghes); @@ -1229,7 +1246,8 @@ static int ghes_remove(struct platform_device *ghes_dev) break; case ACPI_HEST_NOTIFY_SEA: - ghes_sea_remove(ghes); + case ACPI_HEST_NOTIFY_SEI: + ghes_sex_remove(ghes); break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_remove(ghes); diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 9061c5c743b3..41cbce1bc926 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -118,6 +118,6 @@ static inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata) (void *)section - (void *)(estatus + 1) < estatus->data_length; \ section = acpi_hest_get_next(section)) -int ghes_notify_sea(void); +int ghes_notify_sex(u8 type); #endif /* GHES_H */