Blob Blame History Raw
From: Jiri Bohac <jbohac@suse.cz>
Subject: kdump: wait for DMA to time out when using CMA
Patch-mainline: Submitted, 2023-11-24 https://lore.kernel.org/lkml/ZWD_fAPqEWkFlEkM@dwarf.suse.cz/
References: jsc#PED-7249

When re-using the CMA area for kdump there is a risk
of pending DMA into pinned user pages in the CMA area.

Pages that are pinned long-term are migrated away from CMA, so these are not a
concern. Only pages pinned without the FOLL_LONGTERM.

I believe waiting for 1 second before reusing them should be safe enough.

Acked-by: Jiri Bohac <jbohac@suse.cz>
---
 include/linux/crash_core.h |  1 +
 kernel/crash_core.c        | 11 +++++++++++
 kernel/kexec_core.c        |  1 +
 3 files changed, 13 insertions(+)

diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h
index 97db2374b493..f0cef9ce95b0 100644
--- a/include/linux/crash_core.h
+++ b/include/linux/crash_core.h
@@ -20,6 +20,7 @@ extern int crashk_cma_cnt;
 #else
 #define crashk_cma_cnt 0
 #endif
+void crash_cma_clear_pending_dma(void);
 
 #define CRASH_CORE_NOTE_NAME	   "CORE"
 #define CRASH_CORE_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index d71ecd59f16b..d85f370c1e5d 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -16,6 +16,7 @@
 #include <linux/kexec.h>
 #include <linux/kmemleak.h>
 #include <linux/cma.h>
+#include <linux/delay.h>
 
 #include <asm/page.h>
 #include <asm/sections.h>
@@ -25,6 +26,8 @@
 #include "kallsyms_internal.h"
 #include "kexec_internal.h"
 
+#define CMA_DMA_TIMEOUT_MSEC 1000
+
 /* Per cpu memory for storing cpu states in case of system crash. */
 note_buf_t __percpu *crash_notes;
 
@@ -527,6 +530,14 @@ void __init reserve_crashkernel_cma(unsigned long long cma_size)
 }
 #endif
 
+void crash_cma_clear_pending_dma(void)
+{
+	if (!crashk_cma_cnt)
+		return;
+
+	mdelay(CMA_DMA_TIMEOUT_MSEC);
+}
+
 int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map,
 			  void **addr, unsigned long *sz)
 {
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index be5642a4ec49..5d26b49e7cee 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -1044,6 +1044,7 @@ void __noclone __crash_kexec(struct pt_regs *regs)
 		if (kexec_crash_image) {
 			struct pt_regs fixed_regs;
 
+			crash_cma_clear_pending_dma();
 			crash_setup_regs(&fixed_regs, regs);
 			crash_save_vmcoreinfo();
 			machine_crash_shutdown(&fixed_regs);