On 10/13/2026 10:22 PM, Bin Meng wrote:
FU540 and PolarFire use the same L2 configuration and way-control
interface, with different master counts. The `sifive_u` machine
currently leaves L2CC unimplemented and exposes L2-LIM as fixed
RAM without WayEnable control.

Instantiate the shared SiFive L2CC with 21 masters and a modeled
2 MiB Zero window.

Signed-off-by: Bin Meng <[email protected]>


Reviewed-by: Daniel Henrique Barboza <[email protected]>

---

(no changes since v3)

Changes in v3:
- New

  docs/system/riscv/sifive_u.rst |  2 +-
  include/hw/riscv/sifive_u.h    |  3 +++
  hw/riscv/sifive_u.c            | 30 +++++++++++++-----------------
  hw/riscv/Kconfig               |  1 +
  4 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
index 0e4dcf3e70..e91853ffe2 100644
--- a/docs/system/riscv/sifive_u.rst
+++ b/docs/system/riscv/sifive_u.rst
@@ -14,7 +14,7 @@ The ``sifive_u`` machine supports the following devices:
  * Core Local Interruptor (CLINT)
  * Platform-Level Interrupt Controller (PLIC)
  * Power, Reset, Clock, Interrupt (PRCI)
-* L2 Loosely Integrated Memory (L2-LIM)
+* L2 cache controller, including L2-LIM and L2-Zero windows
  * DDR memory controller
  * 2 UARTs
  * 1 GEM Ethernet controller
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index aed966a62d..be5e6232ce 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -28,6 +28,7 @@
  #include "hw/gpio/sifive_gpio.h"
  #include "hw/misc/sifive_u_otp.h"
  #include "hw/misc/sifive_u_prci.h"
+#include "hw/misc/sifive_l2cc.h"
  #include "hw/ssi/sifive_spi.h"
  #include "hw/timer/sifive_pwm.h"
@@ -45,6 +46,7 @@ typedef struct SiFiveUSoCState {
      RISCVHartArrayState e_cpus;
      RISCVHartArrayState u_cpus;
      DeviceState *plic;
+    SiFiveL2CCState l2cc;
      SiFiveUPRCIState prci;
      SIFIVEGPIOState gpio;
      SiFiveUOTPState otp;
@@ -82,6 +84,7 @@ enum {
      SIFIVE_U_DEV_L2CC,
      SIFIVE_U_DEV_PDMA,
      SIFIVE_U_DEV_L2LIM,
+    SIFIVE_U_DEV_L2ZERO,
      SIFIVE_U_DEV_PLIC,
      SIFIVE_U_DEV_PRCI,
      SIFIVE_U_DEV_UART0,
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 1ac0d1bbd9..3603cc2aa2 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -73,6 +73,7 @@ static const MemMapEntry sifive_u_memmap[] = {
      [SIFIVE_U_DEV_L2CC] =     {  0x2010000,     0x1000 },
      [SIFIVE_U_DEV_PDMA] =     {  0x3000000,   0x100000 },
      [SIFIVE_U_DEV_L2LIM] =    {  0x8000000,   0x200000 },
+    [SIFIVE_U_DEV_L2ZERO] =   {  0xa000000,   0x200000 },
      [SIFIVE_U_DEV_PLIC] =     {  0xc000000,  0x4000000 },
      [SIFIVE_U_DEV_PRCI] =     { 0x10000000,     0x1000 },
      [SIFIVE_U_DEV_UART0] =    { 0x10010000,     0x1000 },
@@ -715,6 +716,10 @@ static void sifive_u_soc_instance_init(Object *obj)
      object_initialize_child(obj, "gem", &s->gem, TYPE_CADENCE_GEM);
      object_initialize_child(obj, "gpio", &s->gpio, TYPE_SIFIVE_GPIO);
      object_initialize_child(obj, "pdma", &s->dma, TYPE_SIFIVE_PDMA);
+    object_initialize_child(obj, "l2-cache-controller", &s->l2cc,
+                            TYPE_SIFIVE_L2CC);
+    qdev_prop_set_uint64(DEVICE(&s->l2cc), "zero-size",
+                         sifive_u_memmap[SIFIVE_U_DEV_L2ZERO].size);
      object_initialize_child(obj, "spi0", &s->spi0, TYPE_SIFIVE_SPI);
      object_initialize_child(obj, "spi2", &s->spi2, TYPE_SIFIVE_SPI);
      object_initialize_child(obj, "pwm0", &s->pwm[0], TYPE_SIFIVE_PWM);
@@ -728,7 +733,6 @@ static void sifive_u_soc_realize(DeviceState *dev, Error 
**errp)
      const MemMapEntry *memmap = sifive_u_memmap;
      MemoryRegion *system_memory = get_system_memory();
      MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
-    MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
      char *plic_hart_config;
      int i, j;
@@ -754,19 +758,14 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
      memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_MROM].base,
                                  mask_rom);
- /*
-     * Add L2-LIM at reset size.
-     * This should be reduced in size as the L2 Cache Controller WayEnable
-     * register is incremented. Unfortunately I don't see a nice (or any) way
-     * to handle reducing or blocking out the L2 LIM while still allowing it
-     * be re returned to all enabled after a reset. For the time being, just
-     * leave it enabled all the time. This won't break anything, but will be
-     * too generous to misbehaving guests.
-     */
-    memory_region_init_ram(l2lim_mem, NULL, "riscv.sifive.u.l2lim",
-                           memmap[SIFIVE_U_DEV_L2LIM].size, &error_fatal);
-    memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_L2LIM].base,
-                                l2lim_mem);
+    /* L2 cache controller, LIM, and Zero windows */
+    sysbus_realize(SYS_BUS_DEVICE(&s->l2cc), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->l2cc), SIFIVE_L2CC_MMIO_REGS,
+                    memmap[SIFIVE_U_DEV_L2CC].base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->l2cc), SIFIVE_L2CC_MMIO_LIM,
+                    memmap[SIFIVE_U_DEV_L2LIM].base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->l2cc), SIFIVE_L2CC_MMIO_ZERO,
+                    memmap[SIFIVE_U_DEV_L2ZERO].base);
/* create PLIC hart topology configuration string */
      plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus);
@@ -868,9 +867,6 @@ static void sifive_u_soc_realize(DeviceState *dev, Error 
**errp)
      create_unimplemented_device("riscv.sifive.u.dmc",
          memmap[SIFIVE_U_DEV_DMC].base, memmap[SIFIVE_U_DEV_DMC].size);
- create_unimplemented_device("riscv.sifive.u.l2cc",
-        memmap[SIFIVE_U_DEV_L2CC].base, memmap[SIFIVE_U_DEV_L2CC].size);
-
      sysbus_realize(SYS_BUS_DEVICE(&s->spi0), errp);
      sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi0), 0,
                      memmap[SIFIVE_U_DEV_QSPI0].base);
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 46a499f70f..b2b816de6a 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -99,6 +99,7 @@ config SIFIVE_U
      select CPU_CLUSTER
      select DEVICE_TREE
      select RISCV_ACLINT
+    select SIFIVE_L2CC
      select SIFIVE_GPIO
      select SIFIVE_PDMA
      select SIFIVE_PLIC


Reply via email to