[PATCH v7 12/15] kexec: Add kexec_load_other_segments() helper
Jinjie Ruan
ruanjinjie at huawei.com
Mon Oct 26 00:51:58 PDT 2026
arm64, LoongArch and RISC-V duplicate the elf core header and initrd
loading. Move it into a common helper with one arch hook for the boot
parameters; a failure releases everything added for the attempt.
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: Baoquan He <baoquan.he at linux.dev>
Cc: Mike Rapoport <rppt at kernel.org>
Suggested-by: Mike Rapoport <rppt at kernel.org>
Signed-off-by: Jinjie Ruan <ruanjinjie at huawei.com>
---
include/linux/kexec.h | 15 ++++++++
kernel/kexec_file.c | 90 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index faba26f871a4..de1d83ddc38b 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -259,6 +259,21 @@ int kexec_kernel_verify_pe_sig(const char *kernel, unsigned long kernel_len);
extern int kexec_add_buffer(struct kexec_buf *kbuf);
int kexec_locate_mem_hole(struct kexec_buf *kbuf);
+struct kexec_load_params {
+ unsigned long kernel_load_addr;
+ unsigned long kernel_size;
+ char *initrd;
+ unsigned long initrd_len;
+ char *cmdline;
+ unsigned long cmdline_len;
+};
+
+int arch_kexec_setup_other_segments(struct kimage *image,
+ struct kexec_load_params *params,
+ unsigned long initrd_load_addr);
+int kexec_load_other_segments(struct kimage *image,
+ struct kexec_load_params *params, bool top_down);
+
#ifndef arch_kexec_locate_mem_hole
/**
* arch_kexec_locate_mem_hole - Find free memory to place the segments.
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 62d4cba278a5..8b80f1186875 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -1295,3 +1295,93 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
return 0;
}
#endif /* CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY */
+
+int __weak arch_kexec_setup_other_segments(struct kimage *image,
+ struct kexec_load_params *params,
+ unsigned long initrd_load_addr)
+{
+ return 0;
+}
+
+int kexec_load_other_segments(struct kimage *image,
+ struct kexec_load_params *params, bool top_down)
+{
+ struct kexec_buf kbuf = {
+ .image = image,
+ /* Do not allocate anything below the kernel */
+ .buf_min = params->kernel_load_addr + params->kernel_size,
+ .buf_max = top_down ? PFN_PHYS(max_low_pfn) : ULONG_MAX,
+ };
+
+ unsigned long orig_segments = image->nr_segments;
+ unsigned long initrd_load_addr = 0;
+ int ret = 0;
+
+#ifdef CONFIG_CRASH_DUMP
+ if (image->type == KEXEC_TYPE_CRASH) {
+ ret = crash_prepare_headers(true, &kbuf.buffer, &kbuf.bufsz, NULL);
+ if (ret) {
+ pr_err("Preparing elf core header failed\n");
+ goto out_err;
+ }
+
+ 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 = kbuf.bufsz;
+ kbuf.buf_align = SZ_64K; /* largest supported page size */
+ kbuf.top_down = true;
+
+ ret = kexec_add_buffer(&kbuf);
+ if (ret)
+ goto out_err;
+
+ image->elf_load_addr = kbuf.mem;
+
+ kexec_dprintk("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+ image->elf_load_addr, kbuf.bufsz, kbuf.memsz);
+ }
+#endif
+
+ if (params->initrd) {
+ kbuf.buffer = params->initrd;
+ kbuf.bufsz = params->initrd_len;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ kbuf.memsz = params->initrd_len;
+ kbuf.buf_align = 0;
+ /* within 1GB-aligned window of up to 32GB in size */
+ if (!top_down)
+ kbuf.buf_max = round_down(params->kernel_load_addr, SZ_1G) +
+ (unsigned long)SZ_1G * 32;
+ kbuf.top_down = top_down;
+
+ ret = kexec_add_buffer(&kbuf);
+ if (ret)
+ goto out_err;
+ initrd_load_addr = kbuf.mem;
+
+ kexec_dprintk("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+ initrd_load_addr, kbuf.bufsz, kbuf.memsz);
+ }
+
+ ret = arch_kexec_setup_other_segments(image, params,
+ initrd_load_addr);
+ if (ret)
+ goto out_err;
+
+ return 0;
+
+out_err:
+ while (image->nr_segments > orig_segments) {
+ kexec_free_segment_cma(image, image->nr_segments - 1);
+ image->nr_segments--;
+ }
+
+ kexec_free_elf_headers(image);
+
+ return ret;
+}
--
2.34.1
More information about the kexec
mailing list