@samitouri / QOSamiQemu / commits / b3b4a424e2

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