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 <[email protected]> Cc: Will Deacon <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Baoquan He <[email protected]> Cc: Mike Rapoport <[email protected]> Signed-off-by: Jinjie Ruan <[email protected]> --- 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
