On 10/21/2026 8:08 AM, Ralf Ramsauer wrote:
From: Ralf Ramsauer <[email protected]> The PLIC device is created from riscv_plic_hart_config_string(), which gives a hart a supervisor context only if that hart has supervisor mode. The device tree instead hardcodes the fu540 topology: no supervisor context for the management hart, one for every other hart. Both agree as long as the application harts keep the default CPU type. The board sets no valid_cpu_types, though, and passes machine->cpu_type on to the U cluster, so -cpu rv64,s=false,u=false builds a PLIC without any supervisor context while the device tree still advertises one per application hart. Contexts are numbered by their position in 'interrupts-extended', so from the second hart on the numbering drifts apart, as it does on the virt machine. Ask the harts instead of assuming, like create_fdt_socket_plic() does. No change for the default CPU type: the E51 management hart has no RVS, the U54 application harts have. Signed-off-by: Ralf Ramsauer <[email protected]> ---
Reviewed-by: Daniel Henrique Barboza <[email protected]>
hw/riscv/sifive_u.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index b7d5e7b4da..8f50c67a14 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -99,6 +99,7 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, MachineState *ms = MACHINE(s); void *fdt; int cpu; + RISCVCPU *hart; uint32_t *cells, cells_length; char *nodename; uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1; @@ -195,18 +196,18 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, g_free(nodename);plic_phandle = phandle++;- cells_length = ms->smp.cpus * 4 - 2; - cells = g_new0(uint32_t, cells_length); + cells = g_new0(uint32_t, ms->smp.cpus * 4 - 2); + cells_length = 0; for (cpu = 0; cpu < ms->smp.cpus; cpu++) { /* cpu 0 is the management hart that does not have S-mode */ - if (cpu == 0) { - cells[0] = cpu_to_be32(intc_phandles[cpu]); - cells[1] = cpu_to_be32(IRQ_M_EXT); - } else { - cells[cpu * 4 - 2] = cpu_to_be32(intc_phandles[cpu]); - cells[cpu * 4 - 1] = cpu_to_be32(IRQ_M_EXT); - cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]); - cells[cpu * 4 + 1] = cpu_to_be32(IRQ_S_EXT); + hart = cpu ? &s->soc.u_cpus.harts[cpu - 1] : &s->soc.e_cpus.harts[0]; + + cells[cells_length++] = cpu_to_be32(intc_phandles[cpu]); + cells[cells_length++] = cpu_to_be32(IRQ_M_EXT); + + if (riscv_cpu_has_supervisor_mode(hart)) { + cells[cells_length++] = cpu_to_be32(intc_phandles[cpu]); + cells[cells_length++] = cpu_to_be32(IRQ_S_EXT); } }
