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 <peter.lin@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260516072906.1427203-1-peter.lin@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Yu-Chien Peter Lin
2026-05-16 15:29:06 +08:00
committed by Anup Patel
parent 22d7e99ed2
commit f36acaeb80
2 changed files with 47 additions and 13 deletions
+7
View File
@@ -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 * **possible-harts** (Optional) - The list of CPU DT node phandles for the
the domain instance. This list represents the possible HARTs of the the domain instance. This list represents the possible HARTs of the
domain instance. 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 * **regions** (Optional) - The list of domain memory region DT node phandle
and access permissions for the domain instance. Each list entry is a pair and access permissions for the domain instance. Each list entry is a pair
of DT node phandle and access permissions. The access permissions are of DT node phandle and access permissions. The access permissions are
+39 -12
View File
@@ -10,6 +10,7 @@
#include <libfdt.h> #include <libfdt.h>
#include <libfdt_env.h> #include <libfdt_env.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_domain.h> #include <sbi/sbi_domain.h>
#include <sbi/sbi_error.h> #include <sbi/sbi_error.h>
#include <sbi/sbi_hartmask.h> #include <sbi/sbi_hartmask.h>
@@ -238,6 +239,8 @@ skip_device_disable:
} }
#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 parse_region_data {
struct sbi_domain *dom; struct sbi_domain *dom;
@@ -309,12 +312,14 @@ static int __fdt_parse_domain(const void *fdt, int domain_offset, void *opaque)
u32 val32; u32 val32;
u64 val64; u64 val64;
const u32 *val; const u32 *val;
const char *inherit;
struct sbi_domain *dom; struct sbi_domain *dom;
struct sbi_hartmask *mask; struct sbi_hartmask *mask;
struct sbi_hartmask assign_mask; struct sbi_hartmask assign_mask;
struct parse_region_data preg; struct parse_region_data preg;
int *cold_domain_offset = opaque; int *cold_domain_offset = opaque;
struct sbi_domain_memregion *reg; 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, doffset;
dom = sbi_zalloc(sizeof(*dom)); dom = sbi_zalloc(sizeof(*dom));
@@ -373,20 +378,42 @@ static int __fdt_parse_domain(const void *fdt, int domain_offset, void *opaque)
if (err) if (err)
goto fail_free_all; goto fail_free_all;
/* /* Determine root domain regions inheritance behavior. */
* Copy over root domain memregions which don't allow inherit = fdt_getprop(fdt, domain_offset,
* read, write and execute from lower privilege modes. "root-regions-inheritance", &len);
* if (inherit && len > 0) {
* These root domain memregions without read, write, if (!strcmp(inherit, "all"))
* and execute permissions include: inheritance_mode = FDT_ROOT_REGION_INHERIT_ALL;
* 1) firmware region protecting the firmware memory else if (!strcmp(inherit, "m-only"))
* 2) mmio regions protecting M-mode only mmio devices 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) { sbi_domain_for_each_memregion(&root, reg) {
if ((reg->flags & SBI_DOMAIN_MEMREGION_SU_READABLE) || bool copy = false;
(reg->flags & SBI_DOMAIN_MEMREGION_SU_WRITABLE) ||
(reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE)) 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; continue;
if (preg.max_regions <= preg.region_count) { if (preg.max_regions <= preg.region_count) {
err = SBI_EINVAL; err = SBI_EINVAL;
goto fail_free_all; goto fail_free_all;