Commit b3b4a424e2 for qemu.org
commit b3b4a424e2b29b6b88b2ed9a47a2c908ae1ec182
Author: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Date: Tue Jun 16 20:59:39 2026 -0300
hw/riscv: add create_fdt_plic() helper
Consolidate the common plic FDT code between 'virt' and sifive_u boards
into a single place.
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260616235939.1358663-6-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c
index b27ff13bca..e0e31af09b 100644
--- a/hw/riscv/fdt-common.c
+++ b/hw/riscv/fdt-common.c
@@ -200,3 +200,33 @@ create_fdt_socket_cpu_sifive(void *fdt, char *clust_name,
socket_id, socket_hartid_base,
phandle, intc_phandles, false, false);
}
+
+void 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,
+ uint32_t cells_size, uint32_t ndev_sources,
+ bool numa_enabled, int socket_id)
+{
+ g_autofree char *nodename = NULL;
+ static const char * const plic_compat[2] = {
+ "sifive,plic-1.0.0", "riscv,plic0"
+ };
+
+ nodename = g_strdup_printf("/soc/interrupt-controller@%"HWADDR_PRIx, addr);
+
+ qemu_fdt_add_subnode(fdt, nodename);
+ qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", int_cells);
+ qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", addr_cells);
+ qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
+ (char **)&plic_compat, ARRAY_SIZE(plic_compat));
+ qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
+ qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
+ plic_cells, cells_size);
+ qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
+ 2, addr, 2, size);
+ qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", ndev_sources);
+ if (numa_enabled) {
+ qemu_fdt_setprop_cell(fdt, nodename, "numa-node-id", socket_id);
+ }
+ qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle);
+}
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 7dfc18d3ec..d923f041e0 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -100,14 +100,11 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
MachineState *ms = MACHINE(s);
void *fdt;
int cpu;
- uint32_t *cells;
+ uint32_t *cells, cells_length;
char *nodename;
uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
static const char * const ethclk_names[2] = { "pclk", "hclk" };
- static const char * const plic_compat[2] = {
- "sifive,plic-1.0.0", "riscv,plic0"
- };
g_autofree uint32_t *intc_phandles = g_new0(uint32_t, ms->smp.cpus);
g_autofree char *clust_name = NULL;
@@ -197,7 +194,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
g_free(nodename);
plic_phandle = phandle++;
- cells = g_new0(uint32_t, ms->smp.cpus * 4 - 2);
+ cells_length = ms->smp.cpus * 4 - 2;
+ cells = g_new0(uint32_t, cells_length);
for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
/* cpu 0 is the management hart that does not have S-mode */
if (cpu == 0) {
@@ -210,26 +208,14 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
cells[cpu * 4 + 1] = cpu_to_be32(IRQ_S_EXT);
}
}
- nodename = g_strdup_printf("/soc/interrupt-controller@%lx",
- (long)memmap[SIFIVE_U_DEV_PLIC].base);
- qemu_fdt_add_subnode(fdt, nodename);
- qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells",
- SIFIVE_U_PLIC_INT_CELLS);
- qemu_fdt_setprop_cell(fdt, nodename, "#address-cells",
- SIFIVE_U_PLIC_ADDR_CELLS);
- qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
- (char **)&plic_compat, ARRAY_SIZE(plic_compat));
- qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
- qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
- cells, (ms->smp.cpus * 4 - 2) * sizeof(uint32_t));
- qemu_fdt_setprop_cells(fdt, nodename, "reg",
- 0x0, memmap[SIFIVE_U_DEV_PLIC].base,
- 0x0, memmap[SIFIVE_U_DEV_PLIC].size);
- qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev",
- SIFIVE_U_PLIC_NUM_SOURCES - 1);
- qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle);
+
+ create_fdt_plic(fdt, memmap[SIFIVE_U_DEV_PLIC].base,
+ memmap[SIFIVE_U_DEV_PLIC].size,
+ plic_phandle, SIFIVE_U_PLIC_INT_CELLS,
+ SIFIVE_U_PLIC_ADDR_CELLS, cells,
+ cells_length * sizeof(uint32_t),
+ SIFIVE_U_PLIC_NUM_SOURCES - 1, false, 0);
g_free(cells);
- g_free(nodename);
gpio_phandle = phandle++;
nodename = g_strdup_printf("/soc/gpio@%lx",
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index fa464e644f..92c30a6f4c 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -326,39 +326,25 @@ static void create_fdt_socket_plic(RISCVVirtState *s,
int cpu;
g_autofree char *plic_name = NULL;
g_autofree uint32_t *plic_cells;
- unsigned long plic_addr;
MachineState *ms = MACHINE(s);
- static const char * const plic_compat[2] = {
- "sifive,plic-1.0.0", "riscv,plic0"
- };
+ unsigned long plic_addr = s->memmap[VIRT_PLIC].base +
+ (s->memmap[VIRT_PLIC].size * socket);
+ bool numa_enabled = riscv_numa_enabled(MACHINE(s));
+ uint32_t cells_length;
- plic_phandles[socket] = (*phandle)++;
- plic_addr = s->memmap[VIRT_PLIC].base +
- (s->memmap[VIRT_PLIC].size * socket);
plic_name = g_strdup_printf("/soc/interrupt-controller@%lx", plic_addr);
- qemu_fdt_add_subnode(ms->fdt, plic_name);
- qemu_fdt_setprop_cell(ms->fdt, plic_name,
- "#interrupt-cells", FDT_PLIC_INT_CELLS);
- qemu_fdt_setprop_cell(ms->fdt, plic_name,
- "#address-cells", FDT_PLIC_ADDR_CELLS);
- qemu_fdt_setprop_string_array(ms->fdt, plic_name, "compatible",
- (char **)&plic_compat,
- ARRAY_SIZE(plic_compat));
- qemu_fdt_setprop(ms->fdt, plic_name, "interrupt-controller", NULL, 0);
if (kvm_enabled()) {
- plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
+ cells_length = s->soc[socket].num_harts * 2;
+ plic_cells = g_new0(uint32_t, cells_length);
for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
plic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
plic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT);
}
-
- qemu_fdt_setprop(ms->fdt, plic_name, "interrupts-extended",
- plic_cells,
- s->soc[socket].num_harts * sizeof(uint32_t) * 2);
} else {
- plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
+ cells_length = s->soc[socket].num_harts * 4;
+ plic_cells = g_new0(uint32_t, cells_length);
for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
@@ -366,19 +352,16 @@ static void create_fdt_socket_plic(RISCVVirtState *s,
plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT);
}
-
- qemu_fdt_setprop(ms->fdt, plic_name, "interrupts-extended",
- plic_cells,
- s->soc[socket].num_harts * sizeof(uint32_t) * 4);
}
- qemu_fdt_setprop_sized_cells(ms->fdt, plic_name, "reg",
- 2, plic_addr, 2, s->memmap[VIRT_PLIC].size);
- qemu_fdt_setprop_cell(ms->fdt, plic_name, "riscv,ndev",
- VIRT_IRQCHIP_NUM_SOURCES - 1);
- riscv_socket_fdt_write_id(ms, plic_name, socket);
- qemu_fdt_setprop_cell(ms->fdt, plic_name, "phandle",
- plic_phandles[socket]);
+ plic_phandles[socket] = (*phandle)++;
+
+ create_fdt_plic(ms->fdt, plic_addr, s->memmap[VIRT_PLIC].size,
+ plic_phandles[socket], FDT_PLIC_INT_CELLS,
+ FDT_PLIC_ADDR_CELLS, plic_cells,
+ cells_length * sizeof(uint32_t),
+ VIRT_IRQCHIP_NUM_SOURCES - 1,
+ numa_enabled, socket);
if (!socket) {
platform_bus_add_all_fdt_nodes(ms->fdt, plic_name,
diff --git a/include/hw/riscv/fdt-common.h b/include/hw/riscv/fdt-common.h
index 2d6b9a5d03..017278b611 100644
--- a/include/hw/riscv/fdt-common.h
+++ b/include/hw/riscv/fdt-common.h
@@ -30,4 +30,9 @@ void create_fdt_socket_cpu_sifive(void *fdt, char *clust_name,
int cpu_id, int socket_id,
int socket_hartid_base, uint32_t *phandle,
uint32_t *intc_phandles);
+void 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,
+ uint32_t cells_size, uint32_t ndev_sources,
+ bool numa_enabled, int socket);
#endif