On Fri, Jun 10, 2022 at 04:53:52PM +0800, Hui Li wrote: > Under loongson platform, use command: > kexec -l vmlinux... --append="root=UUID=28e1..." --initrd=... > kexec -e > quick restart failed like this: > > ******************************************************************** > [ 3.420791] VFS: Cannot open root device "UUID=6462a8a4-02fb-49..." > [ 3.431262] Please append a correct "root=" boot option; ... > ... > ... > ... > [ 3.543175] 0801 4194304 sda1 554e69cc-01 > [ 3.543175] > [ 3.549494] 0802 62914560 sda2 554e69cc-02 > [ 3.549495] > [ 3.555818] 0803 8388608 sda3 554e69cc-03 > [ 3.555819] > [ 3.562139] 0804 174553229 sda4 554e69cc-04 > [ 3.562139] > [ 3.568463] 0b00 1048575 sr0 > [ 3.568464] driver: sr > [ 3.574524] Kernel panic - not syncing: VFS: Unable to mount root fs... > [ 3.582750] ---[ end Kernel panic - not syncing: VFS:... > ******************************************************************* > > The kernel cannot parse the UUID, the UUID is parsed in the initrd. > For compatibility with previous platforms, loongson platform obtain > initrd parameter through cmdline in kernel, the kernel supports use > cmdline to parse initrd. But under the mips architecture, kexec-tools > pass the initrd through DTB. > > So some modifications as follows: > > (1) in kexec/arch/mips/kexec-elf-mips.c > Add patch_initrd_info(), at runtime to distinguish different cpu, > only for loongson cpu, add initrd parameter to cmdline. > > (2) in kexec/arch/mips/crashdump-mips.c > Because loongson uses a different page_offset, it should be modified > to ensure that crashdump functionality is correct and reliable. > > Signed-off-by: Hui Li <lihui@xxxxxxxxxxx> Hi Hui Li, thanks for the follow-up and sorry for the slow response. Overall I am happy with this approach. I have made a few minor comments inline for your consideration. > --- > kexec/arch/mips/crashdump-mips.c | 3 ++ > kexec/arch/mips/kexec-elf-mips.c | 73 +++++++++++++++++++++++++++++++- > 2 files changed, 74 insertions(+), 2 deletions(-) > > diff --git a/kexec/arch/mips/crashdump-mips.c b/kexec/arch/mips/crashdump-mips.c > index aa09c83..548aeff 100644 > --- a/kexec/arch/mips/crashdump-mips.c > +++ b/kexec/arch/mips/crashdump-mips.c > @@ -335,6 +335,9 @@ static int patch_elf_info(void) > /* OCTEON uses a different page_offset. */ > if (strstr(line, "Octeon")) > elf_info64.page_offset = 0x8000000000000000ULL; > + /* LOONGSON uses a different page_offset. */ > + else if (strstr(line, "Loongson")) > + elf_info64.page_offset = 0xffffffff80000000ULL; nit: 0xffffffff80000000ULL is used twice. Perhaps we could make it a #define. And perhaps 0x8000000000000000ULL too, while we are here. > break; > } > } > diff --git a/kexec/arch/mips/kexec-elf-mips.c b/kexec/arch/mips/kexec-elf-mips.c > index a2d11fc..b9e0341 100644 > --- a/kexec/arch/mips/kexec-elf-mips.c > +++ b/kexec/arch/mips/kexec-elf-mips.c > @@ -40,6 +40,74 @@ static const int probe_debug = 0; > #define CMDLINE_PREFIX "kexec " > static char cmdline_buf[COMMAND_LINE_SIZE] = CMDLINE_PREFIX; > > +/* Converts unsigned long to ascii string. */ > +static void ultoa(unsigned long i, char *str) > +{ > + int j = 0, k; > + char tmp; > + > + do { > + str[j++] = i % 10 + '0'; > + } while ((i /= 10) > 0); > + str[j] = '\0'; > + > + /* Reverse the string. */ > + for (j = 0, k = strlen(str) - 1; j < k; j++, k--) { > + tmp = str[k]; > + str[k] = str[j]; > + str[j] = tmp; > + } > +} > + > +/* Adds initrd parameters to command line. */ > +static int cmdline_add_initrd(char *cmdline, unsigned long addr, char *new_para) > +{ > + int cmdlen, len; > + char str[30], *ptr; > + > + ptr = str; > + strcpy(str, new_para); > + ptr += strlen(str); > + ultoa(addr, ptr); > + len = strlen(str); > + cmdlen = strlen(cmdline) + len; > + if (cmdlen > (COMMAND_LINE_SIZE - 1)) > + die("Command line overflow\n"); > + strcat(cmdline, str); > + > + return 0; > +} > + > +/* add initrd to cmdline to compatible with previous platforms. */ > +static int patch_initrd_info(char *cmdline, unsigned long initrd_base, unsigned long initrd_size) nit: I would prefer if the code was less than 80 columns wide. > +{ > + const char cpuinfo[] = "/proc/cpuinfo"; > + char line[MAX_LINE]; > + FILE *fp; > + unsigned long page_offset = PAGE_OFFSET; > + > + fp = fopen(cpuinfo, "r"); > + if (!fp) { > + fprintf(stderr, "Cannot open %s: %s\n", > + cpuinfo, strerror(errno)); > + return -1; > + } > + while (fgets(line, sizeof(line), fp) != 0) { > + if (strncmp(line, "cpu model", 9) == 0) { > + /* LOONGSON64 uses a different page_offset. */ > + if (strstr(line, "Loongson")) { > + if (arch_options.core_header_type == CORE_TYPE_ELF64) > + page_offset = (unsigned long)0xffffffff80000000ULL; > + cmdline_add_initrd(cmdline, page_offset + initrd_base, " rd_start="); > + cmdline_add_initrd(cmdline, initrd_size, " rd_size="); > + break; > + } > + } > + } > + fclose(fp); > + return 0; > +} > + > int elf_mips_probe(const char *buf, off_t len) > { > struct mem_ehdr ehdr; > @@ -171,9 +239,10 @@ int elf_mips_load(int argc, char **argv, const char *buf, off_t len, > /* Now that the buffer for initrd is prepared, update the dtb > * with an appropriate location */ > dtb_set_initrd(&dtb_buf, &dtb_length, initrd_base, initrd_base + initrd_size); > - } > - > > + /* Add the initrd parameters to cmdline */ > + patch_initrd_info(cmdline_buf, initrd_base, initrd_size); > + } > /* This is a legacy method for commandline passing used > * currently by Octeon CPUs only */ > add_buffer(info, cmdline_buf, sizeof(cmdline_buf), > -- > 2.20.1 > > > _______________________________________________ > kexec mailing list > kexec@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/kexec > _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec