hw/hexagon/virt: add l2vic interrupt-controller and virtio-mmio FDT nodes
Expose l2vic as a device-tree interrupt-controller node and reference it via interrupt-parent, so guest kernels can discover the virtio-mmio transports. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com> Link: https://lore.kernel.org/qemu-devel/20260806042723.3785369-12-brian.cain@oss.qualcomm.com Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
Brian Cain committed
Aug 5, 2026 at 21:27 UTC
abd9e918e79bc3ed860745890c35355b4ed85cc6
1 file changed
+41
-2
hw/hexagon/virt.c
+41
-2
@@ -75,6 +75,30 @@ static void create_fdt(HexagonVirtMachineState *vms)
75
qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
76
}
77
78
+static int32_t fdt_add_l2vic(HexagonVirtMachineState *vms,
79
+ const struct hexagon_machine_config *m_cfg)
80
+{
81
+ MachineState *ms = MACHINE(vms);
82
+ int32_t l2vic_phandle = qemu_fdt_alloc_phandle(ms->fdt);
83
+ char *nodename = g_strdup_printf("/soc/interrupt-controller@%x",
84
+ m_cfg->l2vic_base);
85
+ const char compat[] = "qcom,h2-pic\0hvm-pic";
86
+
87
+ qemu_fdt_setprop_cell(ms->fdt, "/soc", "interrupt-parent", l2vic_phandle);
88
+
89
+ qemu_fdt_add_subnode(ms->fdt, nodename);
90
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x0);
91
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 0x1);
92
+ qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat));
93
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0,
94
+ m_cfg->l2vic_base, m_cfg->l2vic_size);
95
+ qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
96
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", l2vic_phandle);
97
+
98
+ g_free(nodename);
99
+ return l2vic_phandle;
100
+}
101
+
102
static void fdt_add_hvx(HexagonVirtMachineState *vms,
103
const struct hexagon_machine_config *m_cfg)
104
{
@@ -175,13 +199,16 @@ static void fdt_add_cpu_nodes(const HexagonVirtMachineState *vms)
199
}
200
}
201
178
-static void create_virtio_devices(HexagonVirtMachineState *vms)
202
+static void create_virtio_devices(HexagonVirtMachineState *vms,
203
+ int32_t l2vic_phandle)
204
{
205
+ MachineState *ms = MACHINE(vms);
206
hwaddr size = base_memmap[VIRT_MMIO].size;
207
208
for (int i = 0; i < VIRTIO_DEV_COUNT; i++) {
209
int irq = VIRTIO_IRQ_BASE + i;
210
hwaddr base = base_memmap[VIRT_MMIO].base + i * size;
211
+ char *nodename = g_strdup_printf("/soc/virtio_mmio@%" PRIx64, base);
212
DeviceState *dev = qdev_new("virtio-mmio");
213
SysBusDevice *s = SYS_BUS_DEVICE(dev);
214
@@ -192,6 +219,16 @@ static void create_virtio_devices(HexagonVirtMachineState *vms)
219
sysbus_connect_irq(s, 0,
220
qdev_get_gpio_in(vms->parent_obj.l2vic, irq));
221
vms->virtio_mmio[i] = dev;
222
+
223
+ qemu_fdt_add_subnode(ms->fdt, nodename);
224
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
225
+ "virtio,mmio");
226
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, size);
227
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupts", irq);
228
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
229
+ l2vic_phandle);
230
+
231
+ g_free(nodename);
232
}
233
}
234
@@ -251,6 +288,7 @@ static void virt_init(MachineState *ms)
288
HexagonVirtMachineState *vms = HEXAGON_VIRT_MACHINE(ms);
289
const struct hexagon_machine_config *m_cfg = &v68n_1024;
290
int32_t clk_phandle;
291
+ int32_t l2vic_phandle;
292
293
create_fdt(vms);
294
qemu_fdt_setprop_string(ms->fdt, "/chosen", "bootargs", ms->kernel_cmdline);
@@ -272,7 +310,8 @@ static void virt_init(MachineState *ms)
310
311
fdt_add_hvx(vms, m_cfg);
312
275
- create_virtio_devices(vms);
313
+ l2vic_phandle = fdt_add_l2vic(vms, m_cfg);
314
+ create_virtio_devices(vms, l2vic_phandle);
315
316
g_autofree HexagonCPU **cpus = g_new(HexagonCPU *, ms->smp.cpus);
317