All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] arm64: crash: Add crash hotplug support
@ 2026-07-29  3:12 Jinjie Ruan
  2026-07-29  3:12 ` [PATCH v2 1/5] kexec: Extract kexec_free_segment_cma() from kimage_free_cma() Jinjie Ruan
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Jinjie Ruan @ 2026-07-29  3:12 UTC (permalink / raw)
  To: catalin.marinas, will, akpm, baoquan.he, rppt, pasha.tatashin,
	pratyush, thuth, mark.rutland, jic23, james.morse, ardb, leitao,
	yeoreum.yun, sourabhjain, robh, kees, coxu, makb, piliu, graf,
	ebiggers, jbouron, bgwin, linux-arm-kernel, linux-kernel, kexec
  Cc: ruanjinjie

When CPU or memory hotplug events occur, the elfcorehdr in the kdump
image becomes stale, potentially leading to incomplete crash dumps.

Currently, userspace udev rules reload the entire kdump image upon such
events, which is inefficient and leaves kdump inactive for a long time.

Commit 247262756121 ("crash: add generic infrastructure for crash hotplug
support") introduced a kernel mechanism to update only the elfcorehdr.
This patch set implements crash hotplug support for arm64.

As Baoquan suggested, it also addresses and fixes several
pre-existing code issues and Sashiko AI review findings extracted
from the previous patch set.

The major improvements and fixes included in this series are:
- Fix several memory leaks for arm64.
- Simplify arm64 load_other_segments().
- Implement infrastructure for arm64 crash memory hotplug support.

This patch set is rebased on liveupdate/crashkernel-cma.

Link: https://lore.kernel.org/all/20260601094805.2928614-1-ruanjinjie@huawei.com/

Changes in v2:
- Split out Powerpc bugfix patch as Mike suggested.
- Use phys_to_virt() instead of __va() in update_crash_elfcorehdr().
- Convert pnum_hdr_sz() to a function.
- Only assign elfcorehdr_index after kexec_add_buffer succeeds, considering
  crash_handle_hotplug_event() already performs validity check on
  elfcorehdr_index:
  - We can safely remove the check for CPU hotplug
    in arch_crash_handle_hotplug_event().
  - The elfcorehdr_index's segment mem will be valid in
    update_crash_elfcorehdr(), so we can safely remove the NULL check.
- Simplify the commit message.
- v1: https://lore.kernel.org/all/20260723131242.1537633-1-ruanjinjie@huawei.com/#t

Jinjie Ruan (5):
  kexec: Extract kexec_free_segment_cma() from kimage_free_cma()
  arm64: kexec_file: Fix CMA page leaks in segment placement retry loops
  arm64: kexec_file: Fix image->elf_headers memory leak in retry loop
  arm64: kexec_file: Simplify load_other_segments()
  arm64: crash: Add crash hotplug support

 arch/arm64/Kconfig                     |   3 +
 arch/arm64/include/asm/kexec.h         |  16 +++
 arch/arm64/kernel/Makefile             |   2 +-
 arch/arm64/kernel/crash.c              | 143 +++++++++++++++++++++++++
 arch/arm64/kernel/kexec_image.c        |   1 +
 arch/arm64/kernel/machine_kexec_file.c |  78 +++++++-------
 include/linux/kexec.h                  |   2 +
 kernel/kexec_core.c                    |  25 +++--
 8 files changed, 216 insertions(+), 54 deletions(-)
 create mode 100644 arch/arm64/kernel/crash.c

-- 
2.34.1



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

* [PATCH v2 1/5] kexec: Extract kexec_free_segment_cma() from kimage_free_cma()
  2026-07-29  3:12 [PATCH v2 0/5] arm64: crash: Add crash hotplug support Jinjie Ruan
@ 2026-07-29  3:12 ` Jinjie Ruan
  2026-07-29  3:12 ` [PATCH v2 2/5] arm64: kexec_file: Fix CMA page leaks in segment placement retry loops Jinjie Ruan
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jinjie Ruan @ 2026-07-29  3:12 UTC (permalink / raw)
  To: catalin.marinas, will, akpm, baoquan.he, rppt, pasha.tatashin,
	pratyush, thuth, mark.rutland, jic23, james.morse, ardb, leitao,
	yeoreum.yun, sourabhjain, robh, kees, coxu, makb, piliu, graf,
	ebiggers, jbouron, bgwin, linux-arm-kernel, linux-kernel, kexec
  Cc: ruanjinjie

kimage_free_cma() relies on image->nr_segments to iterate over segments.
When an architecture loader (e.g., arm64) truncates nr_segments on a
mid-way failure, CMA pages allocated beyond the new boundary become
unreachable, causing silent memory leaks.

Extract the per-segment freeing logic into the exported helper
kexec_free_segment_cma(), so that architecture loaders can release
individual segments before nr_segments is truncated. Refactor
kimage_free_cma() to loop over the new helper, preserving existing
behavior.

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Baoquan He <baoquan.he@linux.dev>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: Pratyush Yadav <pratyush@kernel.org>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
 include/linux/kexec.h |  2 ++
 kernel/kexec_core.c   | 25 ++++++++++++++-----------
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 8a22bc9b8c6c..6f1eabda0300 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -532,6 +532,7 @@ extern bool kexec_file_dbg_print;
 
 extern void *kimage_map_segment(struct kimage *image, int idx);
 extern void kimage_unmap_segment(void *buffer);
+extern void kexec_free_segment_cma(struct kimage *image, unsigned long idx);
 #else /* !CONFIG_KEXEC_CORE */
 struct pt_regs;
 struct task_struct;
@@ -543,6 +544,7 @@ static inline int kexec_crash_loaded(void) { return 0; }
 static inline void *kimage_map_segment(struct kimage *image, int idx)
 { return NULL; }
 static inline void kimage_unmap_segment(void *buffer) { }
+static inline void kexec_free_segment_cma(struct kimage *image, unsigned long idx) { }
 #define kexec_in_progress false
 #endif /* CONFIG_KEXEC_CORE */
 
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index dc770b9a6d05..ec7e86e085b0 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -554,22 +554,25 @@ static void kimage_free_entry(kimage_entry_t entry)
 	kimage_free_pages(page);
 }
 
-static void kimage_free_cma(struct kimage *image)
+void kexec_free_segment_cma(struct kimage *image, unsigned long idx)
 {
-	unsigned long i;
+	u32 nr_pages = image->segment[idx].memsz >> PAGE_SHIFT;
+	struct page *cma = image->segment_cma[idx];
 
-	for (i = 0; i < image->nr_segments; i++) {
-		struct page *cma = image->segment_cma[i];
-		u32 nr_pages = image->segment[i].memsz >> PAGE_SHIFT;
+	if (!cma)
+		return;
 
-		if (!cma)
-			continue;
+	arch_kexec_pre_free_pages(page_address(cma), nr_pages);
+	dma_release_from_contiguous(NULL, cma, nr_pages);
+	image->segment_cma[idx] = NULL;
+}
 
-		arch_kexec_pre_free_pages(page_address(cma), nr_pages);
-		dma_release_from_contiguous(NULL, cma, nr_pages);
-		image->segment_cma[i] = NULL;
-	}
+static void kimage_free_cma(struct kimage *image)
+{
+	unsigned long i;
 
+	for (i = 0; i < image->nr_segments; i++)
+		kexec_free_segment_cma(image, i);
 }
 
 void kimage_free(struct kimage *image)
-- 
2.34.1



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

* [PATCH v2 2/5] arm64: kexec_file: Fix CMA page leaks in segment placement retry loops
  2026-07-29  3:12 [PATCH v2 0/5] arm64: crash: Add crash hotplug support Jinjie Ruan
  2026-07-29  3:12 ` [PATCH v2 1/5] kexec: Extract kexec_free_segment_cma() from kimage_free_cma() Jinjie Ruan
@ 2026-07-29  3:12 ` Jinjie Ruan
  2026-07-29  3:12 ` [PATCH v2 3/5] arm64: kexec_file: Fix image->elf_headers memory leak in retry loop Jinjie Ruan
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jinjie Ruan @ 2026-07-29  3:12 UTC (permalink / raw)
  To: catalin.marinas, will, akpm, baoquan.he, rppt, pasha.tatashin,
	pratyush, thuth, mark.rutland, jic23, james.morse, ardb, leitao,
	yeoreum.yun, sourabhjain, robh, kees, coxu, makb, piliu, graf,
	ebiggers, jbouron, bgwin, linux-arm-kernel, linux-kernel, kexec
  Cc: ruanjinjie

During kexec image placement retry loops, any midway failure causes
the loader to truncate `image->nr_segments` back to its initial state
to purge the failed segments.

However, this truncation introduces a memory leak. The CMA pages
allocated via kexec_add_buffer() during the failed attempt are tracked
in the `image->segment_cma` array. Because the subsequent cleanup paths
only iterate up to the truncated `nr_segments` boundary, these allocated
CMA pages outside the new boundary are permanently leaked.

Fix this by explicitly releasing the associated CMA buffers in
the failure paths before `image->nr_segments` is reduced.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Breno Leitao <leitao@debian.org>
Cc: Pratyush Yadav <pratyush@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Yeoreum Yun <yeoreum.yun@arm.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: stable@vger.kernel.org
Fixes: 07d24902977e4 ("kexec: enable CMA based contiguous allocation")
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
 arch/arm64/kernel/kexec_image.c        | 1 +
 arch/arm64/kernel/machine_kexec_file.c | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
index b70f4df15a1a..ffcb7f9075e6 100644
--- a/arch/arm64/kernel/kexec_image.c
+++ b/arch/arm64/kernel/kexec_image.c
@@ -107,6 +107,7 @@ static void *image_load(struct kimage *image,
 		 * We couldn't find space for the other segments; erase the
 		 * kernel segment and try the next available hole.
 		 */
+		kexec_free_segment_cma(image, kernel_segment_number);
 		image->nr_segments -= 1;
 		kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
 		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 854d872dfd0f..e48f29167b38 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -179,7 +179,10 @@ int load_other_segments(struct kimage *image,
 	return 0;
 
 out_err:
-	image->nr_segments = orig_segments;
+	while (image->nr_segments > orig_segments) {
+		kexec_free_segment_cma(image, image->nr_segments - 1);
+		image->nr_segments--;
+	}
 	kvfree(dtb);
 	return ret;
 }
-- 
2.34.1



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

* [PATCH v2 3/5] arm64: kexec_file: Fix image->elf_headers memory leak in retry loop
  2026-07-29  3:12 [PATCH v2 0/5] arm64: crash: Add crash hotplug support Jinjie Ruan
  2026-07-29  3:12 ` [PATCH v2 1/5] kexec: Extract kexec_free_segment_cma() from kimage_free_cma() Jinjie Ruan
  2026-07-29  3:12 ` [PATCH v2 2/5] arm64: kexec_file: Fix CMA page leaks in segment placement retry loops Jinjie Ruan
@ 2026-07-29  3:12 ` Jinjie Ruan
  2026-07-29  3:12 ` [PATCH v2 4/5] arm64: kexec_file: Simplify load_other_segments() Jinjie Ruan
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jinjie Ruan @ 2026-07-29  3:12 UTC (permalink / raw)
  To: catalin.marinas, will, akpm, baoquan.he, rppt, pasha.tatashin,
	pratyush, thuth, mark.rutland, jic23, james.morse, ardb, leitao,
	yeoreum.yun, sourabhjain, robh, kees, coxu, makb, piliu, graf,
	ebiggers, jbouron, bgwin, linux-arm-kernel, linux-kernel, kexec
  Cc: ruanjinjie

If load_other_segments() fails after image->elf_headers is assigned,
the memory lifecycle is safely managed by the global kimage object
and will be freed in arch_kimage_file_post_load_cleanup().

However, during a retry loop in image_load(), a subsequent iteration
will allocate a new buffer and overwrite image->elf_headers. This
permanently leaks the stale memory from the previous iteration before
the global cleanup can track it.

Fix this by explicitly freeing the stale `image->elf_headers` buffer
before assigning the newly allocated headers.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Breno Leitao <leitao@debian.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Yeoreum Yun <yeoreum.yun@arm.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: stable@vger.kernel.org
Fixes: 108aa503657e ("arm64: kexec_file: try more regions if loading segments fails")
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
 arch/arm64/kernel/machine_kexec_file.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index e48f29167b38..2f750e5f4fcc 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -112,6 +112,10 @@ int load_other_segments(struct kimage *image,
 			vfree(headers);
 			goto out_err;
 		}
+
+		if (unlikely(image->elf_headers))
+			vfree(image->elf_headers);
+
 		image->elf_headers = headers;
 		image->elf_load_addr = kbuf.mem;
 		image->elf_headers_sz = headers_sz;
-- 
2.34.1



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

* [PATCH v2 4/5] arm64: kexec_file: Simplify load_other_segments()
  2026-07-29  3:12 [PATCH v2 0/5] arm64: crash: Add crash hotplug support Jinjie Ruan
                   ` (2 preceding siblings ...)
  2026-07-29  3:12 ` [PATCH v2 3/5] arm64: kexec_file: Fix image->elf_headers memory leak in retry loop Jinjie Ruan
@ 2026-07-29  3:12 ` Jinjie Ruan
  2026-07-29  3:12 ` [PATCH v2 5/5] arm64: crash: Add crash hotplug support Jinjie Ruan
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jinjie Ruan @ 2026-07-29  3:12 UTC (permalink / raw)
  To: catalin.marinas, will, akpm, baoquan.he, rppt, pasha.tatashin,
	pratyush, thuth, mark.rutland, jic23, james.morse, ardb, leitao,
	yeoreum.yun, sourabhjain, robh, kees, coxu, makb, piliu, graf,
	ebiggers, jbouron, bgwin, linux-arm-kernel, linux-kernel, kexec
  Cc: ruanjinjie

Use `kbuf` fields directly in crash_prepare_headers() to eliminate
the local variables "headers" and "headers_sz"..

Advance the assignment to image->elf_headers before
calling kexec_add_buffer(). If kexec_add_buffer() fails, the explicit
vfree() in the error path can be removed, as the global infrastructure
in arch_kimage_file_post_load_cleanup() will handle the cleanup.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Baoquan He <bhe@redhat.com>
Cc: Breno Leitao <leitao@debian.org>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
 arch/arm64/kernel/machine_kexec_file.c | 24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 2f750e5f4fcc..3d907f8ee594 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -89,36 +89,30 @@ int load_other_segments(struct kimage *image,
 	kbuf.buf_min = kernel_load_addr + kernel_size;
 
 #ifdef CONFIG_CRASH_DUMP
-	/* load elf core header */
-	void *headers;
-	unsigned long headers_sz;
 	if (image->type == KEXEC_TYPE_CRASH) {
-		ret = crash_prepare_headers(true, &headers, &headers_sz, NULL);
+		ret = crash_prepare_headers(true, &kbuf.buffer, &kbuf.bufsz, NULL);
 		if (ret) {
 			pr_err("Preparing elf core header failed\n");
 			goto out_err;
 		}
 
-		kbuf.buffer = headers;
-		kbuf.bufsz = headers_sz;
+		if (unlikely(image->elf_headers))
+			vfree(image->elf_headers);
+
+		image->elf_headers = kbuf.buffer;
+		image->elf_headers_sz = kbuf.bufsz;
+
 		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
-		kbuf.memsz = headers_sz;
+		kbuf.memsz = kbuf.bufsz;
 		kbuf.buf_align = SZ_64K; /* largest supported page size */
 		kbuf.buf_max = ULONG_MAX;
 		kbuf.top_down = true;
 
 		ret = kexec_add_buffer(&kbuf);
-		if (ret) {
-			vfree(headers);
+		if (ret)
 			goto out_err;
-		}
-
-		if (unlikely(image->elf_headers))
-			vfree(image->elf_headers);
 
-		image->elf_headers = headers;
 		image->elf_load_addr = kbuf.mem;
-		image->elf_headers_sz = headers_sz;
 
 		kexec_dprintk("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
 			      image->elf_load_addr, kbuf.bufsz, kbuf.memsz);
-- 
2.34.1



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

* [PATCH v2 5/5] arm64: crash: Add crash hotplug support
  2026-07-29  3:12 [PATCH v2 0/5] arm64: crash: Add crash hotplug support Jinjie Ruan
                   ` (3 preceding siblings ...)
  2026-07-29  3:12 ` [PATCH v2 4/5] arm64: kexec_file: Simplify load_other_segments() Jinjie Ruan
@ 2026-07-29  3:12 ` Jinjie Ruan
  2026-08-13 16:05   ` Catalin Marinas
  2026-08-11 13:05 ` [PATCH v2 0/5] " Jinjie Ruan
  2026-08-13 14:40 ` Catalin Marinas
  6 siblings, 1 reply; 9+ messages in thread
From: Jinjie Ruan @ 2026-07-29  3:12 UTC (permalink / raw)
  To: catalin.marinas, will, akpm, baoquan.he, rppt, pasha.tatashin,
	pratyush, thuth, mark.rutland, jic23, james.morse, ardb, leitao,
	yeoreum.yun, sourabhjain, robh, kees, coxu, makb, piliu, graf,
	ebiggers, jbouron, bgwin, linux-arm-kernel, linux-kernel, kexec
  Cc: ruanjinjie

When CPU or memory hotplug events occur, the elfcorehdr in the kdump
image becomes stale, potentially leading to incomplete crash dumps.

Currently, userspace udev rules reload the entire kdump image upon such
events, which is inefficient and leaves kdump inactive for a long time.

Commit 247262756121 ("crash: add generic infrastructure for crash hotplug
support") introduced a kernel mechanism to update only the elfcorehdr.
This patch enables that support for arm64.

On arm64, only memory hotplug events require elfcorehdr updates:
- Physical CPU hotplug is not supported.

- For ACPI based vCPU hotplug [1], the elfcorehdr is built using
  for_each_possible_cpu(), so no update is needed.

The patch:
- Adds CONFIG_ARCH_SUPPORTS_CRASH_HOTPLUG (default y).

- Implements following arch functions to handle memory hotplug:
  1. arch_crash_hotplug_support()
  2. arch_crash_get_elfcorehdr_size()
  3. arch_crash_handle_hotplug_event()

- Moves arch_get_system_nr_ranges() and arch_crash_populate_cmem()
  from machine_kexec_file.c to crash.c for crash hotplug reuse.

Follows the approach of x86 commit ea53ad9cf73b ("x86/crash: add x86 crash
hotplug support") and powerpc commit b741092d5976 ("powerpc/crash: add
crash CPU hotplug support").

Tested with QEMU [2] virtual machine using:
	-M virt,acpi=on,highmem=on
	-smp cpus=1,maxcpus=3
	-bios /usr/share/edk2/aarch64/QEMU_EFI.fd
	-m 2G,slots=64,maxmem=16G

Only kexec_file_load path has been tested; kexec_load is expected to
work via KEXEC_CRASH_HOTPLUG_SUPPORT flag but not yet verified.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Baoquan He <bhe@redhat.com>
Cc: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Breno Leitao <leitao@debian.org>
Cc: Sourabh Jain <sourabhjain@linux.ibm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Thomas Huth <thuth@redhat.com>
[1]: https://lore.kernel.org/all/20240529133446.28446-1-Jonathan.Cameron@huawei.com/
[2]: https://github.com/salil-mehta/qemu.git virt-cpuhp-armv8/rfc-v2
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
 arch/arm64/Kconfig                     |   3 +
 arch/arm64/include/asm/kexec.h         |  16 +++
 arch/arm64/kernel/Makefile             |   2 +-
 arch/arm64/kernel/crash.c              | 143 +++++++++++++++++++++++++
 arch/arm64/kernel/machine_kexec_file.c |  55 +++++-----
 5 files changed, 187 insertions(+), 32 deletions(-)
 create mode 100644 arch/arm64/kernel/crash.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b3afe0688919..bebebded5b96 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1666,6 +1666,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 TRANS_TABLE
 	def_bool y
 	depends on HIBERNATION || KEXEC_CORE
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 892e5bebda95..6c9a73c0b920 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -130,6 +130,22 @@ extern int load_other_segments(struct kimage *image,
 		char *cmdline);
 #endif
 
+#ifdef CONFIG_CRASH_HOTPLUG
+static inline unsigned long pnum_hdr_sz(unsigned long pnum)
+{
+	return pnum * sizeof(Elf64_Phdr) + sizeof(Elf64_Ehdr);
+}
+
+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 /* __ASSEMBLER__ */
 
 #endif
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index d2690c3ec528..9bbac452994c 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -64,7 +64,7 @@ obj-$(CONFIG_KEXEC_CORE)		+= machine_kexec.o relocate_kernel.o	\
 obj-$(CONFIG_KEXEC_FILE)		+= machine_kexec_file.o kexec_image.o
 obj-$(CONFIG_ARM64_RELOC_TEST)		+= arm64-reloc-test.o
 arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o
-obj-$(CONFIG_CRASH_DUMP)		+= crash_dump.o
+obj-$(CONFIG_CRASH_DUMP)		+= crash_dump.o crash.o
 obj-$(CONFIG_VMCORE_INFO)		+= vmcore_info.o
 obj-$(CONFIG_ARM_SDE_INTERFACE)		+= sdei.o
 obj-$(CONFIG_ARM64_PTR_AUTH)		+= pointer_auth.o
diff --git a/arch/arm64/kernel/crash.c b/arch/arm64/kernel/crash.c
new file mode 100644
index 000000000000..1f49caa627c4
--- /dev/null
+++ b/arch/arm64/kernel/crash.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Architecture specific functions for kexec based crash dumps.
+ */
+
+#define pr_fmt(fmt)	"crash hp: " fmt
+
+#include <linux/kexec.h>
+#include <linux/elf.h>
+#include <linux/memblock.h>
+#include <linux/vmalloc.h>
+#include <linux/cacheflush.h>
+#include <linux/crash_core.h>
+
+#include <asm/kexec.h>
+
+#if defined(CONFIG_KEXEC_FILE) || defined(CONFIG_CRASH_HOTPLUG)
+unsigned int arch_get_system_nr_ranges(void)
+{
+	unsigned int nr_ranges = 2 + crashk_cma_cnt; /* for exclusion of crashkernel region */
+	phys_addr_t start, end;
+	u64 i;
+
+	for_each_mem_range(i, &start, &end)
+		nr_ranges++;
+
+	return nr_ranges;
+}
+
+int arch_crash_populate_cmem(struct crash_mem *cmem)
+{
+	phys_addr_t start, end;
+	u64 i;
+
+	for_each_mem_range(i, &start, &end) {
+		cmem->ranges[cmem->nr_ranges].start = start;
+		cmem->ranges[cmem->nr_ranges].end = end - 1;
+		cmem->nr_ranges++;
+	}
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_CRASH_HOTPLUG
+int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags)
+{
+#ifdef CONFIG_KEXEC_FILE
+	if (image->file_mode)
+		return 1;
+#endif
+	/*
+	 * For kexec_load syscall, crash hotplug support requires
+	 * KEXEC_CRASH_HOTPLUG_SUPPORT flag to be passed by userspace.
+	 */
+	return kexec_flags & KEXEC_CRASH_HOTPLUG_SUPPORT;
+}
+
+unsigned int arch_crash_get_elfcorehdr_size(void)
+{
+	unsigned long phdr_cnt;
+
+	/* A program header for possible CPUs, vmcoreinfo and kernel_map */
+	phdr_cnt = 2 + num_possible_cpus();
+	if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+		phdr_cnt += CONFIG_CRASH_MAX_MEMORY_RANGES;
+
+	return pnum_hdr_sz(phdr_cnt);
+}
+
+/**
+ * update_crash_elfcorehdr() - Recreate the elfcorehdr and replace it with old
+ *			       elfcorehdr in the kexec segment array.
+ * @image: the active struct kimage
+ */
+static void update_crash_elfcorehdr(struct kimage *image)
+{
+	void *elfbuf = NULL, *old_elfcorehdr;
+	unsigned long mem, memsz;
+	unsigned long elfsz = 0;
+
+	/*
+	 * 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 = phys_to_virt(mem);
+
+	/*
+	 * Temporarily invalidate the crash image while the
+	 * elfcorehdr is updated.
+	 */
+	xchg(&kexec_crash_image, NULL);
+	memcpy(old_elfcorehdr, elfbuf, elfsz);
+	dcache_clean_inval_poc((unsigned long)old_elfcorehdr,
+			       (unsigned long)(old_elfcorehdr + elfsz));
+	xchg(&kexec_crash_image, image);
+	pr_debug("updated elfcorehdr\n");
+
+out:
+	vfree(elfbuf);
+}
+
+/**
+ * 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.
+ *
+ * Update the kdump image based on the type of hotplug event:
+ * - CPU add and remove: No action is needed.
+ * - Memory add/remove: Update the elfcorehdr to reflect the current memory layout.
+ *
+ * Prepare the new elfcorehdr and replace the existing elfcorehdr.
+ */
+void arch_crash_handle_hotplug_event(struct kimage *image, void *arg)
+{
+	if (image->hp_action == KEXEC_CRASH_HP_ADD_CPU ||
+	    image->hp_action == KEXEC_CRASH_HP_REMOVE_CPU)
+		return;
+
+	update_crash_elfcorehdr(image);
+}
+#endif /* CONFIG_CRASH_HOTPLUG */
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 3d907f8ee594..cce19f00acc0 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/kexec.h>
 #include <linux/libfdt.h>
-#include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/slab.h>
@@ -39,34 +38,6 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
 	return kexec_image_post_load_cleanup_default(image);
 }
 
-#ifdef CONFIG_CRASH_DUMP
-unsigned int arch_get_system_nr_ranges(void)
-{
-	unsigned int nr_ranges = 2 + crashk_cma_cnt; /* for exclusion of crashkernel region */
-	phys_addr_t start, end;
-	u64 i;
-
-	for_each_mem_range(i, &start, &end)
-		nr_ranges++;
-
-	return nr_ranges;
-}
-
-int arch_crash_populate_cmem(struct crash_mem *cmem)
-{
-	phys_addr_t start, end;
-	u64 i;
-
-	for_each_mem_range(i, &start, &end) {
-		cmem->ranges[cmem->nr_ranges].start = start;
-		cmem->ranges[cmem->nr_ranges].end = end - 1;
-		cmem->nr_ranges++;
-	}
-
-	return 0;
-}
-#endif
-
 /*
  * Tries to add the initrd and DTB to the image. If it is not possible to find
  * valid locations, this function will undo changes to the image and return non
@@ -89,8 +60,9 @@ int load_other_segments(struct kimage *image,
 	kbuf.buf_min = kernel_load_addr + kernel_size;
 
 #ifdef CONFIG_CRASH_DUMP
+	unsigned long pnum = 0;
 	if (image->type == KEXEC_TYPE_CRASH) {
-		ret = crash_prepare_headers(true, &kbuf.buffer, &kbuf.bufsz, NULL);
+		ret = crash_prepare_headers(true, &kbuf.buffer, &kbuf.bufsz, &pnum);
 		if (ret) {
 			pr_err("Preparing elf core header failed\n");
 			goto out_err;
@@ -101,9 +73,27 @@ int load_other_segments(struct kimage *image,
 
 		image->elf_headers = kbuf.buffer;
 		image->elf_headers_sz = kbuf.bufsz;
+		kbuf.memsz = kbuf.bufsz;
+
+#ifdef CONFIG_CRASH_HOTPLUG
+		/*
+		 * The elfcorehdr segment size accounts for VMCOREINFO, kernel_map
+		 * maximum CPUs and maximum memory ranges.
+		 */
+		if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+			pnum = 2 + num_possible_cpus() + CONFIG_CRASH_MAX_MEMORY_RANGES;
+		else
+			pnum += 2 + num_possible_cpus();
+
+		if (pnum < PN_XNUM) {
+			kbuf.memsz = pnum_hdr_sz(pnum);
+			image->elf_headers_sz = max(kbuf.memsz, kbuf.bufsz);
+		} else {
+			pr_err("number of Phdrs %lu exceeds max\n", pnum);
+		}
+#endif
 
 		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
-		kbuf.memsz = kbuf.bufsz;
 		kbuf.buf_align = SZ_64K; /* largest supported page size */
 		kbuf.buf_max = ULONG_MAX;
 		kbuf.top_down = true;
@@ -112,6 +102,9 @@ int load_other_segments(struct kimage *image,
 		if (ret)
 			goto out_err;
 
+		if (IS_ENABLED(CONFIG_CRASH_HOTPLUG) && pnum < PN_XNUM)
+			image->elfcorehdr_index = image->nr_segments - 1;
+
 		image->elf_load_addr = kbuf.mem;
 
 		kexec_dprintk("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
-- 
2.34.1



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

* Re: [PATCH v2 0/5] arm64: crash: Add crash hotplug support
  2026-07-29  3:12 [PATCH v2 0/5] arm64: crash: Add crash hotplug support Jinjie Ruan
                   ` (4 preceding siblings ...)
  2026-07-29  3:12 ` [PATCH v2 5/5] arm64: crash: Add crash hotplug support Jinjie Ruan
@ 2026-08-11 13:05 ` Jinjie Ruan
  2026-08-13 14:40 ` Catalin Marinas
  6 siblings, 0 replies; 9+ messages in thread
From: Jinjie Ruan @ 2026-08-11 13:05 UTC (permalink / raw)
  To: catalin.marinas, will, akpm, baoquan.he, rppt, pasha.tatashin,
	pratyush, thuth, mark.rutland, jic23, james.morse, ardb, leitao,
	yeoreum.yun, sourabhjain, robh, kees, coxu, makb, piliu, graf,
	ebiggers, jbouron, bgwin, linux-arm-kernel, linux-kernel, kexec



在 2026/7/29 11:12, Jinjie Ruan 写道:
> When CPU or memory hotplug events occur, the elfcorehdr in the kdump
> image becomes stale, potentially leading to incomplete crash dumps.
> 
> Currently, userspace udev rules reload the entire kdump image upon such
> events, which is inefficient and leaves kdump inactive for a long time.
> 
> Commit 247262756121 ("crash: add generic infrastructure for crash hotplug
> support") introduced a kernel mechanism to update only the elfcorehdr.
> This patch set implements crash hotplug support for arm64.
> 
> As Baoquan suggested, it also addresses and fixes several
> pre-existing code issues and Sashiko AI review findings extracted
> from the previous patch set.
> 
> The major improvements and fixes included in this series are:
> - Fix several memory leaks for arm64.
> - Simplify arm64 load_other_segments().
> - Implement infrastructure for arm64 crash memory hotplug support.

Hi all,

I'd like to ask if anyone has any suggestions for improvement?

> 
> This patch set is rebased on liveupdate/crashkernel-cma.
> 
> Link: https://lore.kernel.org/all/20260601094805.2928614-1-ruanjinjie@huawei.com/
> 
> Changes in v2:
> - Split out Powerpc bugfix patch as Mike suggested.
> - Use phys_to_virt() instead of __va() in update_crash_elfcorehdr().
> - Convert pnum_hdr_sz() to a function.
> - Only assign elfcorehdr_index after kexec_add_buffer succeeds, considering
>   crash_handle_hotplug_event() already performs validity check on
>   elfcorehdr_index:
>   - We can safely remove the check for CPU hotplug
>     in arch_crash_handle_hotplug_event().
>   - The elfcorehdr_index's segment mem will be valid in
>     update_crash_elfcorehdr(), so we can safely remove the NULL check.
> - Simplify the commit message.
> - v1: https://lore.kernel.org/all/20260723131242.1537633-1-ruanjinjie@huawei.com/#t
> 
> Jinjie Ruan (5):
>   kexec: Extract kexec_free_segment_cma() from kimage_free_cma()
>   arm64: kexec_file: Fix CMA page leaks in segment placement retry loops
>   arm64: kexec_file: Fix image->elf_headers memory leak in retry loop
>   arm64: kexec_file: Simplify load_other_segments()
>   arm64: crash: Add crash hotplug support
> 
>  arch/arm64/Kconfig                     |   3 +
>  arch/arm64/include/asm/kexec.h         |  16 +++
>  arch/arm64/kernel/Makefile             |   2 +-
>  arch/arm64/kernel/crash.c              | 143 +++++++++++++++++++++++++
>  arch/arm64/kernel/kexec_image.c        |   1 +
>  arch/arm64/kernel/machine_kexec_file.c |  78 +++++++-------
>  include/linux/kexec.h                  |   2 +
>  kernel/kexec_core.c                    |  25 +++--
>  8 files changed, 216 insertions(+), 54 deletions(-)
>  create mode 100644 arch/arm64/kernel/crash.c
> 



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

* Re: [PATCH v2 0/5] arm64: crash: Add crash hotplug support
  2026-07-29  3:12 [PATCH v2 0/5] arm64: crash: Add crash hotplug support Jinjie Ruan
                   ` (5 preceding siblings ...)
  2026-08-11 13:05 ` [PATCH v2 0/5] " Jinjie Ruan
@ 2026-08-13 14:40 ` Catalin Marinas
  6 siblings, 0 replies; 9+ messages in thread
From: Catalin Marinas @ 2026-08-13 14:40 UTC (permalink / raw)
  To: Jinjie Ruan
  Cc: will, akpm, baoquan.he, rppt, pasha.tatashin, pratyush, thuth,
	mark.rutland, jic23, james.morse, ardb, leitao, yeoreum.yun,
	sourabhjain, robh, kees, coxu, makb, piliu, graf, ebiggers,
	jbouron, bgwin, linux-arm-kernel, linux-kernel, kexec

On Wed, Jul 29, 2026 at 11:12:30AM +0800, Jinjie Ruan wrote:
> When CPU or memory hotplug events occur, the elfcorehdr in the kdump
> image becomes stale, potentially leading to incomplete crash dumps.
> 
> Currently, userspace udev rules reload the entire kdump image upon such
> events, which is inefficient and leaves kdump inactive for a long time.
> 
> Commit 247262756121 ("crash: add generic infrastructure for crash hotplug
> support") introduced a kernel mechanism to update only the elfcorehdr.
> This patch set implements crash hotplug support for arm64.
> 
> As Baoquan suggested, it also addresses and fixes several
> pre-existing code issues and Sashiko AI review findings extracted
> from the previous patch set.
> 
> The major improvements and fixes included in this series are:
> - Fix several memory leaks for arm64.
> - Simplify arm64 load_other_segments().
> - Implement infrastructure for arm64 crash memory hotplug support.
> 
> This patch set is rebased on liveupdate/crashkernel-cma.
> 
> Link: https://lore.kernel.org/all/20260601094805.2928614-1-ruanjinjie@huawei.com/

Is there any dependency for the first 3 patches on the above branch?
Patches 2/3 look like fixes and they depend on patch 1. Not sure about
cc stable, maybe patch 2.

[...]

> Jinjie Ruan (5):
>   kexec: Extract kexec_free_segment_cma() from kimage_free_cma()
>   arm64: kexec_file: Fix CMA page leaks in segment placement retry loops
>   arm64: kexec_file: Fix image->elf_headers memory leak in retry loop
>   arm64: kexec_file: Simplify load_other_segments()
>   arm64: crash: Add crash hotplug support

-- 
Catalin


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

* Re: [PATCH v2 5/5] arm64: crash: Add crash hotplug support
  2026-07-29  3:12 ` [PATCH v2 5/5] arm64: crash: Add crash hotplug support Jinjie Ruan
@ 2026-08-13 16:05   ` Catalin Marinas
  0 siblings, 0 replies; 9+ messages in thread
From: Catalin Marinas @ 2026-08-13 16:05 UTC (permalink / raw)
  To: Jinjie Ruan
  Cc: will, akpm, baoquan.he, rppt, pasha.tatashin, pratyush, thuth,
	mark.rutland, jic23, james.morse, ardb, leitao, yeoreum.yun,
	sourabhjain, robh, kees, coxu, makb, piliu, graf, ebiggers,
	jbouron, bgwin, linux-arm-kernel, linux-kernel, kexec

Hi Jinjie,

On Wed, Jul 29, 2026 at 11:12:35AM +0800, Jinjie Ruan wrote:
> +/**
> + * update_crash_elfcorehdr() - Recreate the elfcorehdr and replace it with old
> + *			       elfcorehdr in the kexec segment array.
> + * @image: the active struct kimage
> + */
> +static void update_crash_elfcorehdr(struct kimage *image)
> +{
> +	void *elfbuf = NULL, *old_elfcorehdr;
> +	unsigned long mem, memsz;
> +	unsigned long elfsz = 0;
> +
> +	/*
> +	 * 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 = phys_to_virt(mem);
> +
> +	/*
> +	 * Temporarily invalidate the crash image while the
> +	 * elfcorehdr is updated.
> +	 */
> +	xchg(&kexec_crash_image, NULL);
> +	memcpy(old_elfcorehdr, elfbuf, elfsz);
> +	dcache_clean_inval_poc((unsigned long)old_elfcorehdr,
> +			       (unsigned long)(old_elfcorehdr + elfsz));
> +	xchg(&kexec_crash_image, image);
> +	pr_debug("updated elfcorehdr\n");
> +
> +out:
> +	vfree(elfbuf);
> +}
> +
> +/**
> + * 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.
> + *
> + * Update the kdump image based on the type of hotplug event:
> + * - CPU add and remove: No action is needed.
> + * - Memory add/remove: Update the elfcorehdr to reflect the current memory layout.
> + *
> + * Prepare the new elfcorehdr and replace the existing elfcorehdr.
> + */
> +void arch_crash_handle_hotplug_event(struct kimage *image, void *arg)
> +{
> +	if (image->hp_action == KEXEC_CRASH_HP_ADD_CPU ||
> +	    image->hp_action == KEXEC_CRASH_HP_REMOVE_CPU)
> +		return;
> +
> +	update_crash_elfcorehdr(image);
> +}

Looking at powerpc, they pass the arg down to update_crash_elfcorehdr()
to handle the memory hot-unplug case. It looks like the notifier is
called before the memblock_remove(), so the update above will still
count the memory being removed.

There are a few Sashiko comments as well, though some might be about
existing issues (it would be nice to have them fixed ;)).

-- 
Catalin


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

end of thread, other threads:[~2026-08-13 16:05 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29  3:12 [PATCH v2 0/5] arm64: crash: Add crash hotplug support Jinjie Ruan
2026-07-29  3:12 ` [PATCH v2 1/5] kexec: Extract kexec_free_segment_cma() from kimage_free_cma() Jinjie Ruan
2026-07-29  3:12 ` [PATCH v2 2/5] arm64: kexec_file: Fix CMA page leaks in segment placement retry loops Jinjie Ruan
2026-07-29  3:12 ` [PATCH v2 3/5] arm64: kexec_file: Fix image->elf_headers memory leak in retry loop Jinjie Ruan
2026-07-29  3:12 ` [PATCH v2 4/5] arm64: kexec_file: Simplify load_other_segments() Jinjie Ruan
2026-07-29  3:12 ` [PATCH v2 5/5] arm64: crash: Add crash hotplug support Jinjie Ruan
2026-08-13 16:05   ` Catalin Marinas
2026-08-11 13:05 ` [PATCH v2 0/5] " Jinjie Ruan
2026-08-13 14:40 ` Catalin Marinas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.