mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code
@ 2023-06-06  7:42 Shuai Xue
  2023-06-06  7:42 ` [RESEND PATCH v7 1/2] ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on synchronous events Shuai Xue
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Shuai Xue @ 2023-06-06  7:42 UTC (permalink / raw)
  To: rafael, wangkefeng.wang, tanxiaofei, mawupeng1, tony.luck,
	naoya.horiguchi
  Cc: linux-acpi, linux-mm, linux-kernel, xueshuai, justin.he, akpm,
	ardb, ashish.kalra, baolin.wang, bp, cuibixuan, dave.hansen,
	james.morse, jarkko, lenb, linmiaohe, lvying6, xiexiuqi,
	zhuo.song

changes since v6:
- add more explicty error message suggested by Xiaofei
- pick up reviewed-by tag from Xiaofei
- pick up internal reviewed-by tag from Baolin

changes since v5 by addressing comments from Kefeng:
- document return value of memory_failure()
- drop redundant comments in call site of memory_failure() 
- make ghes_do_proc void and handle abnormal case within it
- pick up reviewed-by tag from Kefeng Wang 

changes since v4 by addressing comments from Xiaofei:
- do a force kill only for abnormal sync errors

changes since v3 by addressing comments from Xiaofei:
- do a force kill for abnormal memory failure error such as invalid PA,
unexpected severity, OOM, etc
- pcik up tested-by tag from Ma Wupeng

changes since v2 by addressing comments from Naoya:
- rename mce_task_work to sync_task_work
- drop ACPI_HEST_NOTIFY_MCE case in is_hest_sync_notify()
- add steps to reproduce this problem in cover letter

changes since v1:
- synchronous events by notify type
- Link: https://lore.kernel.org/lkml/20221206153354.92394-3-xueshuai@linux.alibaba.com/


Shuai Xue (2):
  ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on
    synchronous events
  ACPI: APEI: handle synchronous exceptions in task work

 arch/x86/kernel/cpu/mce/core.c |   9 +--
 drivers/acpi/apei/ghes.c       | 113 ++++++++++++++++++++++-----------
 include/acpi/ghes.h            |   3 -
 mm/memory-failure.c            |  17 +----
 4 files changed, 79 insertions(+), 63 deletions(-)

-- 
2.20.1.12.g72788fdb


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RESEND PATCH v7 1/2] ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on synchronous events
  2023-06-06  7:42 [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code Shuai Xue
@ 2023-06-06  7:42 ` Shuai Xue
  2023-06-06  7:42 ` [RESEND PATCH v7 2/2] ACPI: APEI: handle synchronous exceptions in task work Shuai Xue
  2023-06-16  7:15 ` [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code Shuai Xue
  2 siblings, 0 replies; 7+ messages in thread
From: Shuai Xue @ 2023-06-06  7:42 UTC (permalink / raw)
  To: rafael, wangkefeng.wang, tanxiaofei, mawupeng1, tony.luck,
	naoya.horiguchi
  Cc: linux-acpi, linux-mm, linux-kernel, xueshuai, justin.he, akpm,
	ardb, ashish.kalra, baolin.wang, bp, cuibixuan, dave.hansen,
	james.morse, jarkko, lenb, linmiaohe, lvying6, xiexiuqi,
	zhuo.song

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 <xueshuai@linux.alibaba.com>
Tested-by: Ma Wupeng <mawupeng1@huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Reviewed-by: Xiaofei Tan <tanxiaofei@huawei.com>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
---
 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);
 
-- 
2.20.1.12.g72788fdb


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RESEND PATCH v7 2/2] ACPI: APEI: handle synchronous exceptions in task work
  2023-06-06  7:42 [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code Shuai Xue
  2023-06-06  7:42 ` [RESEND PATCH v7 1/2] ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on synchronous events Shuai Xue
@ 2023-06-06  7:42 ` Shuai Xue
  2023-06-16  7:15 ` [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code Shuai Xue
  2 siblings, 0 replies; 7+ messages in thread
From: Shuai Xue @ 2023-06-06  7:42 UTC (permalink / raw)
  To: rafael, wangkefeng.wang, tanxiaofei, mawupeng1, tony.luck,
	naoya.horiguchi
  Cc: linux-acpi, linux-mm, linux-kernel, xueshuai, justin.he, akpm,
	ardb, ashish.kalra, baolin.wang, bp, cuibixuan, dave.hansen,
	james.morse, jarkko, lenb, linmiaohe, lvying6, xiexiuqi,
	zhuo.song

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 <xueshuai@linux.alibaba.com>
Tested-by: Ma Wupeng <mawupeng1@huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Reviewed-by: Xiaofei Tan <tanxiaofei@huawei.com>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
---
 arch/x86/kernel/cpu/mce/core.c |  9 +---
 drivers/acpi/apei/ghes.c       | 84 +++++++++++++++++++++-------------
 include/acpi/ghes.h            |  3 --
 mm/memory-failure.c            | 17 ++-----
 4 files changed, 56 insertions(+), 57 deletions(-)

diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
index 2eec60f50057..2ebaaa494ac4 100644
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -1311,17 +1311,10 @@ static void kill_me_maybe(struct callback_head *cb)
 		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");
+	pr_err("Sending SIGBUS to current task due to memory error not recovered");
 	kill_me_now(cb);
 }
 
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index c479b85899f5..b41d4e462b36 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -452,28 +452,41 @@ 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 || ret == -EHWPOISON || ret == -EOPNOTSUPP)
+		return;
+
+	pr_err("Sending SIGBUS to current task due to 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 +499,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;
 }
@@ -654,7 +679,7 @@ static void ghes_defer_non_standard_event(struct acpi_hest_generic_data *gdata,
 	schedule_work(&entry->work);
 }
 
-static bool ghes_do_proc(struct ghes *ghes,
+static void ghes_do_proc(struct ghes *ghes,
 			 const struct acpi_hest_generic_status *estatus)
 {
 	int sev, sec_sev;
@@ -698,7 +723,14 @@ static bool ghes_do_proc(struct ghes *ghes,
 		}
 	}
 
-	return queued;
+	/*
+	 * If no memory failure work is queued for abnormal synchronous
+	 * errors, do a force kill.
+	 */
+	if (sync && !queued) {
+		pr_err("Sending SIGBUS to current task due to memory error not recovered");
+		force_sig(SIGBUS);
+	}
 }
 
 static void __ghes_print_estatus(const char *pfx,
@@ -1000,9 +1032,7 @@ 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;
 	u32 len, node_len;
-	int ret;
 
 	llnode = llist_del_all(&ghes_estatus_llist);
 	/*
@@ -1017,25 +1047,16 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
 		estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
 		len = cper_estatus_len(estatus);
 		node_len = GHES_ESTATUS_NODE_LEN(len);
-		task_work_pending = ghes_do_proc(estatus_node->ghes, estatus);
+
+		ghes_do_proc(estatus_node->ghes, estatus);
+
 		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 +1117,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 5b663eca1f29..50e9583051ed 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -2134,7 +2134,9 @@ static DEFINE_MUTEX(mf_mutex);
  *
  * Return: 0 for successfully handled the memory error,
  *         -EOPNOTSUPP for hwpoison_filter() filtered the error event,
- *         < 0(except -EOPNOTSUPP) on failure.
+ *         -EHWPOISON for already sent SIGBUS to the current process with
+ *         the proper error info,
+ *         other negative error code on failure.
  */
 int memory_failure(unsigned long pfn, int flags)
 {
@@ -2416,19 +2418,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;
-- 
2.20.1.12.g72788fdb


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code
  2023-06-06  7:42 [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code Shuai Xue
  2023-06-06  7:42 ` [RESEND PATCH v7 1/2] ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on synchronous events Shuai Xue
  2023-06-06  7:42 ` [RESEND PATCH v7 2/2] ACPI: APEI: handle synchronous exceptions in task work Shuai Xue
@ 2023-06-16  7:15 ` Shuai Xue
  2023-07-10  3:15   ` Shuai Xue
  2 siblings, 1 reply; 7+ messages in thread
From: Shuai Xue @ 2023-06-16  7:15 UTC (permalink / raw)
  To: rafael, wangkefeng.wang, tanxiaofei, mawupeng1, tony.luck,
	naoya.horiguchi
  Cc: linux-acpi, linux-mm, linux-kernel, justin.he, akpm, ardb,
	ashish.kalra, baolin.wang, bp, cuibixuan, dave.hansen,
	james.morse, jarkko, lenb, linmiaohe, lvying6, xiexiuqi,
	zhuo.song



On 2023/6/6 15:42, Shuai Xue wrote:
> changes since v6:
> - add more explicty error message suggested by Xiaofei
> - pick up reviewed-by tag from Xiaofei
> - pick up internal reviewed-by tag from Baolin
> 
> changes since v5 by addressing comments from Kefeng:
> - document return value of memory_failure()
> - drop redundant comments in call site of memory_failure() 
> - make ghes_do_proc void and handle abnormal case within it
> - pick up reviewed-by tag from Kefeng Wang 
> 
> changes since v4 by addressing comments from Xiaofei:
> - do a force kill only for abnormal sync errors
> 
> changes since v3 by addressing comments from Xiaofei:
> - do a force kill for abnormal memory failure error such as invalid PA,
> unexpected severity, OOM, etc
> - pcik up tested-by tag from Ma Wupeng
> 
> changes since v2 by addressing comments from Naoya:
> - rename mce_task_work to sync_task_work
> - drop ACPI_HEST_NOTIFY_MCE case in is_hest_sync_notify()
> - add steps to reproduce this problem in cover letter
> 
> changes since v1:
> - synchronous events by notify type
> - Link: https://lore.kernel.org/lkml/20221206153354.92394-3-xueshuai@linux.alibaba.com/
> 
> 
> Shuai Xue (2):
>   ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on
>     synchronous events
>   ACPI: APEI: handle synchronous exceptions in task work
> 
>  arch/x86/kernel/cpu/mce/core.c |   9 +--
>  drivers/acpi/apei/ghes.c       | 113 ++++++++++++++++++++++-----------
>  include/acpi/ghes.h            |   3 -
>  mm/memory-failure.c            |  17 +----
>  4 files changed, 79 insertions(+), 63 deletions(-)
> 


Hi, Rafael,

Gentle ping.

Are you happy to queue this patch set or anything I can do to improve it?
As @Kefeng said, this issue is met in Alibaba and Huawei products, we hope it
could be fixed ASAP.

Thank you.

Best Regards,
Shuai

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code
  2023-06-16  7:15 ` [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code Shuai Xue
@ 2023-07-10  3:15   ` Shuai Xue
  2023-08-08  3:17     ` Shuai Xue
  0 siblings, 1 reply; 7+ messages in thread
From: Shuai Xue @ 2023-07-10  3:15 UTC (permalink / raw)
  To: rafael, wangkefeng.wang, tanxiaofei, mawupeng1, tony.luck,
	naoya.horiguchi
  Cc: linux-acpi, linux-mm, linux-kernel, justin.he, akpm, ardb,
	ashish.kalra, baolin.wang, bp, cuibixuan, dave.hansen,
	james.morse, jarkko, lenb, linmiaohe, lvying6, xiexiuqi,
	zhuo.song



On 2023/6/16 15:15, Shuai Xue wrote:
> 
> 
> On 2023/6/6 15:42, Shuai Xue wrote:
>> changes since v6:
>> - add more explicty error message suggested by Xiaofei
>> - pick up reviewed-by tag from Xiaofei
>> - pick up internal reviewed-by tag from Baolin
>>
>> changes since v5 by addressing comments from Kefeng:
>> - document return value of memory_failure()
>> - drop redundant comments in call site of memory_failure() 
>> - make ghes_do_proc void and handle abnormal case within it
>> - pick up reviewed-by tag from Kefeng Wang 
>>
>> changes since v4 by addressing comments from Xiaofei:
>> - do a force kill only for abnormal sync errors
>>
>> changes since v3 by addressing comments from Xiaofei:
>> - do a force kill for abnormal memory failure error such as invalid PA,
>> unexpected severity, OOM, etc
>> - pcik up tested-by tag from Ma Wupeng
>>
>> changes since v2 by addressing comments from Naoya:
>> - rename mce_task_work to sync_task_work
>> - drop ACPI_HEST_NOTIFY_MCE case in is_hest_sync_notify()
>> - add steps to reproduce this problem in cover letter
>>
>> changes since v1:
>> - synchronous events by notify type
>> - Link: https://lore.kernel.org/lkml/20221206153354.92394-3-xueshuai@linux.alibaba.com/
>>
>>
>> Shuai Xue (2):
>>   ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on
>>     synchronous events
>>   ACPI: APEI: handle synchronous exceptions in task work
>>
>>  arch/x86/kernel/cpu/mce/core.c |   9 +--
>>  drivers/acpi/apei/ghes.c       | 113 ++++++++++++++++++++++-----------
>>  include/acpi/ghes.h            |   3 -
>>  mm/memory-failure.c            |  17 +----
>>  4 files changed, 79 insertions(+), 63 deletions(-)
>>
> 
> 
> Hi, Rafael,
> 
> Gentle ping.
> 
> Are you happy to queue this patch set or anything I can do to improve it?
> As @Kefeng said, this issue is met in Alibaba and Huawei products, we hope it
> could be fixed ASAP.

Hi Rafael, Tony, and Naoya,

Gentle ping. I am sorry to see that we have missed v6.3 and v6.4 merge window
since three Reviewed-by tags and one Tested-by tag.

Do we still need any designated APEI reviewers Reviewed-by? Could you give me your
Reviewed-by @Tony, and @Naoya if you are happy with the change.

Or Please could you Ack this change if you are happy with the proposal and the
change? @Rafael

> 
> Thank you.
> 
> Best Regards,
> Shuai

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code
  2023-07-10  3:15   ` Shuai Xue
@ 2023-08-08  3:17     ` Shuai Xue
  2023-09-11  0:44       ` Shuai Xue
  0 siblings, 1 reply; 7+ messages in thread
From: Shuai Xue @ 2023-08-08  3:17 UTC (permalink / raw)
  To: rafael, wangkefeng.wang, tanxiaofei, mawupeng1, tony.luck,
	naoya.horiguchi, james.morse
  Cc: linux-acpi, linux-mm, linux-kernel, justin.he, akpm, ardb,
	ashish.kalra, baolin.wang, bp, cuibixuan, dave.hansen, jarkko,
	lenb, linmiaohe, lvying6, xiexiuqi, zhuo.song



On 2023/7/10 11:15, Shuai Xue wrote:
> 
> 
> On 2023/6/16 15:15, Shuai Xue wrote:
>>
>>
>> On 2023/6/6 15:42, Shuai Xue wrote:
>>> changes since v6:
>>> - add more explicty error message suggested by Xiaofei
>>> - pick up reviewed-by tag from Xiaofei
>>> - pick up internal reviewed-by tag from Baolin
>>>
>>> changes since v5 by addressing comments from Kefeng:
>>> - document return value of memory_failure()
>>> - drop redundant comments in call site of memory_failure() 
>>> - make ghes_do_proc void and handle abnormal case within it
>>> - pick up reviewed-by tag from Kefeng Wang 
>>>
>>> changes since v4 by addressing comments from Xiaofei:
>>> - do a force kill only for abnormal sync errors
>>>
>>> changes since v3 by addressing comments from Xiaofei:
>>> - do a force kill for abnormal memory failure error such as invalid PA,
>>> unexpected severity, OOM, etc
>>> - pcik up tested-by tag from Ma Wupeng
>>>
>>> changes since v2 by addressing comments from Naoya:
>>> - rename mce_task_work to sync_task_work
>>> - drop ACPI_HEST_NOTIFY_MCE case in is_hest_sync_notify()
>>> - add steps to reproduce this problem in cover letter
>>>
>>> changes since v1:
>>> - synchronous events by notify type
>>> - Link: https://lore.kernel.org/lkml/20221206153354.92394-3-xueshuai@linux.alibaba.com/
>>>
>>>
>>> Shuai Xue (2):
>>>   ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on
>>>     synchronous events
>>>   ACPI: APEI: handle synchronous exceptions in task work
>>>
>>>  arch/x86/kernel/cpu/mce/core.c |   9 +--
>>>  drivers/acpi/apei/ghes.c       | 113 ++++++++++++++++++++++-----------
>>>  include/acpi/ghes.h            |   3 -
>>>  mm/memory-failure.c            |  17 +----
>>>  4 files changed, 79 insertions(+), 63 deletions(-)
>>>
>>
>>
>> Hi, Rafael,
>>
>> Gentle ping.
>>
>> Are you happy to queue this patch set or anything I can do to improve it?
>> As @Kefeng said, this issue is met in Alibaba and Huawei products, we hope it
>> could be fixed ASAP.
> 
> Hi Rafael, Tony, and Naoya,
> 
> Gentle ping. I am sorry to see that we have missed v6.3 and v6.4 merge window
> since three Reviewed-by tags and one Tested-by tag.
> 
> Do we still need any designated APEI reviewers Reviewed-by? Could you give me your
> Reviewed-by @Tony, and @Naoya if you are happy with the change.
> 
> Or Please could you Ack this change if you are happy with the proposal and the
> change? @Rafael
> 

Hi, ALL,

Gentle ping.

>>
>> Thank you.
>>
>> Best Regards,
>> Shuai

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code
  2023-08-08  3:17     ` Shuai Xue
@ 2023-09-11  0:44       ` Shuai Xue
  0 siblings, 0 replies; 7+ messages in thread
From: Shuai Xue @ 2023-09-11  0:44 UTC (permalink / raw)
  To: rafael, wangkefeng.wang, tanxiaofei, mawupeng1, tony.luck,
	naoya.horiguchi, james.morse, gregkh, Will Deacon
  Cc: linux-acpi, linux-mm, linux-kernel, justin.he, akpm, ardb,
	ashish.kalra, baolin.wang, bp, cuibixuan, dave.hansen, jarkko,
	lenb, linmiaohe, lvying6, xiexiuqi, zhuo.song, stable



On 2023/8/8 11:17, Shuai Xue wrote:
> 
> 
> On 2023/7/10 11:15, Shuai Xue wrote:
>>
>>
>> On 2023/6/16 15:15, Shuai Xue wrote:
>>>
>>>
>>> On 2023/6/6 15:42, Shuai Xue wrote:
>>>> changes since v6:
>>>> - add more explicty error message suggested by Xiaofei
>>>> - pick up reviewed-by tag from Xiaofei
>>>> - pick up internal reviewed-by tag from Baolin
>>>>
>>>> changes since v5 by addressing comments from Kefeng:
>>>> - document return value of memory_failure()
>>>> - drop redundant comments in call site of memory_failure() 
>>>> - make ghes_do_proc void and handle abnormal case within it
>>>> - pick up reviewed-by tag from Kefeng Wang 
>>>>
>>>> changes since v4 by addressing comments from Xiaofei:
>>>> - do a force kill only for abnormal sync errors
>>>>
>>>> changes since v3 by addressing comments from Xiaofei:
>>>> - do a force kill for abnormal memory failure error such as invalid PA,
>>>> unexpected severity, OOM, etc
>>>> - pcik up tested-by tag from Ma Wupeng
>>>>
>>>> changes since v2 by addressing comments from Naoya:
>>>> - rename mce_task_work to sync_task_work
>>>> - drop ACPI_HEST_NOTIFY_MCE case in is_hest_sync_notify()
>>>> - add steps to reproduce this problem in cover letter
>>>>
>>>> changes since v1:
>>>> - synchronous events by notify type
>>>> - Link: https://lore.kernel.org/lkml/20221206153354.92394-3-xueshuai@linux.alibaba.com/
>>>>
>>>>
>>>> Shuai Xue (2):
>>>>   ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on
>>>>     synchronous events
>>>>   ACPI: APEI: handle synchronous exceptions in task work
>>>>
>>>>  arch/x86/kernel/cpu/mce/core.c |   9 +--
>>>>  drivers/acpi/apei/ghes.c       | 113 ++++++++++++++++++++++-----------
>>>>  include/acpi/ghes.h            |   3 -
>>>>  mm/memory-failure.c            |  17 +----
>>>>  4 files changed, 79 insertions(+), 63 deletions(-)
>>>>
>>>
>>>
>>> Hi, Rafael,
>>>
>>> Gentle ping.
>>>
>>> Are you happy to queue this patch set or anything I can do to improve it?
>>> As @Kefeng said, this issue is met in Alibaba and Huawei products, we hope it
>>> could be fixed ASAP.
>>
>> Hi Rafael, Tony, and Naoya,
>>
>> Gentle ping. I am sorry to see that we have missed v6.3 and v6.4 merge window
>> since three Reviewed-by tags and one Tested-by tag.
>>
>> Do we still need any designated APEI reviewers Reviewed-by? Could you give me your
>> Reviewed-by @Tony, and @Naoya if you are happy with the change.
>>
>> Or Please could you Ack this change if you are happy with the proposal and the
>> change? @Rafael
>>
> 
> Hi, ALL,
> 
> Gentle ping.
> 

Hi, ALL,

I have rewritten the cover letter with the hope that the maintainer will truly
understand the necessity of this patch. Both Alibaba and Huawei met the same
issue in products, and we hope it could be fixed ASAP.

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 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 error.

The main difference between AR and AO errors is that AR errors are synchronous
events, while AO errors are asynchronous events. Synchronous exceptions, such as
Machine Check Exception (MCE) on X86 and Synchronous External Abort (SEA) on
Arm64, are signaled by the hardware when an error is detected and the memory
access has architecturally been executed.

Currently, both synchronous and asynchronous errors are queued as AO errors and
handled by a dedicated kernel thread in a work queue on the ARM64 platform. For
synchronous errors, memory_failure() is synced using a cancel_work_sync trick to
ensure that the corrupted page is unmapped and poisoned. Upon returning to
user-space, the process resumes at the current instruction, triggering a page
fault. As a result, the kernel sends a SIGBUS signal to the current process due
to VM_FAULT_HWPOISON.

However, this trick is not always be effective, this patch set improves the
recovery process in three specific aspects:

1. Handle synchronous exceptions with proper si_code

ghes_handle_memory_failure() queue both synchronous and asynchronous errors with
flag=0. Then the kernel will notify the process by sending a SIGBUS signal in
memory_failure() with wrong si_code: BUS_MCEERR_AO to the actual user-space
process instead of BUS_MCEERR_AR. The user-space processes rely on the si_code
to distinguish to handle memory failure.

For example, hwpoison-aware user-space processes use the si_code: BUS_MCEERR_AO
for 'action optional' early notifications, and BUS_MCEERR_AR for 'action
required' synchronous/late notifications. Specifically, when a SIGBUS_MCEERR_AR
synchronous signal is delivered to QEMU, it will inject a vSEA to Guest
kernel.[1]

Fix it by seting memory failure flags as MF_ACTION_REQUIRED on synchronous events. (PATCH 1)

2. Handle memory_failure() abnormal fails to avoid a unnecessary reboot

If process mapping fault page, but memory_failure() abnormal return before
try_to_unmap(), for example, the fault page process mapping is KSM page.
In this case, arm64 cannot use the page fault process to terminate the
synchronous exception loop.

This loop can potentially exceed the platform firmware threshold or even trigger
a kernel hard lockup, leading to a system reboot. However, kernel has the
capability to recover from this error.

Fix it by performing a force kill when memory_failure() abnormal fails or when
other abnormal synchronous errors occur. These errors can include situations
such as invalid PA, unexpected severity, no memory failure config support,
invalid GUID section, OOM, etc. (PATCH 2)

3. Handle memory_failure() in current process context which consuming poison

When synchronous errors occur, memory_failure() assume that current process
context is exactly that consuming poison synchronous error.

For example, kill_accessing_process() holds mmap locking of current->mm, does
pagetable walk to find the error virtual address, and sends SIGBUS to the
current process with error info. However, the mm of kworker is not valid,
resulting in a null-pointer dereference. I have fixed this in[3].

	commit 77677cdbc2aa mm,hwpoison: check mm when killing accessing process

Another example is that collect_procs()/kill_procs() walk the task list, only
collect and send sigbus to task which consuming poison. But memory_failure() is
queued and handled by a dedicated kernel thread on arm64 platform.

Fix it by queuing memory_failure() as a task work which runs in current
execution context to synchronously send SIGBUS before ret_to_user. (PATCH 2)

Lv Ying and XiuQi from Huawei also proposed to address similar problem[2][4].
Acknowledge to discussion with them.

To reproduce this problem:

	# STEP1: enable early kill mode
	#sysctl -w vm.memory_failure_early_kill=1
	vm.memory_failure_early_kill = 1

	# STEP2: inject an UCE error and consume it to trigger a synchronous error
	#einj_mem_uc single
	0: single   vaddr = 0xffffb0d75400 paddr = 4092d55b400
	injecting ...
	triggering ...
	signal 7 code 5 addr 0xffffb0d75000
	page not present
	Test passed

The si_code (code 5) from einj_mem_uc indicates that it is BUS_MCEERR_AO error
and it is not fact.

After this patch set:

	# STEP1: enable early kill mode
	#sysctl -w vm.memory_failure_early_kill=1
	vm.memory_failure_early_kill = 1

	# STEP2: inject an UCE error and consume it to trigger a synchronous error
	#einj_mem_uc single
	0: single   vaddr = 0xffffb0d75400 paddr = 4092d55b400
	injecting ...
	triggering ...
	signal 7 code 4 addr 0xffffb0d75000
	page not present
	Test passed

The si_code (code 4) from einj_mem_uc indicates that it is BUS_MCEERR_AR error
as we expected.

[1] Add ARMv8 RAS virtualization support in QEMU https://patchew.org/QEMU/20200512030609.19593-1-gengdongjiu@huawei.com/
[2] https://lore.kernel.org/lkml/20221205115111.131568-3-lvying6@huawei.com/
[3] https://lkml.kernel.org/r/20220914064935.7851-1-xueshuai@linux.alibaba.com
[4] https://lore.kernel.org/lkml/20221209095407.383211-1-lvying6@huawei.com/


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-09-11  0:44 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-06  7:42 [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code Shuai Xue
2023-06-06  7:42 ` [RESEND PATCH v7 1/2] ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on synchronous events Shuai Xue
2023-06-06  7:42 ` [RESEND PATCH v7 2/2] ACPI: APEI: handle synchronous exceptions in task work Shuai Xue
2023-06-16  7:15 ` [RESEND PATCH v7 0/2] ACPI: APEI: handle synchronous exceptions with proper si_code Shuai Xue
2023-07-10  3:15   ` Shuai Xue
2023-08-08  3:17     ` Shuai Xue
2023-09-11  0:44       ` Shuai Xue

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®