Hi, Youling, On Mon, Aug 11, 2025 at 5:28 PM Youling Tang <youling.t...@linux.dev> wrote: > > From: Youling Tang <tangyoul...@kylinos.cn> > > Add inird loading support and pass it to the second kernel via the > cmdline 'initrd=start,size'. I think Patch-3 and Patch-5 should be merged into Patch-2.
Huacai > > Signed-off-by: Youling Tang <tangyoul...@kylinos.cn> > --- > arch/loongarch/kernel/machine_kexec_file.c | 71 ++++++++++++++++++++++ > 1 file changed, 71 insertions(+) > > diff --git a/arch/loongarch/kernel/machine_kexec_file.c > b/arch/loongarch/kernel/machine_kexec_file.c > index bc91ae0afa4c..e1240644f529 100644 > --- a/arch/loongarch/kernel/machine_kexec_file.c > +++ b/arch/loongarch/kernel/machine_kexec_file.c > @@ -34,13 +34,84 @@ int arch_kimage_file_post_load_cleanup(struct kimage > *image) > return kexec_image_post_load_cleanup_default(image); > } > > +/* Adds the "initrd=start,size" command line parameter to command line. */ > +static void cmdline_add_initrd(struct kimage *image, unsigned long > *cmdline_tmplen, > + char *modified_cmdline, unsigned long initrd) > +{ > + int initrd_strlen; > + > + initrd_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), > "initrd=0x%lx,0x%lx ", > + initrd, image->initrd_buf_len); > + *cmdline_tmplen += initrd_strlen; > +} > + > +/* > + * Tries to add the initrd 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, unsigned long cmdline_len) > { > + struct kexec_buf kbuf; > + unsigned long orig_segments = image->nr_segments; > + char *modified_cmdline = NULL; > + unsigned long cmdline_tmplen = 0; > + unsigned long initrd_load_addr = 0; > + int ret = 0; > + > + > + kbuf.image = image; > + /* not allocate anything below the kernel */ > + kbuf.buf_min = kernel_load_addr + kernel_size; > + > + modified_cmdline = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL); > + if (!modified_cmdline) > + return -EINVAL; > + > + /* Ensure it's nul terminated */ > + modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0'; > + > + /* 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); > + > + /* Add the initrd=start,size parameter to the command line */ > + cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, > initrd_load_addr); > + } > + > + if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) { > + pr_err("Appending kdump cmdline exceeds cmdline size\n"); > + ret = -EINVAL; > + goto out_err; > + } > + memcpy(modified_cmdline + cmdline_tmplen, cmdline, cmdline_len); > + cmdline = modified_cmdline; > image->arch.cmdline_ptr = (unsigned long)cmdline; > > return 0; > + > +out_err: > + image->nr_segments = orig_segments; > + kfree(modified_cmdline); > + return ret; > } > -- > 2.34.1 >