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>
Daniel Henrique Barboza committed
Jun 16, 2026 at 20:59 UTC
b3b4a424e2b29b6b88b2ed9a47a2c908ae1ec182
4 files changed
+61
-57
hw/riscv/fdt-common.c
+30
@@ -200,3 +200,33 @@ create_fdt_socket_cpu_sifive(void *fdt, char *clust_name,
200
socket_id, socket_hartid_base,
201
phandle, intc_phandles, false, false);
202
}
203
+
204
+void create_fdt_plic(void *fdt, hwaddr addr, uint64_t size,
205
+ uint32_t plic_phandle, uint32_t int_cells,
206
+ uint32_t addr_cells, uint32_t *plic_cells,
207
+ uint32_t cells_size, uint32_t ndev_sources,
208
+ bool numa_enabled, int socket_id)
209
+{
210
+ g_autofree char *nodename = NULL;
211
+ static const char * const plic_compat[2] = {
212
+ "sifive,plic-1.0.0", "riscv,plic0"
213
+ };
214
+
215
+ nodename = g_strdup_printf("/soc/interrupt-controller@%"HWADDR_PRIx, addr);
216
+
217
+ qemu_fdt_add_subnode(fdt, nodename);
218
+ qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", int_cells);
219
+ qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", addr_cells);
220
+ qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
221
+ (char **)&plic_compat, ARRAY_SIZE(plic_compat));
222
+ qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
223
+ qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
224
+ plic_cells, cells_size);
225
+ qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
226
+ 2, addr, 2, size);
227
+ qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", ndev_sources);
228
+ if (numa_enabled) {
229
+ qemu_fdt_setprop_cell(fdt, nodename, "numa-node-id", socket_id);
230
+ }
231
+ qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle);
232
+}
hw/riscv/sifive_u.c
+10
-24
@@ -100,14 +100,11 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
100
MachineState *ms = MACHINE(s);
101
void *fdt;
102
int cpu;
103
- uint32_t *cells;
103
+ uint32_t *cells, cells_length;
104
char *nodename;
105
uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
106
uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
107
static const char * const ethclk_names[2] = { "pclk", "hclk" };
108
- static const char * const plic_compat[2] = {
109
- "sifive,plic-1.0.0", "riscv,plic0"
110
- };
108
g_autofree uint32_t *intc_phandles = g_new0(uint32_t, ms->smp.cpus);
109
g_autofree char *clust_name = NULL;
110
@@ -197,7 +194,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
194
g_free(nodename);
195
196
plic_phandle = phandle++;
200
- cells = g_new0(uint32_t, ms->smp.cpus * 4 - 2);
197
+ cells_length = ms->smp.cpus * 4 - 2;
198
+ cells = g_new0(uint32_t, cells_length);
199
for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
200
/* cpu 0 is the management hart that does not have S-mode */
201
if (cpu == 0) {
@@ -210,26 +208,14 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
208
cells[cpu * 4 + 1] = cpu_to_be32(IRQ_S_EXT);
209
}
210
}
213
- nodename = g_strdup_printf("/soc/interrupt-controller@%lx",
214
- (long)memmap[SIFIVE_U_DEV_PLIC].base);
215
- qemu_fdt_add_subnode(fdt, nodename);
216
- qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells",
217
- SIFIVE_U_PLIC_INT_CELLS);
218
- qemu_fdt_setprop_cell(fdt, nodename, "#address-cells",
219
- SIFIVE_U_PLIC_ADDR_CELLS);
220
- qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
221
- (char **)&plic_compat, ARRAY_SIZE(plic_compat));
222
- qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
223
- qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
224
- cells, (ms->smp.cpus * 4 - 2) * sizeof(uint32_t));
225
- qemu_fdt_setprop_cells(fdt, nodename, "reg",
226
- 0x0, memmap[SIFIVE_U_DEV_PLIC].base,
227
- 0x0, memmap[SIFIVE_U_DEV_PLIC].size);
228
- qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev",
229
- SIFIVE_U_PLIC_NUM_SOURCES - 1);
230
- qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle);
211
+
212
+ create_fdt_plic(fdt, memmap[SIFIVE_U_DEV_PLIC].base,
213
+ memmap[SIFIVE_U_DEV_PLIC].size,
214
+ plic_phandle, SIFIVE_U_PLIC_INT_CELLS,
215
+ SIFIVE_U_PLIC_ADDR_CELLS, cells,
216
+ cells_length * sizeof(uint32_t),
217
+ SIFIVE_U_PLIC_NUM_SOURCES - 1, false, 0);
218
g_free(cells);
232
- g_free(nodename);
219
220
gpio_phandle = phandle++;
221
nodename = g_strdup_printf("/soc/gpio@%lx",
hw/riscv/virt.c
+16
-33
@@ -326,39 +326,25 @@ static void create_fdt_socket_plic(RISCVVirtState *s,
326
int cpu;
327
g_autofree char *plic_name = NULL;
328
g_autofree uint32_t *plic_cells;
329
- unsigned long plic_addr;
329
MachineState *ms = MACHINE(s);
331
- static const char * const plic_compat[2] = {
332
- "sifive,plic-1.0.0", "riscv,plic0"
333
- };
330
+ unsigned long plic_addr = s->memmap[VIRT_PLIC].base +
331
+ (s->memmap[VIRT_PLIC].size * socket);
332
+ bool numa_enabled = riscv_numa_enabled(MACHINE(s));
333
+ uint32_t cells_length;
334
335
- plic_phandles[socket] = (*phandle)++;
336
- plic_addr = s->memmap[VIRT_PLIC].base +
337
- (s->memmap[VIRT_PLIC].size * socket);
335
plic_name = g_strdup_printf("/soc/interrupt-controller@%lx", plic_addr);
339
- qemu_fdt_add_subnode(ms->fdt, plic_name);
340
- qemu_fdt_setprop_cell(ms->fdt, plic_name,
341
- "#interrupt-cells", FDT_PLIC_INT_CELLS);
342
- qemu_fdt_setprop_cell(ms->fdt, plic_name,
343
- "#address-cells", FDT_PLIC_ADDR_CELLS);
344
- qemu_fdt_setprop_string_array(ms->fdt, plic_name, "compatible",
345
- (char **)&plic_compat,
346
- ARRAY_SIZE(plic_compat));
347
- qemu_fdt_setprop(ms->fdt, plic_name, "interrupt-controller", NULL, 0);
336
337
if (kvm_enabled()) {
350
- plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
338
+ cells_length = s->soc[socket].num_harts * 2;
339
+ plic_cells = g_new0(uint32_t, cells_length);
340
341
for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
342
plic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
343
plic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT);
344
}
356
-
357
- qemu_fdt_setprop(ms->fdt, plic_name, "interrupts-extended",
358
- plic_cells,
359
- s->soc[socket].num_harts * sizeof(uint32_t) * 2);
345
} else {
361
- plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
346
+ cells_length = s->soc[socket].num_harts * 4;
347
+ plic_cells = g_new0(uint32_t, cells_length);
348
349
for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
350
plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
@@ -366,19 +352,16 @@ static void create_fdt_socket_plic(RISCVVirtState *s,
352
plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
353
plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT);
354
}
369
-
370
- qemu_fdt_setprop(ms->fdt, plic_name, "interrupts-extended",
371
- plic_cells,
372
- s->soc[socket].num_harts * sizeof(uint32_t) * 4);
355
}
356
375
- qemu_fdt_setprop_sized_cells(ms->fdt, plic_name, "reg",
376
- 2, plic_addr, 2, s->memmap[VIRT_PLIC].size);
377
- qemu_fdt_setprop_cell(ms->fdt, plic_name, "riscv,ndev",
378
- VIRT_IRQCHIP_NUM_SOURCES - 1);
379
- riscv_socket_fdt_write_id(ms, plic_name, socket);
380
- qemu_fdt_setprop_cell(ms->fdt, plic_name, "phandle",
381
- plic_phandles[socket]);
357
+ plic_phandles[socket] = (*phandle)++;
358
+
359
+ create_fdt_plic(ms->fdt, plic_addr, s->memmap[VIRT_PLIC].size,
360
+ plic_phandles[socket], FDT_PLIC_INT_CELLS,
361
+ FDT_PLIC_ADDR_CELLS, plic_cells,
362
+ cells_length * sizeof(uint32_t),
363
+ VIRT_IRQCHIP_NUM_SOURCES - 1,
364
+ numa_enabled, socket);
365
366
if (!socket) {
367
platform_bus_add_all_fdt_nodes(ms->fdt, plic_name,
include/hw/riscv/fdt-common.h
+5
@@ -30,4 +30,9 @@ void create_fdt_socket_cpu_sifive(void *fdt, char *clust_name,
30
int cpu_id, int socket_id,
31
int socket_hartid_base, uint32_t *phandle,
32
uint32_t *intc_phandles);
33
+void create_fdt_plic(void *fdt, hwaddr addr, uint64_t size,
34
+ uint32_t plic_phandle, uint32_t int_cells,
35
+ uint32_t addr_cells, uint32_t *plic_cells,
36
+ uint32_t cells_size, uint32_t ndev_sources,
37
+ bool numa_enabled, int socket);
38
#endif