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

Bin Meng bmeng at tinylab.org
Thu Dec 29 20:26:11 PST 2022


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.

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);
 }
-- 
2.34.1




More information about the opensbi mailing list