[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