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]> --- 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 -- 2.53.0
