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);