[PATCH v7 13/15] arm64: kexec_file: Use kexec_load_other_segments() to simplify code
From: Jinjie Ruan
Date: Mon Oct 26 2026 - 03:56:22 EST
Replace the local copy with the common helper.
The retry loop stays. And the DTB and the dm-crypt keys move to the setup
hook and the keys are loaded after the initrd now.
Cc: Catalin Marinas <catalin.marinas@xxxxxxx>
Cc: Will Deacon <will@xxxxxxxxxx>
Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Cc: Baoquan He <baoquan.he@xxxxxxxxx>
Cc: Mike Rapoport <rppt@xxxxxxxxxx>
Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
arch/arm64/include/asm/kexec.h | 5 --
arch/arm64/kernel/kexec_image.c | 12 +++-
arch/arm64/kernel/machine_kexec_file.c | 95 ++++----------------------
3 files changed, 23 insertions(+), 89 deletions(-)
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 892e5bebda95..8fc04e0e7dad 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -123,11 +123,6 @@ extern const struct kexec_file_ops kexec_image_ops;
int arch_kimage_file_post_load_cleanup(struct kimage *image);
#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
-
-extern int load_other_segments(struct kimage *image,
- unsigned long kernel_load_addr, unsigned long kernel_size,
- char *initrd, unsigned long initrd_len,
- char *cmdline);
#endif
#endif /* __ASSEMBLER__ */
diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
index 6ed1991e3142..f5a7f1f92afc 100644
--- a/arch/arm64/kernel/kexec_image.c
+++ b/arch/arm64/kernel/kexec_image.c
@@ -44,6 +44,12 @@ static void *image_load(struct kimage *image,
struct kexec_buf kbuf = {};
unsigned long text_offset, kernel_segment_number;
struct kexec_segment *kernel_segment;
+ struct kexec_load_params params = {
+ .initrd = initrd,
+ .initrd_len = initrd_len,
+ .cmdline = cmdline,
+ .cmdline_len = cmdline_len,
+ };
int ret;
/*
@@ -101,9 +107,9 @@ static void *image_load(struct kimage *image,
while ((ret = kexec_add_buffer(&kbuf)) == 0) {
/* Try to load additional data */
kernel_segment = &image->segment[kernel_segment_number];
- ret = load_other_segments(image, kernel_segment->mem,
- kernel_segment->memsz, initrd,
- initrd_len, cmdline);
+ params.kernel_load_addr = kernel_segment->mem;
+ params.kernel_size = kernel_segment->memsz;
+ ret = kexec_load_other_segments(image, ¶ms, false);
if (!ret)
break;
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index e7f280915e8d..44754b380bf1 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -63,91 +63,30 @@ int arch_crash_populate_cmem(struct crash_mem *cmem)
}
#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
- * zero.
- */
-int load_other_segments(struct kimage *image,
- unsigned long kernel_load_addr,
- unsigned long kernel_size,
- char *initrd, unsigned long initrd_len,
- char *cmdline)
+int arch_kexec_setup_other_segments(struct kimage *image,
+ struct kexec_load_params *params,
+ unsigned long initrd_load_addr)
{
struct kexec_buf kbuf = {
.image = image,
- /* not allocate anything below the kernel */
- .buf_min = kernel_load_addr + kernel_size,
- .buf_max = ULONG_MAX,
+ .buf_min = params->kernel_load_addr + params->kernel_size,
};
- void *dtb = NULL;
- unsigned long initrd_load_addr = 0, dtb_len,
- orig_segments = image->nr_segments;
- int ret = 0;
+ unsigned long dtb_len;
+ void *dtb;
+ int ret;
-#ifdef CONFIG_CRASH_DUMP
- /* load elf core header */
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);
-
ret = crash_load_dm_crypt_keys(image);
if (ret)
- goto out_err;
- }
-#endif
-
- /* load initrd */
- if (initrd) {
- kbuf.buffer = initrd;
- kbuf.bufsz = initrd_len;
- kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
- kbuf.memsz = initrd_len;
- kbuf.buf_align = 0;
- /* within 1GB-aligned window of up to 32GB in size */
- kbuf.buf_max = round_down(kernel_load_addr, SZ_1G)
- + (unsigned long)SZ_1G * 32;
- kbuf.top_down = false;
-
- 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);
+ return ret;
}
/* load dtb */
dtb = of_kexec_alloc_and_setup_fdt(image, initrd_load_addr,
- initrd_len, cmdline, 0);
+ params->initrd_len, params->cmdline, 0);
if (!dtb) {
pr_err("Preparing for new dtb failed\n");
- ret = -EINVAL;
- goto out_err;
+ return -EINVAL;
}
/* trim it */
@@ -163,8 +102,10 @@ int load_other_segments(struct kimage *image,
kbuf.top_down = true;
ret = kexec_add_buffer(&kbuf);
- if (ret)
- goto out_err;
+ if (ret) {
+ kvfree(dtb);
+ return ret;
+ }
image->arch.dtb = dtb;
image->arch.dtb_mem = kbuf.mem;
@@ -172,12 +113,4 @@ int load_other_segments(struct kimage *image,
kbuf.mem, kbuf.bufsz, kbuf.memsz);
return 0;
-
-out_err:
- 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