@samitouri / QOSamiQemu / commits / abd9e918e7

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