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 <[email protected]>

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
> [email protected]
> http://lists.infradead.org/mailman/listinfo/kexec
> 

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to