[PATCH v2 2/3] lib: sbi_domain: Re-work boot-time assignment of HARTs to non-ROOT domains

Yu-Chien Peter Lin peter.lin at sifive.com
Fri Aug 28 05:45:25 PDT 2026


Hi Anup,

On Mon, Aug 17, 2026 at 08:00:24PM +0530, Anup Patel wrote:
> Assign a non-ROOT domain to a HART on first come first serve basis if the
> HART is listed as a possible HART of the non-ROOT domain. If no non-ROOT
> domain list a HART as possible HART then the HART is assigned to the ROOT
> domain.
> 
> This allows us to drop the OpenSBI specific DT property from each CPU DT
> node (aka "opensbi-domain" Dt property).
> 
> Signed-off-by: Anup Patel <anup.patel at oss.qualcomm.com>
> ---
>  docs/domain_support.md             | 20 +++----
>  include/sbi/sbi_domain.h           |  4 +-
>  include/sbi_utils/fdt/fdt_domain.h |  3 +-
>  lib/sbi/sbi_domain.c               | 34 ++++++-----
>  lib/utils/fdt/fdt_domain.c         | 95 +++---------------------------
>  5 files changed, 35 insertions(+), 121 deletions(-)
> 
> diff --git a/docs/domain_support.md b/docs/domain_support.md
> index e267a9f7..82f155e1 100644
> --- a/docs/domain_support.md
> +++ b/docs/domain_support.md
> @@ -207,15 +207,14 @@ The DT properties of a domain instance DT node are as follows:
>  
>  ### Assigning HART To Domain Instance
>  
> -By default, all HARTs are assigned to **the ROOT domain**. The OpenSBI
> -platform support can provide the HART to domain instance assignment using
> -platform specific callback.
> +At boot-time, a HART is assigned to a non-ROOT domain on first come
> +first serve basis if the HART is listed as a possible HART of the
> +non-ROOT domain. If no non-ROOT domain list a HART as possible HART
> +then the HART is assigned to **the ROOT domain**.
>  
> -The HART to domain instance assignment can be parsed from the device tree
> -using optional DT property **opensbi-domain** in each CPU DT node. The
> -value of DT property **opensbi-domain** is the DT phandle of the domain
> -instance DT node. If **opensbi-domain** DT property is not specified then
> -corresponding HART is assigned to **the ROOT domain**.
> +At runtime, the assignment of a HART can change from one domain to
> +another domain as long as the HART is listed in possible HARTs of
> +both domains.
>  
>  ### Domain Configuration Only Accessible to OpenSBI
>  
> @@ -289,7 +288,6 @@ be done:
>              device_type = "cpu";
>              reg = <0x00>;
>              compatible = "riscv";
> -            opensbi-domain = <&tdomain>;
>              ...
>          };
>  
> @@ -297,7 +295,6 @@ be done:
>              device_type = "cpu";
>              reg = <0x01>;
>              compatible = "riscv";
> -            opensbi-domain = <&udomain>;
>              ...
>          };
>  
> @@ -305,7 +302,6 @@ be done:
>              device_type = "cpu";
>              reg = <0x02>;
>              compatible = "riscv";
> -            opensbi-domain = <&udomain>;
>              ...
>          };
>  
> @@ -313,7 +309,6 @@ be done:
>              device_type = "cpu";
>              reg = <0x03>;
>              compatible = "riscv";
> -            opensbi-domain = <&udomain>;
>              ...
>          };
>  
> @@ -321,7 +316,6 @@ be done:
>              device_type = "cpu";
>              reg = <0x04>;
>              compatible = "riscv";
> -            opensbi-domain = <&udomain>;
>              ...
>          };
>      };
> diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h
> index 16edd4ce..b6731c04 100644
> --- a/include/sbi/sbi_domain.h
> +++ b/include/sbi/sbi_domain.h
> @@ -328,12 +328,10 @@ void sbi_domain_dump_all(const char *suffix);
>  /**
>   * Register a new domain
>   * @param dom pointer to domain
> - * @param assign_mask pointer to HART mask of HARTs assigned to the domain
>   *
>   * @return 0 on success and negative error code on failure
>   */
> -int sbi_domain_register(struct sbi_domain *dom,
> -			const struct sbi_hartmask *assign_mask);
> +int sbi_domain_register(struct sbi_domain *dom);
>  
>  /**
>   * Add a memory range with its flags to the root domain
> diff --git a/include/sbi_utils/fdt/fdt_domain.h b/include/sbi_utils/fdt/fdt_domain.h
> index 8c2dee09..a366b271 100644
> --- a/include/sbi_utils/fdt/fdt_domain.h
> +++ b/include/sbi_utils/fdt/fdt_domain.h
> @@ -50,8 +50,7 @@ int fdt_iterate_each_memregion(void *fdt, int domain_offset, void *opaque,
>   *
>   * This routine:
>   * 1. Disables MMIO devices not accessible to the coldboot HART domain
> - * 2. Removes "opensbi-domain" DT property from CPU DT nodes
> - * 3. Removes domain configuration DT node under /chosen DT node
> + * 2. Removes domain configuration DT node under /chosen DT node
>   *
>   * It is recommended that platform support call this function in
>   * their final_init() platform operation.
> diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
> index fa69170b..af753459 100644
> --- a/lib/sbi/sbi_domain.c
> +++ b/lib/sbi/sbi_domain.c
> @@ -625,16 +625,14 @@ void sbi_domain_dump_all(const char *suffix)
>  	}
>  }
>  
> -int sbi_domain_register(struct sbi_domain *dom,
> -			const struct sbi_hartmask *assign_mask)
> +int sbi_domain_register(struct sbi_domain *dom)
>  {
> -	u32 i;
> -	int rc;
> +	u32 i, cold_hartid = current_hartid();
>  	struct sbi_domain *tdom;
> -	u32 cold_hartid = current_hartid();
> +	int rc;
>  
>  	/* Sanity checks */
> -	if (!dom || !assign_mask || domain_finalized)
> +	if (!dom || domain_finalized)
>  		return SBI_EINVAL;
>  
>  	/* Check if domain already discovered */
> @@ -663,15 +661,21 @@ int sbi_domain_register(struct sbi_domain *dom,
>  	/* Clear assigned HARTs of domain */
>  	sbi_hartmask_clear_all(&dom->assigned_harts);
>  
> -	/* Assign domain to HART if HART is a possible HART */
> -	sbi_hartmask_for_each_hartindex(i, assign_mask) {
> -		if (!sbi_hartmask_test_hartindex(i, dom->possible_harts))
> -			continue;
> -
> +	/*
> +	 * Assign a non-ROOT domain to a HART on first come first serve
> +	 * basis if the HART is listed as a possible HART of the non-ROOT
> +	 * domain. If no non-ROOT domain list a HART as possible HART then
> +	 * the HART is assigned to the ROOT domain.
> +	 */
> +	sbi_hartmask_for_each_hartindex(i, dom->possible_harts) {
>  		tdom = sbi_hartindex_to_domain(i);
> -		if (tdom)
> -			sbi_hartmask_clear_hartindex(i,
> -					&tdom->assigned_harts);
> +		if (tdom) {
> +			if (tdom == &root)
> +				sbi_hartmask_clear_hartindex(i, &tdom->assigned_harts);
> +			else
> +				continue;
> +		}
> +
>  		sbi_update_hartindex_to_domain(i, dom);
>  		sbi_hartmask_set_hartindex(i, &dom->assigned_harts);
>  
> @@ -975,7 +979,7 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
>  		sbi_hartmask_set_hartindex(i, root_hmask);
>  
>  	/* Finally register the root domain */
> -	rc = sbi_domain_register(&root, root_hmask);
> +	rc = sbi_domain_register(&root);
>  	if (rc)
>  		goto fail_free_root_hmask;
>  
> diff --git a/lib/utils/fdt/fdt_domain.c b/lib/utils/fdt/fdt_domain.c
> index 61627db3..3857831d 100644
> --- a/lib/utils/fdt/fdt_domain.c
> +++ b/lib/utils/fdt/fdt_domain.c
> @@ -170,26 +170,11 @@ static int __fixup_disable_devices(void *fdt, int doff, int roff,
>  
>  void fdt_domain_fixup(void *fdt)
>  {
> -	u32 i, dcount;
> +	u32 dcount;
>  	int err, poffset, doffset;
>  	struct sbi_domain *dom = sbi_domain_thishart_ptr();
>  	struct __fixup_find_domain_offset_info fdo;
>  
> -	/* Remove the domain assignment DT property from CPU DT nodes */
> -	poffset = fdt_path_offset(fdt, "/cpus");
> -	if (poffset < 0)
> -		return;
> -	fdt_for_each_subnode(doffset, fdt, poffset) {
> -		err = fdt_parse_hart_id(fdt, doffset, &i);
> -		if (err)
> -			continue;
> -
> -		if (!fdt_node_is_enabled(fdt, doffset))
> -			continue;
> -
> -		fdt_nop_property(fdt, doffset, "opensbi-domain");
> -	}
> -
>  	/* Skip device disable for root domain */
>  	if (!dom->index)
>  		goto skip_device_disable;
> @@ -315,12 +300,10 @@ static int __fdt_parse_domain(const void *fdt, int domain_offset, void *opaque)
>  	const char *inherit;
>  	struct sbi_domain *dom;
>  	struct sbi_hartmask *mask;
> -	struct sbi_hartmask assign_mask;
>  	struct parse_region_data preg;
> -	int *cold_domain_offset = opaque;
>  	struct sbi_domain_memregion *reg;
>  	int inheritance_mode = FDT_ROOT_REGION_INHERIT_M_ONLY;
> -	int i, err = 0, len, cpus_offset, cpu_offset, doffset;
> +	int i, err = 0, len, cpus_offset, cpu_offset;
>  
>  	dom = sbi_zalloc(sizeof(*dom));
>  	if (!dom)
> @@ -440,7 +423,7 @@ static int __fdt_parse_domain(const void *fdt, int domain_offset, void *opaque)
>  		val64 = fdt32_to_cpu(val[0]);
>  		val64 = (val64 << 32) | fdt32_to_cpu(val[1]);
>  	} else {
> -		val64 = sbi_scratch_thishart_ptr()->next_arg1;
> +		val64 = root.next_arg1;
>  	}
>  	dom->next_arg1 = val64;
>  
> @@ -451,8 +434,7 @@ static int __fdt_parse_domain(const void *fdt, int domain_offset, void *opaque)
>  		val64 = fdt32_to_cpu(val[0]);
>  		val64 = (val64 << 32) | fdt32_to_cpu(val[1]);
>  	} else {
> -		if (domain_offset == *cold_domain_offset)
> -			val64 = sbi_scratch_thishart_ptr()->next_addr;
> +		val64 = root.next_addr;
>  	}
>  	dom->next_addr = val64;
>  
> @@ -464,8 +446,7 @@ static int __fdt_parse_domain(const void *fdt, int domain_offset, void *opaque)
>  		if (val32 != 0x0 && val32 != 0x1)
>  			val32 = 0x1;
>  	} else {
> -		if (domain_offset == *cold_domain_offset)
> -			val32 = sbi_scratch_thishart_ptr()->next_mode;
> +		val32 = root.next_mode;
>  	}
>  	dom->next_mode = val32;

We may update domain_support.md accordingly to reflect these changes.
https://github.com/riscv-software-src/opensbi/blob/4e79fd7de59f1b2899092c1a84ce68c8ebc68f93/docs/domain_support.md?plain=1#L186-L202

>  
> @@ -490,37 +471,8 @@ static int __fdt_parse_domain(const void *fdt, int domain_offset, void *opaque)
>  		goto fail_free_all;
>  	}
>  
> -	/* HART to domain assignment mask based on CPU DT nodes */
> -	sbi_hartmask_clear_all(&assign_mask);
> -	fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) {

cpus_offset is unused now in __fdt_parse_domain().

Best regards,
Peter Lin

> -		err = fdt_parse_hart_id(fdt, cpu_offset, &val32);
> -		if (err)
> -			continue;
> -
> -		if (SBI_HARTMASK_MAX_BITS <= sbi_hartid_to_hartindex(val32))
> -			continue;
> -
> -		if (!fdt_node_is_enabled(fdt, cpu_offset))
> -			continue;
> -
> -		/* This is an optional property */
> -		val = fdt_getprop(fdt, cpu_offset, "opensbi-domain", &len);
> -		if (!val || len < 4)
> -			continue;
> -
> -		/* However, it should be valid if specified */
> -		doffset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> -		if (doffset < 0) {
> -			err = doffset;
> -			goto fail_free_all;
> -		}
> -
> -		if (doffset == domain_offset)
> -			sbi_hartmask_set_hartid(val32, &assign_mask);
> -	}
> -
>  	/* Register the domain */
> -	err = sbi_domain_register(dom, &assign_mask);
> +	err = sbi_domain_register(dom);
>  	if (err)
>  		goto fail_free_all;
>  
> @@ -537,43 +489,10 @@ fail_free_domain:
>  
>  int fdt_domains_populate(const void *fdt)
>  {
> -	const u32 *val;
> -	int cold_domain_offset;
> -	u32 hartid, cold_hartid;
> -	int err, len, cpus_offset, cpu_offset;
> -
>  	/* Sanity checks */
>  	if (!fdt)
>  		return SBI_EINVAL;
>  
> -	/* Find /cpus DT node */
> -	cpus_offset = fdt_path_offset(fdt, "/cpus");
> -	if (cpus_offset < 0)
> -		return cpus_offset;
> -
> -	/* Find coldboot HART domain DT node offset */
> -	cold_domain_offset = -1;
> -	cold_hartid = current_hartid();
> -	fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) {
> -		err = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
> -		if (err)
> -			continue;
> -
> -		if (hartid != cold_hartid)
> -			continue;
> -
> -		if (!fdt_node_is_enabled(fdt, cpu_offset))
> -			continue;
> -
> -		val = fdt_getprop(fdt, cpu_offset, "opensbi-domain", &len);
> -		if (val && len >= 4)
> -			cold_domain_offset = fdt_node_offset_by_phandle(fdt,
> -							   fdt32_to_cpu(*val));
> -
> -		break;
> -	}
> -
>  	/* Iterate over each domain in FDT and populate details */
> -	return fdt_iterate_each_domain_ro(fdt, &cold_domain_offset,
> -					  __fdt_parse_domain);
> +	return fdt_iterate_each_domain_ro(fdt, NULL, __fdt_parse_domain);
>  }



More information about the opensbi mailing list