[PATCH v4] kexec-tools: mips: Pass initrd parameter via cmdline

Simon Horman horms at kernel.org
Thu Jun 23 07:17:14 PDT 2022


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 at loongson.cn>

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 at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
> 



More information about the kexec mailing list