[PATCH] lib: sbi_domain: Avoid overwriting coldboot hart's scratch->arg1

Samuel Holland samuel at sholland.org
Fri Dec 30 08:26:50 PST 2022


Hi Bin,

On 12/29/22 22:26, Bin Meng wrote:
> In sbi_domain_finalize(), when locating the coldboot hart's domain,
> the coldboot hart's scratch->arg1 will be overwritten by the domain
> configuration. scratch->arg1 holds the FDT address of the coldboot
> hart, and in later boot process OpenSBI codes still read the FDT
> here and there, which leads to a crash.

It sounds to me like the bug is in fdt_get_address(), not here. We
should save off the FDT address in some global variable, and not
continue getting it from next_arg1. Then there is no problem updating
next_arg1 from the domain configuration.

Regards,
Samuel

> To fix this, we save the next booting stage arg1 for the coldboot
> domain instance for the caller to use later.
> 
> Resolves: https://github.com/riscv-software-src/opensbi/issues/281
> Fixes: b1678af210dc ("lib: sbi: Add initial domain support")
> Reported-by: Marouene Boubakri <marouene.boubakri at nxp.com>
> Signed-off-by: Bin Meng <bmeng at tinylab.org>
> ---
> 
>  include/sbi/sbi_domain.h |  3 ++-
>  lib/sbi/sbi_domain.c     | 15 +++++++++++++--
>  lib/sbi/sbi_init.c       |  7 ++++++-
>  3 files changed, 21 insertions(+), 4 deletions(-)
> 
> diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h
> index 5553d21..0370d48 100644
> --- a/include/sbi/sbi_domain.h
> +++ b/include/sbi/sbi_domain.h
> @@ -195,7 +195,8 @@ int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size,
>  			   unsigned long align, unsigned long region_flags);
>  
>  /** Finalize domain tables and startup non-root domains */
> -int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid);
> +int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid,
> +			bool *coldboot_domain, unsigned long *next_arg1);
>  
>  /** Initialize domains */
>  int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid);
> diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
> index 3205595..bdef99f 100644
> --- a/lib/sbi/sbi_domain.c
> +++ b/lib/sbi/sbi_domain.c
> @@ -552,12 +552,14 @@ int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size,
>  	return 0;
>  }
>  
> -int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid)
> +int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid,
> +			bool *coldboot_domain, unsigned long *next_arg1)
>  {
>  	int rc;
>  	u32 i, dhart;
>  	struct sbi_domain *dom;
>  	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
> +	*coldboot_domain = false;
>  
>  	/* Initialize and populate domains for the platform */
>  	rc = sbi_platform_domains_init(plat);
> @@ -589,7 +591,16 @@ int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid)
>  		if (dhart == cold_hartid) {
>  			scratch->next_addr = dom->next_addr;
>  			scratch->next_mode = dom->next_mode;
> -			scratch->next_arg1 = dom->next_arg1;
> +			/*
> +			 * We cannot overwrite the scratch->next_arg1 here
> +			 * as it holds the FDT address for the coldboot hart.
> +			 *
> +			 * Instead, we save the next booting stage arg1 for
> +			 * the coldboot domain instance for the caller to
> +			 * use later.
> +			 */
> +			*coldboot_domain = true;
> +			*next_arg1 = dom->next_arg1;
>  		} else {
>  			rc = sbi_hsm_hart_start(scratch, NULL, dhart,
>  						dom->next_addr,
> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> index a8500e5..85d211b 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -240,6 +240,8 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
>  	int rc;
>  	unsigned long *init_count;
>  	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
> +	bool coldboot_domain;
> +	unsigned long next_arg1;
>  
>  	/* Note: This has to be first thing in coldboot init sequence */
>  	rc = sbi_scratch_init(scratch);
> @@ -314,7 +316,8 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
>  	 * Note: Finalize domains before HART PMP configuration so
>  	 * that we use correct domain for configuring PMP.
>  	 */
> -	rc = sbi_domain_finalize(scratch, hartid);
> +	rc = sbi_domain_finalize(scratch, hartid, &coldboot_domain,
> +				 &next_arg1);
>  	if (rc) {
>  		sbi_printf("%s: domain finalize failed (error %d)\n",
>  			   __func__, rc);
> @@ -351,6 +354,8 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
>  	(*init_count)++;
>  
>  	sbi_hsm_prepare_next_jump(scratch, hartid);
> +	if (coldboot_domain)
> +		scratch->next_arg1 = next_arg1;
>  	sbi_hart_switch_mode(hartid, scratch->next_arg1, scratch->next_addr,
>  			     scratch->next_mode, FALSE);
>  }




More information about the opensbi mailing list