* [PATCH] riscv: crash: Add crash hotplug support
@ 2026-09-08 12:51 Rui Qi
2026-09-09 21:30 ` kernel test robot
0 siblings, 1 reply; 2+ messages in thread
From: Rui Qi @ 2026-09-08 12:51 UTC (permalink / raw)
To: palmer, pjw, aou, alex
Cc: Rui Qi, Deepak Gupta, Kees Cook, Charles Mirabile, Drew Fustini,
Martin Kaiser, open list:RISC-V ARCHITECTURE, open list
When CPUs or memory are hot-plugged on a running system, the crash
dump's elfcorehdr -- which describes the available CPUs and memory to
the capture kernel -- must be kept in sync, otherwise a crash after a
hotplug event would produce a vmcore that does not reflect the current
system topology.
Enable crash hotplug for RISC-V by selecting
ARCH_SUPPORTS_CRASH_HOTPLUG and providing the three architecture hooks
invoked through the override macros in <asm/kexec.h>:
arch_crash_hotplug_support() reports whether an image supports the
mechanism; arch_crash_get_elfcorehdr_size() sizes the segment for
NR_CPUS and, with memory hotplug, CRASH_MAX_MEMORY_RANGES;
arch_crash_handle_hotplug_event() rebuilds the elfcorehdr through the
crash_prepare_headers() helper and writes it over the old segment.
The elfcorehdr is copied with memcpy_flushcache(), matching the x86
implementation; on RISC-V this currently expands to a plain memcpy()
and will benefit automatically once the architecture provides a
flushcache backend. The implementation otherwise follows the x86 crash
hotplug model.
Signed-off-by: Rui Qi <qirui.001@bytedance.com>
Tested-by: Rui Qi <qirui.001@bytedance.com>
---
Testing performed:
Verified that kdump was loaded before each panic, then triggered a
sysrq panic under each of the following hotplug states:
- CPU1 offline only
- one memory block offline only
- two CPUs offline
- two memory blocks offline
- CPU and memory offline, held for 60 s before panic
Each case produced a valid vmcore that could be opened with the crash
tool. At panic time the observed state matched expectations: offline
CPUs were reflected in __cpu_online_mask, and offline memory blocks
appeared as MEM_OFFLINE. kdump worked correctly across all tested CPU
and memory hotplug offline scenarios.
---
arch/riscv/Kconfig | 3 +
arch/riscv/include/asm/kexec.h | 11 ++++
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/crash.c | 113 +++++++++++++++++++++++++++++++++
4 files changed, 128 insertions(+)
create mode 100644 arch/riscv/kernel/crash.c
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index ab7ca8f57420..123a6862dc10 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -1133,6 +1133,9 @@ config ARCH_DEFAULT_CRASH_DUMP
config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
def_bool CRASH_RESERVE
+config ARCH_SUPPORTS_CRASH_HOTPLUG
+ def_bool y
+
config COMPAT
bool "Kernel support for 32-bit U-mode"
default 64BIT
diff --git a/arch/riscv/include/asm/kexec.h b/arch/riscv/include/asm/kexec.h
index b9ee8346cc8c..de6b9b684a57 100644
--- a/arch/riscv/include/asm/kexec.h
+++ b/arch/riscv/include/asm/kexec.h
@@ -75,4 +75,15 @@ int load_extra_segments(struct kimage *image, unsigned long kernel_start,
unsigned long cmdline_len);
#endif
+#ifdef CONFIG_CRASH_HOTPLUG
+void arch_crash_handle_hotplug_event(struct kimage *image, void *arg);
+#define arch_crash_handle_hotplug_event arch_crash_handle_hotplug_event
+
+int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
+#define arch_crash_hotplug_support arch_crash_hotplug_support
+
+unsigned int arch_crash_get_elfcorehdr_size(void);
+#define crash_get_elfcorehdr_size arch_crash_get_elfcorehdr_size
+#endif
+
#endif
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index ebe1c3588177..d0a5d442110f 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -111,6 +111,7 @@ obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_KEXEC_CORE) += kexec_relocate.o crash_save_regs.o machine_kexec.o
obj-$(CONFIG_KEXEC_FILE) += kexec_elf.o kexec_image.o machine_kexec_file.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+obj-$(CONFIG_CRASH_HOTPLUG) += crash.o
obj-$(CONFIG_VMCORE_INFO) += vmcore_info.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
diff --git a/arch/riscv/kernel/crash.c b/arch/riscv/kernel/crash.c
new file mode 100644
index 000000000000..fe5a4b306aae
--- /dev/null
+++ b/arch/riscv/kernel/crash.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RISC-V crash hotplug support
+ *
+ * Copyright (C) 2025 Bytedance Ltd.
+ */
+
+#include <linux/kexec.h>
+#include <linux/crash_core.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#ifdef CONFIG_CRASH_HOTPLUG
+
+#undef pr_fmt
+#define pr_fmt(fmt) "crash hp: " fmt
+
+int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags)
+{
+#ifdef CONFIG_KEXEC_FILE
+ if (image->file_mode)
+ return 1;
+#endif
+ /*
+ * For the kexec_load() syscall path, the user space kexec tool
+ * needs to indicate that the elfcorehdr segment is excluded from
+ * SHA verification by setting the appropriate flags.
+ */
+ return (kexec_flags & KEXEC_UPDATE_ELFCOREHDR ||
+ kexec_flags & KEXEC_CRASH_HOTPLUG_SUPPORT);
+}
+
+unsigned int arch_crash_get_elfcorehdr_size(void)
+{
+ unsigned int sz;
+
+ /* kernel_map, VMCOREINFO and maximum CPUs */
+ sz = 2 + CONFIG_NR_CPUS;
+ if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+ sz += CONFIG_CRASH_MAX_MEMORY_RANGES;
+ sz *= sizeof(Elf64_Phdr);
+ return sz;
+}
+
+/**
+ * arch_crash_handle_hotplug_event() - Handle hotplug elfcorehdr changes
+ * @image: a pointer to kexec_crash_image
+ * @arg: struct memory_notify handler for memory hotplug case and
+ * NULL for CPU hotplug case.
+ *
+ * Prepare the new elfcorehdr and replace the existing elfcorehdr.
+ */
+void arch_crash_handle_hotplug_event(struct kimage *image, void *arg)
+{
+ void *elfbuf = NULL, *old_elfcorehdr;
+ unsigned long mem, memsz;
+ unsigned long elfsz = 0;
+
+ /*
+ * As crash_prepare_elf64_headers() has already described all
+ * possible CPUs, there is no need to update the elfcorehdr
+ * for additional CPU changes.
+ */
+ if ((image->file_mode || image->elfcorehdr_updated) &&
+ ((image->hp_action == KEXEC_CRASH_HP_ADD_CPU) ||
+ (image->hp_action == KEXEC_CRASH_HP_REMOVE_CPU)))
+ return;
+
+ /*
+ * Create the new elfcorehdr reflecting the changes to CPU and/or
+ * memory resources.
+ */
+ if (crash_prepare_headers(true, &elfbuf, &elfsz, NULL)) {
+ pr_err("unable to create new elfcorehdr");
+ goto out;
+ }
+
+ /*
+ * Obtain address and size of the elfcorehdr segment, and
+ * check it against the new elfcorehdr buffer.
+ */
+ mem = image->segment[image->elfcorehdr_index].mem;
+ memsz = image->segment[image->elfcorehdr_index].memsz;
+ if (elfsz > memsz) {
+ pr_err("update elfcorehdr elfsz %lu > memsz %lu",
+ elfsz, memsz);
+ goto out;
+ }
+
+ /*
+ * Copy new elfcorehdr over the old elfcorehdr at destination.
+ */
+ old_elfcorehdr = kmap_local_page(pfn_to_page(mem >> PAGE_SHIFT));
+ if (!old_elfcorehdr) {
+ pr_err("mapping elfcorehdr segment failed\n");
+ goto out;
+ }
+
+ /*
+ * Temporarily invalidate the crash image while the
+ * elfcorehdr is updated.
+ */
+ xchg(&kexec_crash_image, NULL);
+ memcpy_flushcache(old_elfcorehdr, elfbuf, elfsz);
+ xchg(&kexec_crash_image, image);
+ kunmap_local(old_elfcorehdr);
+ pr_debug("updated elfcorehdr\n");
+
+out:
+ vfree(elfbuf);
+}
+
+#endif /* CONFIG_CRASH_HOTPLUG */
--
2.20.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] riscv: crash: Add crash hotplug support
2026-09-08 12:51 [PATCH] riscv: crash: Add crash hotplug support Rui Qi
@ 2026-09-09 21:30 ` kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2026-09-09 21:30 UTC (permalink / raw)
To: Rui Qi, palmer, pjw, aou, alex
Cc: oe-kbuild-all, Rui Qi, Deepak Gupta, Kees Cook, Charles Mirabile,
Drew Fustini, Martin Kaiser, open list:RISC-V ARCHITECTURE,
open list
Hi Rui,
kernel test robot noticed the following build errors:
[auto build test ERROR on kees/for-next/kspp]
[also build test ERROR on linus/master kees/for-next/pstore v7.3-rc2 next-20260909]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Rui-Qi/riscv-crash-Add-crash-hotplug-support/20260908-205143
base: https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/kspp
patch link: https://lore.kernel.org/r/20260908125155.1777895-1-qirui.001%40bytedance.com
patch subject: [PATCH] riscv: crash: Add crash hotplug support
config: riscv-randconfig-r071-20260910 (https://download.01.org/0day-ci/archive/20260910/202609100553.E6HUYviI-lkp@intel.com/config)
compiler: clang version 21.1.8 (https://github.com/llvm/llvm-project 2078da43e25a4623cab2d0d60decddf709aaea28)
smatch: v0.5.0-9187-g5189e3fb
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260910/202609100553.E6HUYviI-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609100553.E6HUYviI-lkp@intel.com/
All error/warnings (new ones prefixed by >>):
In file included from kernel/crash_reserve.c:12:
In file included from include/linux/kexec.h:38:
>> arch/riscv/include/asm/kexec.h:79:45: warning: declaration of 'struct kimage' will not be visible outside of this function [-Wvisibility]
79 | void arch_crash_handle_hotplug_event(struct kimage *image, void *arg);
| ^
arch/riscv/include/asm/kexec.h:82:39: warning: declaration of 'struct kimage' will not be visible outside of this function [-Wvisibility]
82 | int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
| ^
2 warnings generated.
--
In file included from kernel/kexec.c:13:
In file included from include/linux/kexec.h:38:
>> arch/riscv/include/asm/kexec.h:79:45: warning: declaration of 'struct kimage' will not be visible outside of this function [-Wvisibility]
79 | void arch_crash_handle_hotplug_event(struct kimage *image, void *arg);
| ^
arch/riscv/include/asm/kexec.h:82:39: warning: declaration of 'struct kimage' will not be visible outside of this function [-Wvisibility]
82 | int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
| ^
>> kernel/kexec.c:138:61: error: incompatible pointer types passing 'struct kimage *' to parameter of type 'struct kimage *' [-Werror,-Wincompatible-pointer-types]
138 | if ((flags & KEXEC_ON_CRASH) && arch_crash_hotplug_support(image, flags))
| ^~~~~
arch/riscv/include/asm/kexec.h:82:47: note: passing argument to parameter 'image' here
82 | int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
| ^
2 warnings and 1 error generated.
--
In file included from kernel/crash_core.c:14:
In file included from include/linux/kexec.h:38:
>> arch/riscv/include/asm/kexec.h:79:45: warning: declaration of 'struct kimage' will not be visible outside of this function [-Wvisibility]
79 | void arch_crash_handle_hotplug_event(struct kimage *image, void *arg);
| ^
arch/riscv/include/asm/kexec.h:82:39: warning: declaration of 'struct kimage' will not be visible outside of this function [-Wvisibility]
82 | int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
| ^
>> kernel/crash_core.c:718:34: error: incompatible pointer types passing 'struct kimage *' to parameter of type 'struct kimage *' [-Werror,-Wincompatible-pointer-types]
718 | arch_crash_handle_hotplug_event(image, arg);
| ^~~~~
arch/riscv/include/asm/kexec.h:79:53: note: passing argument to parameter 'image' here
79 | void arch_crash_handle_hotplug_event(struct kimage *image, void *arg);
| ^
2 warnings and 1 error generated.
--
In file included from arch/riscv/kernel/crash.c:8:
In file included from include/linux/kexec.h:38:
>> arch/riscv/include/asm/kexec.h:79:45: warning: declaration of 'struct kimage' will not be visible outside of this function [-Wvisibility]
79 | void arch_crash_handle_hotplug_event(struct kimage *image, void *arg);
| ^
arch/riscv/include/asm/kexec.h:82:39: warning: declaration of 'struct kimage' will not be visible outside of this function [-Wvisibility]
82 | int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
| ^
>> arch/riscv/kernel/crash.c:18:5: error: conflicting types for 'arch_crash_hotplug_support'
18 | int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags)
| ^
arch/riscv/include/asm/kexec.h:83:36: note: expanded from macro 'arch_crash_hotplug_support'
83 | #define arch_crash_hotplug_support arch_crash_hotplug_support
| ^
arch/riscv/include/asm/kexec.h:82:5: note: previous declaration is here
82 | int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
| ^
>> arch/riscv/kernel/crash.c:53:6: error: conflicting types for 'arch_crash_handle_hotplug_event'
53 | void arch_crash_handle_hotplug_event(struct kimage *image, void *arg)
| ^
arch/riscv/include/asm/kexec.h:80:41: note: expanded from macro 'arch_crash_handle_hotplug_event'
80 | #define arch_crash_handle_hotplug_event arch_crash_handle_hotplug_event
| ^
arch/riscv/include/asm/kexec.h:79:6: note: previous declaration is here
79 | void arch_crash_handle_hotplug_event(struct kimage *image, void *arg);
| ^
2 warnings and 2 errors generated.
vim +/arch_crash_hotplug_support +18 arch/riscv/kernel/crash.c
17
> 18 int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags)
19 {
20 #ifdef CONFIG_KEXEC_FILE
21 if (image->file_mode)
22 return 1;
23 #endif
24 /*
25 * For the kexec_load() syscall path, the user space kexec tool
26 * needs to indicate that the elfcorehdr segment is excluded from
27 * SHA verification by setting the appropriate flags.
28 */
29 return (kexec_flags & KEXEC_UPDATE_ELFCOREHDR ||
30 kexec_flags & KEXEC_CRASH_HOTPLUG_SUPPORT);
31 }
32
33 unsigned int arch_crash_get_elfcorehdr_size(void)
34 {
35 unsigned int sz;
36
37 /* kernel_map, VMCOREINFO and maximum CPUs */
38 sz = 2 + CONFIG_NR_CPUS;
39 if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
40 sz += CONFIG_CRASH_MAX_MEMORY_RANGES;
41 sz *= sizeof(Elf64_Phdr);
42 return sz;
43 }
44
45 /**
46 * arch_crash_handle_hotplug_event() - Handle hotplug elfcorehdr changes
47 * @image: a pointer to kexec_crash_image
48 * @arg: struct memory_notify handler for memory hotplug case and
49 * NULL for CPU hotplug case.
50 *
51 * Prepare the new elfcorehdr and replace the existing elfcorehdr.
52 */
> 53 void arch_crash_handle_hotplug_event(struct kimage *image, void *arg)
54 {
55 void *elfbuf = NULL, *old_elfcorehdr;
56 unsigned long mem, memsz;
57 unsigned long elfsz = 0;
58
59 /*
60 * As crash_prepare_elf64_headers() has already described all
61 * possible CPUs, there is no need to update the elfcorehdr
62 * for additional CPU changes.
63 */
64 if ((image->file_mode || image->elfcorehdr_updated) &&
65 ((image->hp_action == KEXEC_CRASH_HP_ADD_CPU) ||
66 (image->hp_action == KEXEC_CRASH_HP_REMOVE_CPU)))
67 return;
68
69 /*
70 * Create the new elfcorehdr reflecting the changes to CPU and/or
71 * memory resources.
72 */
73 if (crash_prepare_headers(true, &elfbuf, &elfsz, NULL)) {
74 pr_err("unable to create new elfcorehdr");
75 goto out;
76 }
77
78 /*
79 * Obtain address and size of the elfcorehdr segment, and
80 * check it against the new elfcorehdr buffer.
81 */
82 mem = image->segment[image->elfcorehdr_index].mem;
83 memsz = image->segment[image->elfcorehdr_index].memsz;
84 if (elfsz > memsz) {
85 pr_err("update elfcorehdr elfsz %lu > memsz %lu",
86 elfsz, memsz);
87 goto out;
88 }
89
90 /*
91 * Copy new elfcorehdr over the old elfcorehdr at destination.
92 */
93 old_elfcorehdr = kmap_local_page(pfn_to_page(mem >> PAGE_SHIFT));
94 if (!old_elfcorehdr) {
95 pr_err("mapping elfcorehdr segment failed\n");
96 goto out;
97 }
98
99 /*
100 * Temporarily invalidate the crash image while the
101 * elfcorehdr is updated.
102 */
103 xchg(&kexec_crash_image, NULL);
104 memcpy_flushcache(old_elfcorehdr, elfbuf, elfsz);
105 xchg(&kexec_crash_image, image);
106 kunmap_local(old_elfcorehdr);
107 pr_debug("updated elfcorehdr\n");
108
109 out:
110 vfree(elfbuf);
111 }
112
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-09 21:30 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 12:51 [PATCH] riscv: crash: Add crash hotplug support Rui Qi
2026-09-09 21:30 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox