From f36acaeb80a490339923a5ec01ac3707741f6b90 Mon Sep 17 00:00:00 2001 From: Yu-Chien Peter Lin Date: Sat, 16 May 2026 15:29:06 +0800 Subject: [PATCH] lib: utils: fdt_domain: add root-regions-inheritance policy Introduce root-regions-inheritance DT property to control copying of root domain memregions. Support 'all' and 'm-only' modes, always inheriting firmware and M-only regions; behavior matches m-only policy when property is absent. Signed-off-by: Yu-Chien Peter Lin Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20260516072906.1427203-1-peter.lin@sifive.com Signed-off-by: Anup Patel --- docs/domain_support.md | 7 +++++ lib/utils/fdt/fdt_domain.c | 53 ++++++++++++++++++++++++++++---------- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/docs/domain_support.md b/docs/domain_support.md index c01e445f..e267a9f7 100644 --- a/docs/domain_support.md +++ b/docs/domain_support.md @@ -159,6 +159,13 @@ The DT properties of a domain instance DT node are as follows: * **possible-harts** (Optional) - The list of CPU DT node phandles for the the domain instance. This list represents the possible HARTs of the domain instance. +* **root-regions-inheritance** (Optional) - A string property controlling + how memory regions are inherited from **the ROOT domain**, which are then + overlaid with regions specified in the **regions** property for additional + restrictions. The allowed values are: + * "all" - inherit all memory regions from **the ROOT domain** + * "m-only" - inherit M-mode only memory regions from **the ROOT domain** + If this DT property is absent, behavior is the same as "m-only". * **regions** (Optional) - The list of domain memory region DT node phandle and access permissions for the domain instance. Each list entry is a pair of DT node phandle and access permissions. The access permissions are diff --git a/lib/utils/fdt/fdt_domain.c b/lib/utils/fdt/fdt_domain.c index 1b039533..61627db3 100644 --- a/lib/utils/fdt/fdt_domain.c +++ b/lib/utils/fdt/fdt_domain.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -237,7 +238,9 @@ skip_device_disable: fdt_nop_node(fdt, poffset); } -#define FDT_DOMAIN_REGION_MAX_COUNT 16 +#define FDT_DOMAIN_REGION_MAX_COUNT 16 +#define FDT_ROOT_REGION_INHERIT_M_ONLY 0 +#define FDT_ROOT_REGION_INHERIT_ALL 1 struct parse_region_data { struct sbi_domain *dom; @@ -309,12 +312,14 @@ static int __fdt_parse_domain(const void *fdt, int domain_offset, void *opaque) u32 val32; u64 val64; const u32 *val; + 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; dom = sbi_zalloc(sizeof(*dom)); @@ -373,20 +378,42 @@ static int __fdt_parse_domain(const void *fdt, int domain_offset, void *opaque) if (err) goto fail_free_all; - /* - * Copy over root domain memregions which don't allow - * read, write and execute from lower privilege modes. - * - * These root domain memregions without read, write, - * and execute permissions include: - * 1) firmware region protecting the firmware memory - * 2) mmio regions protecting M-mode only mmio devices - */ + /* Determine root domain regions inheritance behavior. */ + inherit = fdt_getprop(fdt, domain_offset, + "root-regions-inheritance", &len); + if (inherit && len > 0) { + if (!strcmp(inherit, "all")) + inheritance_mode = FDT_ROOT_REGION_INHERIT_ALL; + else if (!strcmp(inherit, "m-only")) + inheritance_mode = FDT_ROOT_REGION_INHERIT_M_ONLY; + else { + sbi_printf("%s: domain \"%s\" has unsupported " + "root-regions-inheritance=\"%s\"\n", + __func__, dom->name, inherit); + err = SBI_EINVAL; + goto fail_free_all; + } + } + + /* Copy over root domain memregions according to inheritance_mode. */ sbi_domain_for_each_memregion(&root, reg) { - if ((reg->flags & SBI_DOMAIN_MEMREGION_SU_READABLE) || - (reg->flags & SBI_DOMAIN_MEMREGION_SU_WRITABLE) || - (reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE)) + bool copy = false; + + switch (inheritance_mode) { + case FDT_ROOT_REGION_INHERIT_ALL: + copy = true; + break; + case FDT_ROOT_REGION_INHERIT_M_ONLY: + if (SBI_DOMAIN_MEMREGION_IS_FIRMWARE(reg->flags) || + SBI_DOMAIN_MEMREGION_M_ONLY_ACCESS(reg->flags)) { + copy = true; + } + break; + } + + if (!copy) continue; + if (preg.max_regions <= preg.region_count) { err = SBI_EINVAL; goto fail_free_all;