From patchwork Tue Apr 11 10:48:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shuai Xue X-Patchwork-Id: 13207341 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5CD62C77B74 for ; Tue, 11 Apr 2023 10:49:02 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id EA560900006; Tue, 11 Apr 2023 06:49:01 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id E562A900002; Tue, 11 Apr 2023 06:49:01 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D1E8B900006; Tue, 11 Apr 2023 06:49:01 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id C23E4900002 for ; Tue, 11 Apr 2023 06:49:01 -0400 (EDT) Received: from smtpin06.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 9588AA0B08 for ; Tue, 11 Apr 2023 10:49:01 +0000 (UTC) X-FDA: 80668787682.06.D113056 Received: from out30-130.freemail.mail.aliyun.com (out30-130.freemail.mail.aliyun.com [115.124.30.130]) by imf04.hostedemail.com (Postfix) with ESMTP id 714EF4001A for ; Tue, 11 Apr 2023 10:48:58 +0000 (UTC) Authentication-Results: imf04.hostedemail.com; dkim=none; spf=pass (imf04.hostedemail.com: domain of xueshuai@linux.alibaba.com designates 115.124.30.130 as permitted sender) smtp.mailfrom=xueshuai@linux.alibaba.com; dmarc=pass (policy=none) header.from=alibaba.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1681210139; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BWw8zWHfZFEDDT2T6xd4sS+5GxWz39NX58w2Z74duR0=; b=J8kou7FXYYS9rIxjw7/lz27R0GAGN62u1H78lZ94UfrBUVTGak8QfNVebOgxrXopbaaZwX scTm/bgZBXQoMt+CNUzruSBlQqhaq4+OuJVAjkA8mLHGjE3P2dLp/XHAFLXhuwLtzpg6zS T1DVbuRQGLsoFI0NXM++mNy0bH7lGJw= ARC-Authentication-Results: i=1; imf04.hostedemail.com; dkim=none; spf=pass (imf04.hostedemail.com: domain of xueshuai@linux.alibaba.com designates 115.124.30.130 as permitted sender) smtp.mailfrom=xueshuai@linux.alibaba.com; dmarc=pass (policy=none) header.from=alibaba.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1681210139; a=rsa-sha256; cv=none; b=qQa6Jy7Mb/nYFjYayU5ICGEEdzO+/eAgh5i6jMKKjJVT4SUIS2R8oZOuY2ia0RFRwIYPAt irm+XvcCmwiRY9PmB9Euu61rSAMBVBtiykCYj6GEqXfOmbImfPRfKMEj8S9g0d9VENKcWh aAm7l1PuFWP8LT1Q2KXcujAjsgqZBVA= X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R321e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018045192;MF=xueshuai@linux.alibaba.com;NM=1;PH=DS;RN=24;SR=0;TI=SMTPD_---0Vfs-smU_1681210132; Received: from localhost.localdomain(mailfrom:xueshuai@linux.alibaba.com fp:SMTPD_---0Vfs-smU_1681210132) by smtp.aliyun-inc.com; Tue, 11 Apr 2023 18:48:53 +0800 From: Shuai Xue To: tanxiaofei@huawei.com, mawupeng1@huawei.com, tony.luck@intel.com, naoya.horiguchi@nec.com Cc: linux-acpi@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, xueshuai@linux.alibaba.com, justin.he@arm.com, akpm@linux-foundation.org, ardb@kernel.org, ashish.kalra@amd.com, baolin.wang@linux.alibaba.com, bp@alien8.de, cuibixuan@linux.alibaba.com, dave.hansen@linux.intel.com, james.morse@arm.com, jarkko@kernel.org, lenb@kernel.org, linmiaohe@huawei.com, lvying6@huawei.com, rafael@kernel.org, xiexiuqi@huawei.com, zhuo.song@linux.alibaba.com Subject: [PATCH v5 1/2] ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on synchronous events Date: Tue, 11 Apr 2023 18:48:41 +0800 Message-Id: <20230411104842.37079-2-xueshuai@linux.alibaba.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221027042445.60108-1-xueshuai@linux.alibaba.com> References: <20221027042445.60108-1-xueshuai@linux.alibaba.com> MIME-Version: 1.0 X-Stat-Signature: xtzt5sncpgm91sza8843z1qu41kad6tu X-Rspam-User: X-Rspamd-Queue-Id: 714EF4001A X-Rspamd-Server: rspam06 X-HE-Tag: 1681210138-786942 X-HE-Meta: U2FsdGVkX1/EbdYJ7EubWErDAN2UebEBhoUw7LG7jr15OJxe0AhXdVqw0OxpzpmuzMw5kFqmdlGTwQJHgRXx/ZGKomJE/9G8ilKJ1OQvJ2L74mrKrcuD/kLeF4Cbw5WJ/oH0Vrb9oXAxAjKxWM13JFniqDEKnDJ7Z/ofFRxV/Oq93wWFP1F9EMA4jaflaD8ZByf4zMIfR00/cZ5rsgIjBOJJCtravwtFDNbzxgZ79PKxW7iW/YUtNBlgg6efmWp9VNsil/Lwrpt1rgmCaUcgqt68K0BkQN8GYL7jMIWWMinR9Fa0fPaHr7FCHaJ7MoYQ9CBrHGEuUpqXVEXrti6IgfpaKYpcfP8QGuB21/AmXqKvaqbP1I3CiOBbU1FB9qjpO742PGQ5rxLv+vJGxwhGbrXpQuXxLxj+QJB7FjVE30ADcNJLWeHvyzo/OGkS9+4n0SHWLmpmJYCl1WDNUlEYfzEOIwHQYnGfhN6nqVyBJmBMP22UgTmXygUErvvmhajBGbDnMxxVq3pyJFAbKMM8j3TNvp3sDhYzNDFM51CkNG246TxX1q0Cf1LmUS15ct810yNVzIyCibMBp8z4e2L2sAazl2OXmQ5eLwHweweak4241yGD8vYx6+OhmP6KzdChyVjJTCDPr7LxKBe1bhoRmWfLx51QKcN3Y+JA9n2vZXifpHpyvfRucNcjqGf+KoEzaLBrJCpvKM4z7ZvH5QIU7MTD01YkLL9Lnr2Gs0f+lIetD0bQ9/fz/YXgdchkUjxhooCqgpNOEkOncW401YA1ITUnjOJYZiOW60CJTUc0li+OMogBKiAyaZC82GdJQLYhLR49eEJZIJKjNw4QsB1aIaZEJKKtyPeb+xK5Zlt1aAQ5QkyER+S6OdLq2e+zNDeK9JbX0ZrvUDVYmdaZLfPKf55h0MFKrINKTty/sfyFrTrWaiRpy+UWO6dyRrGKx3gS0aJlCvs2ZmJp2W5x56T kuakZeCO dLoKi1UQSbGJL11Fenbx1slL83T5dXdzxRc0NiliI5kYCVYxUHpDFDhiJH0CzD1536wlHkGnqe6aRJFOaTZsJ89xcpWpkOVeYLC8BMwfHa+Dx5TEj97wje8NAmWHX2l/ur+taoWqRFgkwFHRAZ5eea7r2mcwDWiLPCdT1DmxWYRqmjG6IH0kuwjbYEBCAFDJQaNEp X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: There are two major types of uncorrected recoverable (UCR) errors : - Action Required (AR): The error is detected and the processor already consumes the memory. OS requires to take action (for example, offline failure page/kill failure thread) to recover this uncorrectable error. - Action Optional (AO): The error is detected out of processor execution context. Some data in the memory are corrupted. But the data have not been consumed. OS is optional to take action to recover this uncorrectable error. The essential difference between AR and AO errors is that AR is a synchronous event, while AO is an asynchronous event. The hardware will signal a synchronous exception (Machine Check Exception on X86 and Synchronous External Abort on Arm64) when an error is detected and the memory access has been architecturally executed. When APEI firmware first is enabled, a platform may describe one error source for the handling of synchronous errors (e.g. MCE or SEA notification ), or for handling asynchronous errors (e.g. SCI or External Interrupt notification). In other words, we can distinguish synchronous errors by APEI notification. For AR errors, kernel will kill current process accessing the poisoned page by sending SIGBUS with BUS_MCEERR_AR. In addition, for AO errors, kernel will notify the process who owns the poisoned page by sending SIGBUS with BUS_MCEERR_AO in early kill mode. However, the GHES driver always sets mf_flags to 0 so that all UCR errors are handled as AO errors in memory failure. To this end, set memory failure flags as MF_ACTION_REQUIRED on synchronous events. Fixes: ba61ca4aab47 ("ACPI, APEI, GHES: Add hardware memory error recovery support")' Signed-off-by: Shuai Xue Tested-by: Ma Wupeng Reviewed-by: Kefeng Wang Reviewed-by: Xiaofei Tan --- drivers/acpi/apei/ghes.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 34ad071a64e9..c479b85899f5 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -101,6 +101,20 @@ static inline bool is_hest_type_generic_v2(struct ghes *ghes) return ghes->generic->header.type == ACPI_HEST_TYPE_GENERIC_ERROR_V2; } +/* + * A platform may describe one error source for the handling of synchronous + * errors (e.g. MCE or SEA), or for handling asynchronous errors (e.g. SCI + * or External Interrupt). On x86, the HEST notifications are always + * asynchronous, so only SEA on ARM is delivered as a synchronous + * notification. + */ +static inline bool is_hest_sync_notify(struct ghes *ghes) +{ + u8 notify_type = ghes->generic->notify.type; + + return notify_type == ACPI_HEST_NOTIFY_SEA; +} + /* * This driver isn't really modular, however for the time being, * continuing to use module_param is the easiest way to remain @@ -477,7 +491,7 @@ static bool ghes_do_memory_failure(u64 physical_addr, int flags) } static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, - int sev) + int sev, bool sync) { int flags = -1; int sec_sev = ghes_severity(gdata->error_severity); @@ -491,7 +505,7 @@ static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED)) flags = MF_SOFT_OFFLINE; if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE) - flags = 0; + flags = sync ? MF_ACTION_REQUIRED : 0; if (flags != -1) return ghes_do_memory_failure(mem_err->physical_addr, flags); @@ -499,9 +513,11 @@ static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, return false; } -static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata, int sev) +static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata, + int sev, bool sync) { struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata); + int flags = sync ? MF_ACTION_REQUIRED : 0; bool queued = false; int sec_sev, i; char *p; @@ -526,7 +542,7 @@ static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata, int s * and don't filter out 'corrected' error here. */ if (is_cache && has_pa) { - queued = ghes_do_memory_failure(err_info->physical_fault_addr, 0); + queued = ghes_do_memory_failure(err_info->physical_fault_addr, flags); p += err_info->length; continue; } @@ -647,6 +663,7 @@ static bool ghes_do_proc(struct ghes *ghes, const guid_t *fru_id = &guid_null; char *fru_text = ""; bool queued = false; + bool sync = is_hest_sync_notify(ghes); sev = ghes_severity(estatus->error_severity); apei_estatus_for_each_section(estatus, gdata) { @@ -664,13 +681,13 @@ static bool ghes_do_proc(struct ghes *ghes, atomic_notifier_call_chain(&ghes_report_chain, sev, mem_err); arch_apei_report_mem_error(sev, mem_err); - queued = ghes_handle_memory_failure(gdata, sev); + queued = ghes_handle_memory_failure(gdata, sev, sync); } else if (guid_equal(sec_type, &CPER_SEC_PCIE)) { ghes_handle_aer(gdata); } else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { - queued = ghes_handle_arm_hw_error(gdata, sev); + queued = ghes_handle_arm_hw_error(gdata, sev, sync); } else { void *err = acpi_hest_get_payload(gdata); From patchwork Tue Apr 11 10:48:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shuai Xue X-Patchwork-Id: 13207342 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E9DCC76196 for ; Tue, 11 Apr 2023 10:49:04 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id DE2BE900002; Tue, 11 Apr 2023 06:49:03 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id D9498280001; Tue, 11 Apr 2023 06:49:03 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id C5C8B900007; Tue, 11 Apr 2023 06:49:03 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id AC348900002 for ; Tue, 11 Apr 2023 06:49:03 -0400 (EDT) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 85761140B51 for ; Tue, 11 Apr 2023 10:49:03 +0000 (UTC) X-FDA: 80668787766.24.92FC397 Received: from out30-124.freemail.mail.aliyun.com (out30-124.freemail.mail.aliyun.com [115.124.30.124]) by imf02.hostedemail.com (Postfix) with ESMTP id 7E9278001A for ; Tue, 11 Apr 2023 10:49:01 +0000 (UTC) Authentication-Results: imf02.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=alibaba.com; spf=pass (imf02.hostedemail.com: domain of xueshuai@linux.alibaba.com designates 115.124.30.124 as permitted sender) smtp.mailfrom=xueshuai@linux.alibaba.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1681210141; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ipCzLD2c6iFBtrlEKYdkbLXpFZkskSJINTlDUo3GKZ8=; b=CM/Luc/APaLAKltCM/Z9xpwjZGgmoYKeciMdN/x5oCp54JEj+B4r1JQgX8WRSYXgehpaNT xHSFGfaHLFXgfMV7cre0GyXk5w0NGj7t9VX22xnxsX91XO5JGJb00vS/5N12XKhs5nUW7m rMBorZhN5KPC9oMyDW0ypv5e+9lY4A8= ARC-Authentication-Results: i=1; imf02.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=alibaba.com; spf=pass (imf02.hostedemail.com: domain of xueshuai@linux.alibaba.com designates 115.124.30.124 as permitted sender) smtp.mailfrom=xueshuai@linux.alibaba.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1681210141; a=rsa-sha256; cv=none; b=3r9BZfPnHS0gCoYFKYazmjQzvVYFRxPIeYQ3m4H1ilst522FN4aiG6dkDt5jnWqg/T40E/ /HCIBdKriFAAL0QNU3cUZiRGssydUIzZcAGnVeP5oa2Jwx+Br9VG+3xQNhioDW9yOpsv0B YW1yZ0V2q75KektU+i02DWSImdRKb8U= X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R211e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018046050;MF=xueshuai@linux.alibaba.com;NM=1;PH=DS;RN=24;SR=0;TI=SMTPD_---0Vfs-snq_1681210134; Received: from localhost.localdomain(mailfrom:xueshuai@linux.alibaba.com fp:SMTPD_---0Vfs-snq_1681210134) by smtp.aliyun-inc.com; Tue, 11 Apr 2023 18:48:56 +0800 From: Shuai Xue To: tanxiaofei@huawei.com, mawupeng1@huawei.com, tony.luck@intel.com, naoya.horiguchi@nec.com Cc: linux-acpi@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, xueshuai@linux.alibaba.com, justin.he@arm.com, akpm@linux-foundation.org, ardb@kernel.org, ashish.kalra@amd.com, baolin.wang@linux.alibaba.com, bp@alien8.de, cuibixuan@linux.alibaba.com, dave.hansen@linux.intel.com, james.morse@arm.com, jarkko@kernel.org, lenb@kernel.org, linmiaohe@huawei.com, lvying6@huawei.com, rafael@kernel.org, xiexiuqi@huawei.com, zhuo.song@linux.alibaba.com Subject: [PATCH v5 2/2] ACPI: APEI: handle synchronous exceptions in task work Date: Tue, 11 Apr 2023 18:48:42 +0800 Message-Id: <20230411104842.37079-3-xueshuai@linux.alibaba.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221027042445.60108-1-xueshuai@linux.alibaba.com> References: <20221027042445.60108-1-xueshuai@linux.alibaba.com> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: 7E9278001A X-Stat-Signature: sjgr6zpop5jmhrbi71pjz4aax6788j4k X-HE-Tag: 1681210141-8933 X-HE-Meta: U2FsdGVkX1+6Gm6pW9YScDKtM2ADKuVYCfSxssPo77TqdaoOwuAflTJWdA4LnRNYlTbwYnTDrYAjuYXU8/Qvbl1Y1ucneS1yjG9utXx6mrv0la/U2WMd1cyXuRuJ2VdSre0pIQ5YxaTGYuDBPA7aA07uCo4KyKGaIqLMh7yaFgeXulmjXvUrNQlemKw5ahprD+F3HfyTtM/yVSLrB1hYBlflv/50wKmZuZBs1191Gep71rKmX+tUDrYZePDVS7J1uyrkN8Q5+wCKcZE+h/4gZDrzEOVAsumkZJx2BdRzBbl6aP7oKtt3RA6lsEf8nav4OAnhGiNISnYi0XGv2XL8EAJRtNrixg2DT1wzuO3nyXqi8WLjhpk6s7ZiKJrDt68jNN3BDHd9e6sMACkZWdTGLTtHr/6W8TKnM8xOJddi7t0HwS5XZ2d0+ghLKStPhXkpnxuqFli/DvTr1RSTx79vmhuvWJyLxcQ7pBXUnPl9P7klMbj8nmI1uhF5J/ZbVX2S+KRNVTEAOUawFmMe7ndcqzRbJFYT/2pWegkJ18qBVa+6ENw50iXyJiqdwUi9vZwAPnCl214731SpOHQ6vwHAT8DIdo3C73xH4O/wSICIq/j0temgv4bOn3SUi1hM9Bl3QmqUio3wkcU8PBRsOAe0xIeiuEPMOl3Mf6rOAH9fVSci6fuJ2XirJEDb0ly+9KCX+8VFd+d4BFRp9D3uhmZ9JWZdVFF9M9vmFRCA+M+IGEZ7s2I1nhKfjfZxwFs09lwTQezbY16rkzJZRRvO3ysOyVOvdAnAggWkCmIanS6dlTyesXfK8RHPr2d7IO8s7aknIss2EprxSh9wSi/V+uDBeGbEhLhdjUsH/6r8ERqpwHktb+qdb5QR4m534Q5/gg7yBBeNAkZ+eEQxSSKWIWWdlddEjh2UfCa0meWOA7cYPdfcpRQWBoJt+wqTf6aWQK5tN9MEKXlk6nFd2rVn/F0 qcFMxToE Z9faGWyCn7JXFmY1/nIUPVqh4AFRMyGw1Wjz6JjqDDiDjmm/m5jNB98+uMSCXdAiM8lFxg1JCQK41kjXia9nPe0bsP1puGG2tlgTI6DUfVOXmzDwkhFIAeqerpnWaQH3PduNfKZCSBk+/taU= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Hardware errors could be signaled by synchronous interrupt, e.g. when an error is detected by a background scrubber, or signaled by synchronous exception, e.g. when an uncorrected error is consumed. Both synchronous and asynchronous error are queued and handled by a dedicated kthread in workqueue. commit 7f17b4a121d0 ("ACPI: APEI: Kick the memory_failure() queue for synchronous errors") keep track of whether memory_failure() work was queued, and make task_work pending to flush out the workqueue so that the work for synchronous error is processed before returning to user-space. The trick ensures that the corrupted page is unmapped and poisoned. And after returning to user-space, the task starts at current instruction which triggering a page fault in which kernel will send SIGBUS to current process due to VM_FAULT_HWPOISON. However, the memory failure recovery for hwpoison-aware mechanisms does not work as expected. For example, hwpoison-aware user-space processes like QEMU register their customized SIGBUS handler and enable early kill mode by seting PF_MCE_EARLY at initialization. Then the kernel will directy notify the process by sending a SIGBUS signal in memory failure with wrong si_code: the actual user-space process accessing the corrupt memory location, but its memory failure work is handled in a kthread context, so it will send SIGBUS with BUS_MCEERR_AO si_code to the actual user-space process instead of BUS_MCEERR_AR in kill_proc(). To this end, separate synchronous and asynchronous error handling into different paths like X86 platform does: - valid synchronous errors: queue a task_work to synchronously send SIGBUS before ret_to_user. - valid asynchronous errors: queue a work into workqueue to asynchronously handle memory failure. - abnormal branches such as invalid PA, unexpected severity, no memory failure config support, invalid GUID section, OOM, etc. Then for valid synchronous errors, the current context in memory failure is exactly belongs to the task consuming poison data and it will send SIBBUS with proper si_code. Fixes: 7f17b4a121d0 ("ACPI: APEI: Kick the memory_failure() queue for synchronous errors") Signed-off-by: Shuai Xue Tested-by: Ma Wupeng Reviewed-by: Kefeng Wang Reviewed-by: Xiaofei Tan --- drivers/acpi/apei/ghes.c | 91 +++++++++++++++++++++++++++------------- include/acpi/ghes.h | 3 -- mm/memory-failure.c | 13 ------ 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index c479b85899f5..4b70955e25f9 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -452,28 +452,51 @@ static void ghes_clear_estatus(struct ghes *ghes, } /* - * Called as task_work before returning to user-space. - * Ensure any queued work has been done before we return to the context that - * triggered the notification. + * struct sync_task_work - for synchronous RAS event + * + * @twork: callback_head for task work + * @pfn: page frame number of corrupted page + * @flags: fine tune action taken + * + * Structure to pass task work to be handled before + * ret_to_user via task_work_add(). */ -static void ghes_kick_task_work(struct callback_head *head) +struct sync_task_work { + struct callback_head twork; + u64 pfn; + int flags; +}; + +static void memory_failure_cb(struct callback_head *twork) { - struct acpi_hest_generic_status *estatus; - struct ghes_estatus_node *estatus_node; - u32 node_len; + int ret; + struct sync_task_work *twcb = + container_of(twork, struct sync_task_work, twork); - estatus_node = container_of(head, struct ghes_estatus_node, task_work); - if (IS_ENABLED(CONFIG_ACPI_APEI_MEMORY_FAILURE)) - memory_failure_queue_kick(estatus_node->task_work_cpu); + ret = memory_failure(twcb->pfn, twcb->flags); + kfree(twcb); - estatus = GHES_ESTATUS_FROM_NODE(estatus_node); - node_len = GHES_ESTATUS_NODE_LEN(cper_estatus_len(estatus)); - gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node, node_len); + if (!ret) + return; + + /* + * -EHWPOISON from memory_failure() means that it already sent SIGBUS + * to the current process with the proper error info, + * -EOPNOTSUPP means hwpoison_filter() filtered the error event, + * + * In both cases, no further processing is required. + */ + if (ret == -EHWPOISON || ret == -EOPNOTSUPP) + return; + + pr_err("Memory error not recovered"); + force_sig(SIGBUS); } static bool ghes_do_memory_failure(u64 physical_addr, int flags) { unsigned long pfn; + struct sync_task_work *twcb; if (!IS_ENABLED(CONFIG_ACPI_APEI_MEMORY_FAILURE)) return false; @@ -486,6 +509,18 @@ static bool ghes_do_memory_failure(u64 physical_addr, int flags) return false; } + if (flags == MF_ACTION_REQUIRED && current->mm) { + twcb = kmalloc(sizeof(*twcb), GFP_ATOMIC); + if (!twcb) + return false; + + twcb->pfn = pfn; + twcb->flags = flags; + init_task_work(&twcb->twork, memory_failure_cb); + task_work_add(current, &twcb->twork, TWA_RESUME); + return true; + } + memory_failure_queue(pfn, flags); return true; } @@ -1000,9 +1035,8 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) struct ghes_estatus_node *estatus_node; struct acpi_hest_generic *generic; struct acpi_hest_generic_status *estatus; - bool task_work_pending; + bool queued, sync; u32 len, node_len; - int ret; llnode = llist_del_all(&ghes_estatus_llist); /* @@ -1015,27 +1049,25 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) estatus_node = llist_entry(llnode, struct ghes_estatus_node, llnode); estatus = GHES_ESTATUS_FROM_NODE(estatus_node); + sync = is_hest_sync_notify(estatus_node->ghes); len = cper_estatus_len(estatus); node_len = GHES_ESTATUS_NODE_LEN(len); - task_work_pending = ghes_do_proc(estatus_node->ghes, estatus); + + queued = ghes_do_proc(estatus_node->ghes, estatus); + /* + * If no memory failure work is queued for abnormal synchronous + * errors, do a force kill. + */ + if (sync && !queued) + force_sig(SIGBUS); + if (!ghes_estatus_cached(estatus)) { generic = estatus_node->generic; if (ghes_print_estatus(NULL, generic, estatus)) ghes_estatus_cache_add(generic, estatus); } - - if (task_work_pending && current->mm) { - estatus_node->task_work.func = ghes_kick_task_work; - estatus_node->task_work_cpu = smp_processor_id(); - ret = task_work_add(current, &estatus_node->task_work, - TWA_RESUME); - if (ret) - estatus_node->task_work.func = NULL; - } - - if (!estatus_node->task_work.func) - gen_pool_free(ghes_estatus_pool, - (unsigned long)estatus_node, node_len); + gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node, + node_len); llnode = next; } @@ -1096,7 +1128,6 @@ static int ghes_in_nmi_queue_one_entry(struct ghes *ghes, estatus_node->ghes = ghes; estatus_node->generic = ghes->generic; - estatus_node->task_work.func = NULL; estatus = GHES_ESTATUS_FROM_NODE(estatus_node); if (__ghes_read_estatus(estatus, buf_paddr, fixmap_idx, len)) { diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 3c8bba9f1114..e5e0c308d27f 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -35,9 +35,6 @@ struct ghes_estatus_node { struct llist_node llnode; struct acpi_hest_generic *generic; struct ghes *ghes; - - int task_work_cpu; - struct callback_head task_work; }; struct ghes_estatus_cache { diff --git a/mm/memory-failure.c b/mm/memory-failure.c index fae9baf3be16..6ea8c325acb3 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -2355,19 +2355,6 @@ static void memory_failure_work_func(struct work_struct *work) } } -/* - * Process memory_failure work queued on the specified CPU. - * Used to avoid return-to-userspace racing with the memory_failure workqueue. - */ -void memory_failure_queue_kick(int cpu) -{ - struct memory_failure_cpu *mf_cpu; - - mf_cpu = &per_cpu(memory_failure_cpu, cpu); - cancel_work_sync(&mf_cpu->work); - memory_failure_work_func(&mf_cpu->work); -} - static int __init memory_failure_init(void) { struct memory_failure_cpu *mf_cpu;