[PATCH v3 0/5] Add WorldGuard support with SiFive WG checker

Yu-Chien Peter Lin peter.lin at sifive.com
Wed Oct 28 21:28:57 PDT 2026


Hi Raymond,

On Fri, Sep 04, 2026 at 12:29:10PM -0400, Raymond Mao wrote:
> From: Raymond Mao <raymond.mao at riscstar.com>
> 
> This series adds WorldGuard support according to the wgchecker2 DT-
> binding proposal from SiFive [1] with QEMU virt integration.
> 
> The implementation:
> - reuse sbi_hart_protection for hart-local runtime reconfiguration
> - reuse sbi_domain_data for per-domain WorldGuard state
> - keep WorldGuard-specific setup and checker programming in platform
>   code
> 
> At boot, the generic platform code invokes a QEMU virt WorldGuard
> setup path which:
> - parses wgchecker2 checker instances
> - parses provider partition at N entries and programs checker MMIO
> - parses per-hart CPU defaults from /cpus
> - parses per-domain WorldGuard metadata under hw-isolation
> 
> Checker programming is provider-driven. Consumer-side
> access-controllers references are carried for DT-binding alignment.
> 
> During domain transitions, the WorldGuard hart protection
> implementation reprograms MLWID and, when available, MLWIDLIST,
> MWIDDELEG, and SLWID.
> 
> The series is split as follows:
> 1. add reusable FDT helpers needed by the WorldGuard parser
> 2. add WorldGuard CSR definitions and hart extension flags
> 3. document the current DT layout consumed by the implementation
> 4. add the wgchecker2 / WorldGuard runtime and QEMU virt integration
> 
> Tested with:
> - QEMU riscv-wg-v4-260821 [2] with arg 'worlds=on' and the merged
>   WorldGuard test DTB.
> 
> [1] dt-bindings: riscv: Add RISC-V Worlds and SiFive WorldGuard DT
>     bindings
>     https://lore.kernel.org/linux-devicetree/20260812122131.1534906-1-peter.lin@sifive.com/
> [2] https://github.com/cwshu/qemu/tree/riscv-wg-v4-260821

Thanks for working on this series. Could we align the implementation with
the DT proposal on a few key points?

1. Domain WIDs should use wid / widdeleg directly under domain nodes, not
   hw-isolation with sifive,wgchecker2. 
   My patches already handle the WID assignment and switching.
   https://patchwork.ozlabs.org/project/opensbi/patch/20261027083509.1076577-10-peter.lin@sifive.com/
2. wgChecker is a static firewall configured once at boot; by design it does
   not support efficient dynamic reconfiguration.
3. Unlike sequential first-match PMP, wgChecker slots are strictly accretive
   (parallel OR), so overlapping rules cannot restrict access. i.e.

   /* PMP (Priority-based, sequential): */
   for (i = N-1; i >= 0; i--) {
       if (pmp[i].matches(addr))
           return pmp[i].perm;      // FIRST match wins
   }
   
   /* wgChecker (Strictly accretive, parallel): */
   perm = NO_ACCESS;
   for (i = 0; i < nslots; i++) {
       if (slot[i].matches(addr))
           perm |= slot[i].perm[wid]; // OR all matches
   }
   if (perm allows access)
       grant_access();
   
   The wgChecker driver should automatically select between NAPOT and TOR
   encoding to minimize slot usage.

4. OpenSBI should support use cases below and dump the wgChecker slot info at boot:

========================================================================
Use Case 1: Single-Slot Peripheral Protection (Full Subordinate Range)
========================================================================

0x001c_1000 +---------------------------------------------------+
            | partition at 0 : [0x001c_1000, 0x001c_2000)          |
            | serial at 1c1000 | WID 0,3 RW (perm 0xc3, cfg 0x1f)  |
            | Slot00..01  : A=TOR (Slot00 base, Slot01 top)     |
0x001c_2000 +---------------------------------------------------+

uart: serial at 1c1000 {
    reg = <0x001c1000 0x1000>;
    access-controllers = <&wgc0 0>;
};

wgc0: access-controller at 1c2000 {
    compatible = "qemu,wgchecker2", "sifive,wgchecker2";
    reg = <0x0 0x001c2000 0x0 0x1000>;
    #access-controller-cells = <1>;
    #address-cells = <1>;
    #size-cells = <0>;

    partition at 0 {
        reg = <0>;
        sifive,wg-region = <0x0 0x001c1000 0x0 0x00001000>;
        sifive,slot-permissions = <0x0 0x000000c3>;
        sifive,slot-config = <0x1f>;
    };
};

Expected OpenSBI boot dump:
wgChecker Base       : 0x1c2000
wgChecker Slot00     : 0x00000000001c1000-.................. 00: A:0 ER:1 EW:1 IR:1 IW:1 L:0
wgChecker Slot01     : ..................-0x00000000001c2000 c3: A:1 ER:1 EW:1 IR:1 IW:1 L:1
wgChecker Slot Usage : 1 (total), 1 (used), 0 (free)

========================================================================
Use Case 2: Multi-Region Peripheral Protection (Disjoint Register Groups)
========================================================================

0x0001_0000 +---------------------------------------------------+
            | partition at 0 : [0x0001_0000, 0x0001_8000) (32 KiB) |
            | reg[0] m_mode | WID 3 RW   (perm 0xc0) | Slot01   |
0x0001_8000 +---------------------------------------------------+
            :                  (unreferenced)                   :
0x00a0_0000 +---------------------------------------------------+
            | partition at 1 : [0x00a0_0000, 0x00a0_4000) (16 KiB) |
            | reg[1] s_mode | WID 0,3 RW (perm 0xc3) | Slot02   |
0x00a0_4000 +---------------------------------------------------+

device at 10000 {
    reg = <0x0 0x00010000 0x0 0x8000>,
          <0x0 0x00a00000 0x0 0x4000>;
    reg-names = "m_mode", "s_mode";
    access-controllers = <&wgc1 0>, <&wgc1 1>;
};

wgc1: access-controller at 35000 {
    compatible = "qemu,wgchecker2", "sifive,wgchecker2";
    reg = <0x0 0x00035000 0x0 0x1000>;
    #access-controller-cells = <1>;
    #address-cells = <1>;
    #size-cells = <0>;

    partition at 0 {
        reg = <0>;
        sifive,wg-region = <0x0 0x00010000 0x0 0x00008000>;
        sifive,slot-permissions = <0x0 0x000000c0>;
        sifive,slot-config = <0x0f>;
    };
    partition at 1 {
        reg = <1>;
        sifive,wg-region = <0x0 0x00a00000 0x0 0x00004000>;
        sifive,slot-permissions = <0x0 0x000000c3>;
        sifive,slot-config = <0x0f>;
    };
};

Expected OpenSBI boot dump:
wgChecker Base       : 0x35000
wgChecker Slot00     : 0x0000000000000000-.................. 00: A:0 ER:1 EW:1 IR:1 IW:1 L:0
wgChecker Slot01     : 0x0000000000010000-0x0000000000018000 c0: A:3 ER:1 EW:1 IR:1 IW:1 L:0
wgChecker Slot02     : 0x0000000000a00000-0x0000000000a04000 c3: A:3 ER:1 EW:1 IR:1 IW:1 L:0
wgChecker Slot04     : ..................-0x0000000001000000 00: A:0 ER:0 EW:0 IR:0 IW:0 L:0
wgChecker Slot Usage : 4 (total), 2 (used), 2 (free)

========================================================================
Use Case 3: Multi-Domain DRAM Spatial Partitioning (Hybrid NAPOT + TOR)
========================================================================

OpenSBI: WID3
Linux  : WID0
OP-TEE : WID1

  0x8000_0000 +---------------------------------------------------+
              | partition at 0 : [0x8000_0000, 0xC000_0000) (1024M)  |
              | Linux / OpenSBI | WID 0,1,3 RW (0xcf) | Slot01 A:3|
  0xC000_0000 +---------------------------------------------------+
              | partition at 1 : [0xC000_0000, 0xC100_0000) (16M)    |
              | OP-TEE / OpenSBI| WID 1,3 RW   (0xcc) | Slot02 A:3|
  0xC100_0000 +---------------------------------------------------+
              | partition at 2 : [0xC100_0000, 0x1_0000_0000) (1008M)|
              | Linux / OpenSBI | WID 0,1,3 RW (0xcf) | Slot03..04|
0x1_0000_0000 +-------------------------------------------------+

memory: memory at 80000000 {
    reg = <0x0 0x80000000 0x0 0x80000000>;
    access-controllers = <&wgc2 0>, <&wgc2 1>, <&wgc2 2>;
};

wgc2: access-controller at 50000000 {
    compatible = "qemu,wgchecker2", "sifive,wgchecker2";
    reg = <0x0 0x50000000 0x0 0x1000>;
    #access-controller-cells = <1>;
    #address-cells = <1>;
    #size-cells = <0>;

    partition at 0 {
        reg = <0>;
        sifive,wg-region = <0x0 0x80000000 0x0 0x40000000>;
        sifive,slot-permissions = <0x0 0x000000cf>;
        sifive,slot-config = <0x0f>;
    };
    partition at 1 {
        reg = <1>;
        sifive,wg-region = <0x0 0xc0000000 0x0 0x01000000>;
        sifive,slot-permissions = <0x0 0x000000cc>;
        sifive,slot-config = <0x0f>;
    };
    partition at 2 {
        reg = <2>;
        sifive,wg-region = <0x0 0xc1000000 0x0 0x3f000000>;
        sifive,slot-permissions = <0x0 0x000000cf>;
        sifive,slot-config = <0x0f>;
    };
};

Expected OpenSBI boot dump:
wgChecker Base              : 0x50000000
wgChecker Slot00            : 0x0000000000000000-.................. 00: A:0 ER:1 EW:1 IR:1 IW:1 L:0
wgChecker Slot01            : 0x0000000080000000-0x00000000c0000000 cf: A:3 ER:1 EW:1 IR:1 IW:1 L:0
wgChecker Slot02            : 0x00000000c0000000-0x00000000c1000000 cc: A:3 ER:1 EW:1 IR:1 IW:1 L:0
wgChecker Slot03            : 0x00000000c1000000-.................. 00: A:0
wgChecker Slot04            : ..................-0x0000000100000000 cf: A:1 ER:1 EW:1 IR:1 IW:1 L:0
wgChecker Slot16            : ..................-0x0000000100000000 00: A:0 ER:0 EW:0 IR:0 IW:0 L:0
wgChecker Slot Usage        : 16 (total), 4 (used), 12 (free)

Best regards,
Peter Lin



More information about the opensbi mailing list