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);
          }
      }


Reply via email to