On Thu, Aug 27, 2026 at 07:25:57PM +0800, Daniel Henrique Barboza wrote:
> Both the 'virt' board and the future 'riscv-server-ref' boards uses an
> iommu-sys device that is declared in the DT. Create a helper to
> encapsulate the logic and avoid copy/pasting stuff between boards.
>
> The helper will return the iommu phandle value instead of returning void
> and writing the used phandle in an extra argument.
>
> Signed-off-by: Daniel Henrique Barboza <[email protected]>
> Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Reviewed-by: Chao Liu <[email protected]>
Thanks,
Chao
> ---
> hw/riscv/fdt-common.c | 35 ++++++++++++++++++++++++
> hw/riscv/virt.c | 50 ++++++-----------------------------
> include/hw/riscv/fdt-common.h | 5 ++++
> 3 files changed, 48 insertions(+), 42 deletions(-)
>
> diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c
> index eac5ca9322..88589330fb 100644
> --- a/hw/riscv/fdt-common.c
> +++ b/hw/riscv/fdt-common.c
> @@ -13,6 +13,8 @@
> #include "hw/core/boards.h"
> #include "hw/riscv/fdt-common.h"
> #include "target/riscv/cpu_bits.h"
> +#include "hw/riscv/riscv-iommu-bits.h"
> +#include "hw/riscv/iommu.h"
>
> void *riscv_create_board_device_tree(const char *model, const char
> *compatible,
> int *fdt_size)
> @@ -349,3 +351,36 @@ void riscv_create_fdt_syscon(void *fdt, uint32_t
> *next_phandle,
> qemu_fdt_setprop_cell(fdt, name, "value", poweroff);
> g_free(name);
> }
> +
> +uint32_t riscv_create_fdt_riscv_iommu_sys(void *fdt, hwaddr addr, hwaddr
> size,
> + uint32_t *next_phandle,
> + uint32_t irq_chip,
> + uint32_t msi_phandle,
> + uint32_t iommu_sys_irq)
> +{
> + const char comp[] = "riscv,iommu";
> + g_autofree char *iommu_node = NULL;
> + uint32_t iommu_phandle;
> +
> + iommu_node = g_strdup_printf("/soc/iommu@%"HWADDR_PRIx, addr);
> + qemu_fdt_add_subnode(fdt, iommu_node);
> +
> + qemu_fdt_setprop(fdt, iommu_node, "compatible", comp, sizeof(comp));
> + qemu_fdt_setprop_cell(fdt, iommu_node, "#iommu-cells", 1);
> +
> + iommu_phandle = next_phandle ? (*next_phandle)++ :
> qemu_fdt_alloc_phandle(fdt);
> + qemu_fdt_setprop_cell(fdt, iommu_node, "phandle", iommu_phandle);
> +
> + qemu_fdt_setprop_sized_cells(fdt, iommu_node, "reg", 2, addr, 2, size);
> + qemu_fdt_setprop_cell(fdt, iommu_node, "interrupt-parent", irq_chip);
> +
> + qemu_fdt_setprop_cells(fdt, iommu_node, "interrupts",
> + iommu_sys_irq + RISCV_IOMMU_INTR_CQ, FDT_IRQ_TYPE_EDGE_LOW,
> + iommu_sys_irq + RISCV_IOMMU_INTR_FQ, FDT_IRQ_TYPE_EDGE_LOW,
> + iommu_sys_irq + RISCV_IOMMU_INTR_PM, FDT_IRQ_TYPE_EDGE_LOW,
> + iommu_sys_irq + RISCV_IOMMU_INTR_PQ, FDT_IRQ_TYPE_EDGE_LOW);
> +
> + qemu_fdt_setprop_cell(fdt, iommu_node, "msi-parent", msi_phandle);
> +
> + return iommu_phandle;
> +}
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index ab6c53c78a..8a165f4d9e 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -869,46 +869,6 @@ static void create_fdt_virtio_iommu(RISCVVirtState *s,
> uint16_t bdf)
> bdf + 1, iommu_phandle, bdf + 1, 0xffff - bdf);
> }
>
> -static void create_fdt_iommu_sys(RISCVVirtState *s, uint32_t irq_chip,
> - uint32_t msi_phandle,
> - uint32_t *iommu_sys_phandle)
> -{
> - const char comp[] = "riscv,iommu";
> - void *fdt = MACHINE(s)->fdt;
> - uint32_t iommu_phandle;
> - g_autofree char *iommu_node = NULL;
> - hwaddr addr = s->memmap[VIRT_IOMMU_SYS].base;
> - hwaddr size = s->memmap[VIRT_IOMMU_SYS].size;
> - uint32_t iommu_irq_map[RISCV_IOMMU_INTR_COUNT] = {
> - IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_CQ,
> - IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_FQ,
> - IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_PM,
> - IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_PQ,
> - };
> -
> - iommu_node = g_strdup_printf("/soc/iommu@%x",
> - (unsigned int)
> s->memmap[VIRT_IOMMU_SYS].base);
> - iommu_phandle = qemu_fdt_alloc_phandle(fdt);
> - qemu_fdt_add_subnode(fdt, iommu_node);
> -
> - qemu_fdt_setprop(fdt, iommu_node, "compatible", comp, sizeof(comp));
> - qemu_fdt_setprop_cell(fdt, iommu_node, "#iommu-cells", 1);
> - qemu_fdt_setprop_cell(fdt, iommu_node, "phandle", iommu_phandle);
> -
> - qemu_fdt_setprop_sized_cells(fdt, iommu_node, "reg", 2, addr, 2, size);
> - qemu_fdt_setprop_cell(fdt, iommu_node, "interrupt-parent", irq_chip);
> -
> - qemu_fdt_setprop_cells(fdt, iommu_node, "interrupts",
> - iommu_irq_map[0], FDT_IRQ_TYPE_EDGE_LOW,
> - iommu_irq_map[1], FDT_IRQ_TYPE_EDGE_LOW,
> - iommu_irq_map[2], FDT_IRQ_TYPE_EDGE_LOW,
> - iommu_irq_map[3], FDT_IRQ_TYPE_EDGE_LOW);
> -
> - qemu_fdt_setprop_cell(fdt, iommu_node, "msi-parent", msi_phandle);
> -
> - *iommu_sys_phandle = iommu_phandle;
> -}
> -
> static void create_fdt_iommu(RISCVVirtState *s, uint16_t bdf)
> {
> const char comp[] = "riscv,pci-iommu";
> @@ -947,8 +907,14 @@ static void finalize_fdt(RISCVVirtState *s)
> create_fdt_virtio(s, irq_virtio_phandle);
>
> if (virt_is_iommu_sys_enabled(s)) {
> - create_fdt_iommu_sys(s, irq_mmio_phandle, msi_pcie_phandle,
> - &iommu_sys_phandle);
> + iommu_sys_phandle =
> + riscv_create_fdt_riscv_iommu_sys(MACHINE(s)->fdt,
> + s->memmap[VIRT_IOMMU_SYS].base,
> + s->memmap[VIRT_IOMMU_SYS].size,
> + &phandle,
> + irq_mmio_phandle,
> + msi_pcie_phandle,
> + IOMMU_SYS_IRQ);
> }
> create_fdt_pcie(s, irq_pcie_phandle, msi_pcie_phandle,
> iommu_sys_phandle);
> diff --git a/include/hw/riscv/fdt-common.h b/include/hw/riscv/fdt-common.h
> index e377682b32..65711468b8 100644
> --- a/include/hw/riscv/fdt-common.h
> +++ b/include/hw/riscv/fdt-common.h
> @@ -43,4 +43,9 @@ void riscv_create_fdt_syscon(void *fdt, uint32_t
> *next_phandle,
> hwaddr addr, hwaddr size,
> uint32_t reboot, uint32_t poweroff,
> bool sifive_test_compat);
> +uint32_t riscv_create_fdt_riscv_iommu_sys(void *fdt, hwaddr addr, hwaddr
> size,
> + uint32_t *next_phandle,
> + uint32_t irq_chip,
> + uint32_t msi_phandle,
> + uint32_t iommu_sys_irq);
> #endif
> --
> 2.43.0
>