On 10/21/2026 8:08 AM, Ralf Ramsauer wrote:
From: Ralf Ramsauer <[email protected]>

virt and sifive_u now describe a hart's PLIC contexts with the same rule:
a machine context unless the hart runs under KVM, where there is no
M-mode, and a supervisor context if the hart has supervisor mode.
Writing that rule down twice is what let the virt device tree drift away
from riscv_plic_hart_config_string().

This makes the sifive_u device tree ask whether KVM is in use, which it
did not do before.  Its PLIC device already does, so the two now agree.

Signed-off-by: Ralf Ramsauer <[email protected]>
---
Cleanup, not a fix.  Can be dropped, the rest does not depend on it.

  hw/riscv/fdt-common.c         | 20 ++++++++++++++++++++
  hw/riscv/sifive_u.c           | 10 ++--------
  hw/riscv/virt.c               | 12 +++---------
  include/hw/riscv/fdt-common.h |  3 +++
  4 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c
index ce2dcb43b4..70f96734b4 100644
--- a/hw/riscv/fdt-common.c
+++ b/hw/riscv/fdt-common.c
@@ -10,6 +10,7 @@
#include "qemu/error-report.h"
  #include "system/device_tree.h"
+#include "system/kvm.h"
  #include "hw/core/boards.h"
  #include "hw/core/sysbus-fdt.h"
  #include "hw/riscv/fdt-common.h"
@@ -212,6 +213,25 @@ riscv_create_fdt_socket_cpu_sifive(void *fdt, char 
*clust_name,
                                     phandle, intc_phandles, false, false);
  }
+uint32_t riscv_plic_hart_fdt_cells(uint32_t *cells, RISCVCPU *hart,
+                                   uint32_t intc_phandle)
+{
+    uint32_t len = 0;
+
+    /* harts running under KVM have no M-mode */
+    if (!kvm_enabled()) {

In this file we're trying to keep it as bland as possible w.r.t accelerator 
logic.
The idea is that the boards will do accelerator considerations and just point
the fdt functions what to write in the fdt.  This will make it less annoying to 
deal
with accel differences across multiple files ... ideally.

For example in virt.c we have:

    riscv_fdt_create_cpu_socket_subnode(ms->fdt,
        kvm_enabled() ? kvm_riscv_get_timebase_frequency(&s->soc->harts[0]) :
                        RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);

The above calls this fdt helper:

void riscv_fdt_create_cpu_socket_subnode(void *fdt,
                                         uint64_t timebase_frequency)

I.e. the fdt helper only cares about timebase_frequency to blindly put it in the
fdt.  It doesn't care if it's kvm or not.

So for this helper I suggest something like:

uint32_t riscv_plic_hart_fdt_cells(uint32_t *cells, RISCVCPU *hart,
                                   uint32_t intc_phandle, bool has_m_mode)

{
    uint32_t len = 0;

    if (has_m_mode) {
        ...
    }
    ...
}

And then virt.c and sifive_u.c makes accellerator considerations if needed.
E.g.:


riscv_plic_hart_fdt_cells(&cells[cells_length], hart,
                          intc_phandles[cpu], !kvm_enabled());


Thanks,
Daniel

+        cells[len++] = cpu_to_be32(intc_phandle);
+        cells[len++] = cpu_to_be32(IRQ_M_EXT);
+    }
+
+    if (riscv_cpu_has_supervisor_mode(hart)) {
+        cells[len++] = cpu_to_be32(intc_phandle);
+        cells[len++] = cpu_to_be32(IRQ_S_EXT);
+    }
+
+    return len;
+}
+
  void riscv_create_fdt_plic(void *fdt, hwaddr addr, uint64_t size,
                             uint32_t plic_phandle, uint32_t int_cells,
                             uint32_t addr_cells, uint32_t *plic_cells,
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 8f50c67a14..456b6da3e6 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -201,14 +201,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
      for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
          /* cpu 0 is the management hart that does not have S-mode */
          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);
-        }
+        cells_length += riscv_plic_hart_fdt_cells(&cells[cells_length], hart,
+                                                  intc_phandles[cpu]);
      }
riscv_create_fdt_plic(fdt, memmap[SIFIVE_U_DEV_PLIC].base,
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index a2851b506d..a325891dca 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -161,15 +161,9 @@ static void create_fdt_socket_plic(RISCVVirtState *s,
      cells_length = 0;
for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
-        if (!kvm_enabled()) {
-            plic_cells[cells_length++] = cpu_to_be32(intc_phandles[cpu]);
-            plic_cells[cells_length++] = cpu_to_be32(IRQ_M_EXT);
-        }
-
-        if (riscv_cpu_has_supervisor_mode(&s->soc[socket].harts[cpu])) {
-            plic_cells[cells_length++] = cpu_to_be32(intc_phandles[cpu]);
-            plic_cells[cells_length++] = cpu_to_be32(IRQ_S_EXT);
-        }
+        cells_length += riscv_plic_hart_fdt_cells(&plic_cells[cells_length],
+                                                  &s->soc[socket].harts[cpu],
+                                                  intc_phandles[cpu]);
      }
plic_phandles[socket] = (*phandle)++;
diff --git a/include/hw/riscv/fdt-common.h b/include/hw/riscv/fdt-common.h
index eb9db8278d..14116a95cf 100644
--- a/include/hw/riscv/fdt-common.h
+++ b/include/hw/riscv/fdt-common.h
@@ -93,6 +93,9 @@ void riscv_create_fdt_socket_cpu_sifive(void *fdt, char 
*clust_name,
                                          int socket_hartid_base,
                                          uint32_t *phandle,
                                          uint32_t *intc_phandles);
+/* Describe one hart's PLIC contexts, returns the number of cells written */
+uint32_t riscv_plic_hart_fdt_cells(uint32_t *cells, RISCVCPU *hart,
+                                   uint32_t intc_phandle);
  void riscv_create_fdt_plic(void *fdt, hwaddr addr, uint64_t size,
                             uint32_t plic_phandle, uint32_t int_cells,
                             uint32_t addr_cells, uint32_t *plic_cells,


Reply via email to