hw/riscv: add create_fdt_clint() helper
Move all clint FDT generation to fdt-common.c reducing code repetition. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260615203734.954428-8-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Daniel Henrique Barboza committed
Jun 15, 2026 at 17:37 UTC
0d37a88d474e7c2f15d4698ce99e84c836100d20
5 files changed
+54
-86
hw/riscv/fdt-common.c
+33
@@ -12,6 +12,7 @@
12
#include "system/device_tree.h"
13
#include "hw/core/boards.h"
14
#include "hw/riscv/fdt-common.h"
15
+#include "target/riscv/cpu_bits.h"
16
17
void *create_board_device_tree(const char *model, const char *compatible,
18
int *fdt_size)
@@ -50,3 +51,35 @@ void create_fdt_socket_memory(void *fdt, hwaddr addr, uint64_t size,
51
qemu_fdt_setprop_cell(fdt, mem_name, "numa-node-id", socket_id);
52
}
53
}
54
+
55
+void create_fdt_socket_clint(void *fdt, hwaddr addr, uint64_t size,
56
+ int socket_id, uint32_t *intc_phandles,
57
+ int num_harts, bool numa_enabled)
58
+{
59
+ g_autofree uint32_t *clint_cells = g_new0(uint32_t, num_harts * 4);
60
+ g_autofree char *clint_name = NULL;
61
+ static const char * const clint_compat[2] = {
62
+ "sifive,clint0", "riscv,clint0"
63
+ };
64
+
65
+ for (int cpu = 0; cpu < num_harts; cpu++) {
66
+ clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
67
+ clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
68
+ clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
69
+ clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
70
+ }
71
+
72
+ clint_name = g_strdup_printf("/soc/clint@%"HWADDR_PRIx, addr);
73
+ qemu_fdt_add_subnode(fdt, clint_name);
74
+ qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
75
+ (char **)&clint_compat,
76
+ ARRAY_SIZE(clint_compat));
77
+ qemu_fdt_setprop_sized_cells(fdt, clint_name, "reg",
78
+ 2, addr, 2, size);
79
+ qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
80
+ clint_cells, num_harts * sizeof(uint32_t) * 4);
81
+
82
+ if (numa_enabled) {
83
+ qemu_fdt_setprop_cell(fdt, clint_name, "numa-node-id", socket_id);
84
+ }
85
+}
hw/riscv/sifive_u.c
+3
-22
@@ -105,9 +105,6 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
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 clint_compat[2] = {
109
- "sifive,clint0", "riscv,clint0"
110
- };
108
static const char * const plic_compat[2] = {
109
"sifive,plic-1.0.0", "riscv,plic0"
110
};
@@ -180,25 +177,9 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
177
g_free(nodename);
178
}
179
183
- cells = g_new0(uint32_t, ms->smp.cpus * 4);
184
- for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
185
- cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
186
- cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
187
- cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
188
- cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
189
- }
190
- nodename = g_strdup_printf("/soc/clint@%lx",
191
- (long)memmap[SIFIVE_U_DEV_CLINT].base);
192
- qemu_fdt_add_subnode(fdt, nodename);
193
- qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
194
- (char **)&clint_compat, ARRAY_SIZE(clint_compat));
195
- qemu_fdt_setprop_cells(fdt, nodename, "reg",
196
- 0x0, memmap[SIFIVE_U_DEV_CLINT].base,
197
- 0x0, memmap[SIFIVE_U_DEV_CLINT].size);
198
- qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
199
- cells, ms->smp.cpus * sizeof(uint32_t) * 4);
200
- g_free(cells);
201
- g_free(nodename);
180
+ create_fdt_socket_clint(fdt, memmap[SIFIVE_U_DEV_CLINT].base,
181
+ memmap[SIFIVE_U_DEV_CLINT].size, 0,
182
+ intc_phandles, ms->smp.cpus, false);
183
184
nodename = g_strdup_printf("/soc/otp@%lx",
185
(long)memmap[SIFIVE_U_DEV_OTP].base);
hw/riscv/spike.c
+5
-26
@@ -58,13 +58,10 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
58
unsigned long clint_addr;
59
int cpu, socket;
60
MachineState *ms = MACHINE(s);
61
- uint32_t *clint_cells;
61
uint32_t cpu_phandle, phandle = 1;
63
- char *clint_name, *clust_name;
62
+ char *clust_name;
63
char *core_name, *cpu_name, *intc_name;
65
- static const char * const clint_compat[2] = {
66
- "sifive,clint0", "riscv,clint0"
67
- };
64
+ bool numa_enabled = riscv_numa_enabled(ms);
65
66
fdt = ms->fdt = create_board_device_tree("ucbbar,spike-bare,qemu",
67
"ucbbar,spike-bare-dev", &fdt_size);
@@ -136,29 +133,11 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
133
create_fdt_socket_memory(fdt, memaddr, memsize, socket,
134
riscv_numa_enabled(ms));
135
139
- clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
140
-
141
- for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
142
- clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
143
- clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
144
- clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
145
- clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
146
- }
147
-
136
clint_addr = memmap[SPIKE_CLINT].base +
137
(memmap[SPIKE_CLINT].size * socket);
150
- clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
151
- qemu_fdt_add_subnode(fdt, clint_name);
152
- qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
153
- (char **)&clint_compat, ARRAY_SIZE(clint_compat));
154
- qemu_fdt_setprop_cells(fdt, clint_name, "reg",
155
- 0x0, clint_addr, 0x0, memmap[SPIKE_CLINT].size);
156
- qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
157
- clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
158
- riscv_socket_fdt_write_id(ms, clint_name, socket);
159
-
160
- g_free(clint_name);
161
- g_free(clint_cells);
138
+ create_fdt_socket_clint(fdt, clint_addr, memmap[SPIKE_CLINT].size,
139
+ socket, intc_phandles,
140
+ s->soc[socket].num_harts, numa_enabled);
141
g_free(clust_name);
142
}
143
hw/riscv/virt.c
+8
-38
@@ -302,42 +302,6 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
302
}
303
}
304
305
-static void create_fdt_socket_clint(RISCVVirtState *s,
306
- int socket,
307
- uint32_t *intc_phandles)
308
-{
309
- int cpu;
310
- g_autofree char *clint_name = NULL;
311
- g_autofree uint32_t *clint_cells = NULL;
312
- hwaddr clint_addr;
313
- MachineState *ms = MACHINE(s);
314
- static const char * const clint_compat[2] = {
315
- "sifive,clint0", "riscv,clint0"
316
- };
317
-
318
- clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
319
-
320
- for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
321
- clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
322
- clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
323
- clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
324
- clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
325
- }
326
-
327
- clint_addr = s->memmap[VIRT_CLINT].base +
328
- s->memmap[VIRT_CLINT].size * socket;
329
- clint_name = g_strdup_printf("/soc/clint@%"HWADDR_PRIx, clint_addr);
330
- qemu_fdt_add_subnode(ms->fdt, clint_name);
331
- qemu_fdt_setprop_string_array(ms->fdt, clint_name, "compatible",
332
- (char **)&clint_compat,
333
- ARRAY_SIZE(clint_compat));
334
- qemu_fdt_setprop_sized_cells(ms->fdt, clint_name, "reg",
335
- 2, clint_addr, 2, s->memmap[VIRT_CLINT].size);
336
- qemu_fdt_setprop(ms->fdt, clint_name, "interrupts-extended",
337
- clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
338
- riscv_socket_fdt_write_id(ms, clint_name, socket);
339
-}
340
-
305
static void create_fdt_socket_aclint(RISCVVirtState *s,
306
int socket,
307
uint32_t *intc_phandles)
@@ -728,6 +692,7 @@ static void create_fdt_sockets(RISCVVirtState *s,
692
uint32_t xplic_phandles[MAX_NODES];
693
g_autofree uint32_t *intc_phandles = NULL;
694
int socket_count = riscv_socket_count(ms);
695
+ bool numa_enabled = riscv_numa_enabled(ms);
696
697
qemu_fdt_add_subnode(ms->fdt, "/cpus");
698
qemu_fdt_setprop_cell(ms->fdt, "/cpus", "timebase-frequency",
@@ -762,8 +727,13 @@ static void create_fdt_sockets(RISCVVirtState *s,
727
create_fdt_socket_aclint(s, socket,
728
&intc_phandles[phandle_pos]);
729
} else if (tcg_enabled()) {
765
- create_fdt_socket_clint(s, socket,
766
- &intc_phandles[phandle_pos]);
730
+ hwaddr clintaddr = s->memmap[VIRT_CLINT].base +
731
+ s->memmap[VIRT_CLINT].size * socket;
732
+
733
+ create_fdt_socket_clint(ms->fdt, clintaddr,
734
+ s->memmap[VIRT_CLINT].size,
735
+ socket, &intc_phandles[phandle_pos],
736
+ s->soc[socket].num_harts, numa_enabled);
737
}
738
}
739
include/hw/riscv/fdt-common.h
+5
@@ -13,4 +13,9 @@ void *create_board_device_tree(const char *model, const char *compatible,
13
int *fdt_size);
14
void create_fdt_socket_memory(void *fdt, hwaddr addr, uint64_t size,
15
int socket_id, bool numa_enabled);
16
+void create_fdt_clint(void *fdt, hwaddr addr, uint64_t size,
17
+ uint32_t *intc_phandles, int num_harts);
18
+void create_fdt_socket_clint(void *fdt, hwaddr addr, uint64_t size,
19
+ int socket_id, uint32_t *intc_phandles,
20
+ int num_harts, bool numa_enabled);
21
#endif