[RFC PATCH 2/3] docs: document hwiso WorldGuard DT bindings and add QEMU overlay example
Raymond Mao
raymondmaoca at gmail.com
Fri May 1 11:33:45 PDT 2026
From: Raymond Mao <raymond.mao at riscstar.com>
Document the hw-isolation and worldguard_cfg device-tree metadata used
by the HWISO framework, and provide a QEMU virt overlay example showing
domain WID/WID list assignment and checker permission policy.
Signed-off-by: Raymond Mao <raymond.mao at riscstar.com>
---
docs/domain_support.md | 159 ++++++++++++++++++
.../generic/virt/qemu-virt-hwiso-overlay.dts | 120 +++++++++++++
2 files changed, 279 insertions(+)
create mode 100644 platform/generic/virt/qemu-virt-hwiso-overlay.dts
diff --git a/docs/domain_support.md b/docs/domain_support.md
index b34e43aa..d81f1bc6 100644
--- a/docs/domain_support.md
+++ b/docs/domain_support.md
@@ -201,6 +201,165 @@ The DT properties of a domain instance DT node are as follows:
whether the domain instance is allowed to do system reset.
* **system-suspend-allowed** (Optional) - A boolean flag representing
whether the domain instance is allowed to do system suspend.
+* **hw-isolation** (Optional) - A child node acting as a container for
+ system-level hardware isolation mechanisms. Each child node represents a
+ single mechanism configured via its compatible string and properties.
+
+Hardware Isolation Hooks
+------------------------
+
+OpenSBI provides a system-level hardware isolation framework that dispatches
+all registered mechanisms in the following phases:
+
+* **init** - Runs at boot to configure system-level isolation features.
+* **domain_init** - Parses per-domain isolation configuration.
+* **domain_exit** - Runs before switching out of a domain.
+* **domain_enter** - Runs after switching into a domain.
+
+Hardware Isolation Device Tree Binding
+--------------------------------------
+
+The hardware isolation configuration is specified as an optional child node
+named **hw-isolation** under a domain instance node. The **hw-isolation**
+node is a container for one or more mechanism nodes.
+
+The DT properties of a hardware isolation container node are as follows:
+
+* **#address-cells** / **#size-cells** (Optional) - Standard container node
+ properties. They are not interpreted by OpenSBI.
+
+Each hardware isolation mechanism has its own properties and compatible
+string. A mechanism can either use per-domain properties below the domain
+instance node, or parse system-level DT nodes describing isolation hardware.
+
+For the WorldGuard support on QEMU virt, OpenSBI parses the
+following WG-style system nodes:
+
+* **sifive,wgchecker2** - WorldGuard checker node.
+* **reg** - Checker MMIO base/size.
+* **sifive,slot-count** - Number of hardware checker slots.
+* **sifive,subordinates** - List of protected resource phandles owned by the
+ checker.
+* **worldguard_cfg** - Child node of a protected memory or device node
+ describing WorldGuard policy for that resource.
+* **perms** - 64-bit permission bitmap values encoded as **<hi lo>** cell
+ pairs, with either one value for the whole resource or one value per
+ protected range.
+* **reg** - Optional protected address ranges inside a **worldguard_cfg**
+ child. If omitted, the resource node's own **reg** is used. A single
+ subordinate with one **perms** entry and no explicit **worldguard_cfg/reg**
+ is treated as a full-checker rule.
+* **worldguard** - Optional CPU child node compatible with **riscv,wgcpu**
+ providing default WG execution state.
+* **mwid** - Default machine world ID for a hart.
+* **mwidlist** - Valid/delegable world IDs for that hart.
+
+Domain nodes can optionally provide WG execution metadata under the
+**hw-isolation** container:
+
+* **worldguard,wid** - Machine world ID selected when entering the domain.
+* **worldguard,widlist** - World IDs delegated to the domain.
+
+At runtime the WorldGuard implementation uses the hooks as follows:
+
+* **init** - Parses all WG checker nodes, validates the protected ranges, and
+ programs checker MMIO slots at boot when platform checker nodes are
+ present. Runtime WID/WID list support is enabled only when per-CPU WG
+ runtime nodes are present; checker-only DTs do not force runtime
+ switching on.
+* **domain_init** - Parses per-domain **worldguard,wid** and
+ **worldguard,widlist** metadata.
+* **domain_exit** - Quiesces the current hart back to its per-hart default
+ machine WID and clears **MWIDDELEG** before the handoff.
+* **domain_enter** - Reprograms **MLWID**, **MWIDDELEG**, and, when
+ delegation is active, **SLWID** for the destination domain when the hart
+ supports **smwg** / **sswg**.
+
+The CPU **worldguard** defaults are parsed per hart from **/cpus/<cpu>**, so
+platforms may provide different default **mwid** / **mwidlist** values on
+different harts.
+
+Hardware Isolation Examples
+---------------------------
+
+Domain instance with WG execution metadata:
+
+```text
+ chosen {
+ opensbi-domains {
+ compatible = "opensbi,domain,config";
+
+ example_domain: domain at 1 {
+ compatible = "opensbi,domain,instance";
+ possible-harts = <&cpu2>;
+ regions = <&mem0 0x3f>;
+ boot-hart = <&cpu2>;
+ next-addr = <0x00000000 0x80200000>;
+ next-mode = <0x1>;
+
+ hw-isolation {
+ worldguard {
+ compatible = "sifive,wgchecker2";
+ worldguard,wid = <1>;
+ worldguard,widlist = <1 3>;
+ };
+ };
+ };
+ };
+ };
+```
+
+WG checker, CPU default state, and protected resource example. These nodes
+remain in the normal system DT topology because they describe isolation
+hardware and protected resources, not OpenSBI domain instances:
+
+```text
+ cpu0: cpu at 0 {
+ worldguard {
+ compatible = "riscv,wgcpu";
+ mwid = <0>;
+ mwidlist = <0 1 3>;
+ };
+ };
+
+ flash0: flash at 20000000 {
+ reg = <0x0 0x20000000 0x0 0x2000000>;
+ worldguard_cfg {
+ perms = <0x0 0xc3>;
+ };
+ };
+
+ uart0: serial at 10000000 {
+ reg = <0x0 0x10000000 0x0 0x100>;
+ worldguard_cfg {
+ perms = <0x0 0xc0>;
+ };
+ };
+
+ memory0: memory at 80000000 {
+ reg = <0x0 0x80000000 0x0 0x80000000>;
+ worldguard_cfg {
+ reg = <0x0 0x80000000 0x0 0x40000000
+ 0x0 0xc0000000 0x0 0x01000000
+ 0x0 0xc1000000 0x0 0x3f000000>;
+ perms = <0x0 0xcf 0x0 0xcc 0x0 0xcf>;
+ };
+ };
+
+ wgchecker0: wgchecker at 10100000 {
+ compatible = "sifive,wgchecker2";
+ reg = <0x0 0x10100000 0x0 0x1000>;
+ sifive,slot-count = <8>;
+ sifive,subordinates = <&memory0 &flash0 &uart0>;
+ };
+```
+
+The test overlay used in this tree is at:
+
+* **platform/generic/virt/qemu-virt-hwiso-overlay.dts**
+
+That overlay only adds per-domain and per-resource metadata. The base DTB
+must still provide the WG checker nodes and per-CPU **worldguard** nodes.
### Assigning HART To Domain Instance
diff --git a/platform/generic/virt/qemu-virt-hwiso-overlay.dts b/platform/generic/virt/qemu-virt-hwiso-overlay.dts
new file mode 100644
index 00000000..63676abb
--- /dev/null
+++ b/platform/generic/virt/qemu-virt-hwiso-overlay.dts
@@ -0,0 +1,120 @@
+/dts-v1/;
+/plugin/;
+
+/*
+ * Test-only overlay for exercising HWISO with WorldGuard metadata.
+ *
+ * This overlay only adds OpenSBI domain metadata and worldguard_cfg resource
+ * policy. The base DTB is expected to already provide the WG checker nodes
+ * and per-CPU worldguard child nodes.
+ *
+ * Usage:
+ * Domain hart phandles are filled in after merge because fdtoverlay does not
+ * reliably resolve CPU-node references against QEMU dumpdtb output here.
+ * See below steps for filling the domain hart phandles (assume the dumped dtb
+ * and merged dtb are represented by 'qemu.dtb' and 'qemu-merged.dtb'
+ * respectively):
+ * cpu0_phandle=$(fdtget -t x qemu.dtb /cpus/cpu at 0 phandle)
+ * cpu1_phandle=$(fdtget -t x qemu.dtb /cpus/cpu at 1 phandle)
+ * fdtput -t x qemu-merged.dtb /chosen/opensbi-domains/domain at 0 \
+ * possible-harts "$cpu0_phandle" "$cpu1_phandle"
+ * fdtput -t x qemu-merged.dtb /chosen/opensbi-domains/domain at 0 \
+ * boot-hart "$cpu0_phandle"
+ * fdtput -t x qemu-merged.dtb /chosen/opensbi-domains/domain at 1 \
+ * possible-harts "$cpu1_phandle"
+ * fdtput -t x qemu-merged.dtb /chosen/opensbi-domains/domain at 1 \
+ * boot-hart "$cpu1_phandle"
+ */
+/ {
+ fragment at 0 {
+ target-path = "/chosen";
+ __overlay__ {
+ opensbi-domains {
+ compatible = "opensbi,domain,config";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ memregion0: memregion at 0 {
+ compatible = "opensbi,domain,memregion";
+ base = <0x00000000 0x80000000>;
+ order = <0x1f>;
+ };
+
+ guest0: domain at 0 {
+ compatible = "opensbi,domain,instance";
+ regions = <&memregion0 0x3f>;
+ next-addr = <0x00000000 0x80200000>;
+ next-arg1 = <0x00000000 0x82200000>;
+ next-mode = <0x1>;
+
+ hw-isolation {
+ worldguard {
+ compatible = "sifive,wgchecker2";
+ worldguard,wid = <0>;
+ worldguard,widlist = <0 1 3>;
+ };
+ };
+ };
+
+ guest1: domain at 1 {
+ compatible = "opensbi,domain,instance";
+ regions = <&memregion0 0x3f>;
+ next-addr = <0x00000000 0x80200000>;
+ next-mode = <0x1>;
+
+ hw-isolation {
+ worldguard {
+ compatible = "sifive,wgchecker2";
+ worldguard,wid = <1>;
+ worldguard,widlist = <1 3>;
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment at 1 {
+ target-path = "/cpus/cpu at 0";
+ __overlay__ {
+ opensbi-domain = <&guest0>;
+ };
+ };
+
+ fragment at 2 {
+ target-path = "/cpus/cpu at 1";
+ __overlay__ {
+ opensbi-domain = <&guest0>;
+ };
+ };
+
+ fragment at 3 {
+ target-path = "/memory at 80000000";
+ __overlay__ {
+ worldguard_cfg {
+ reg = <0x00000000 0x80000000 0x00000000 0x40000000
+ 0x00000000 0xc0000000 0x00000000 0x01000000
+ 0x00000000 0xc1000000 0x00000000 0x3f000000>;
+ perms = <0x0 0xcf 0x0 0xcc 0x0 0xcf>;
+ };
+ };
+ };
+
+ fragment at 4 {
+ target-path = "/flash at 20000000";
+ __overlay__ {
+ worldguard_cfg {
+ perms = <0x0 0xc3>;
+ };
+ };
+ };
+
+ fragment at 5 {
+ target-path = "/soc/serial at 10000000";
+ __overlay__ {
+ worldguard_cfg {
+ perms = <0x0 0xc0>;
+ };
+ };
+ };
+};
--
2.25.1
More information about the opensbi
mailing list