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: 9908923 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 54A6060382 for ; Fri, 18 Aug 2017 13:51:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4DC1C28CB8 for ; Fri, 18 Aug 2017 13:51:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4207328CCC; Fri, 18 Aug 2017 13:51:51 +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 94EE728CB8 for ; Fri, 18 Aug 2017 13:51:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751728AbdHRNvh (ORCPT ); Fri, 18 Aug 2017 09:51:37 -0400 Received: from szxga04-in.huawei.com ([45.249.212.190]:4502 "EHLO szxga04-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753272AbdHRNtj (ORCPT ); Fri, 18 Aug 2017 09:49:39 -0400 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: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , CC: , , , , 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 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.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 */