From: Mirsad Ostrakovic <[email protected]> Create new smmu device for sysbus. Add memory region for SMMU to memory map.
Signed-off-by: Mirsad Ostrakovic <[email protected]> Signed-off-by: Ruslan Ruslichenko <[email protected]> --- hw/arm/virt-acpi-build.c | 4 +- hw/arm/virt.c | 84 +++++++++++++++++++++++++++++++++------- include/hw/arm/virt.h | 4 +- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 200e2a1da7..2d7e2e2725 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -334,8 +334,8 @@ static int populate_smmuv3_legacy_dev(GArray *sdev_blob) */ g_array_sort(sdev.rc_smmu_idmaps, iort_idmap_compare); - sdev.base = vms->memmap[VIRT_SMMU].base; - sdev.irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE; + sdev.base = vms->memmap[VIRT_SMMU_PCIE].base; + sdev.irq = vms->irqmap[VIRT_SMMU_PCIE] + ARM_SPI_BASE; g_array_append_val(sdev_blob, sdev); return sdev.rc_smmu_idmaps->len; } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index d9d7b982b3..ad609bc651 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -187,13 +187,14 @@ static const MemMapEntry base_memmap[] = { [VIRT_FW_CFG] = { 0x09020000, 0x00000018 }, [VIRT_GPIO] = { 0x09030000, 0x00001000 }, [VIRT_UART1] = { 0x09040000, 0x00001000 }, - [VIRT_SMMU] = { 0x09050000, SMMU_IO_LEN }, - [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, - [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, - [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, - [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, - [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 }, - [VIRT_ACPI_PCIHP] = { 0x090c0000, ACPI_PCIHP_SIZE }, + [VIRT_SMMU_PCIE] = { 0x09050000, SMMU_IO_LEN }, + [VIRT_SMMU_SYSBUS] = { 0x09070000, SMMU_IO_LEN }, + [VIRT_PCDIMM_ACPI] = { 0x09090000, MEMORY_HOTPLUG_IO_LEN }, + [VIRT_ACPI_GED] = { 0x090a0000, ACPI_GED_EVT_SEL_LEN }, + [VIRT_NVDIMM_ACPI] = { 0x090b0000, NVDIMM_ACPI_IO_LEN}, + [VIRT_PVTIME] = { 0x090c0000, 0x00010000 }, + [VIRT_SECURE_GPIO] = { 0x090d0000, 0x00001000 }, + [VIRT_ACPI_PCIHP] = { 0x090e0000, ACPI_PCIHP_SIZE }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, @@ -247,7 +248,8 @@ static const int a15irqmap[] = { [VIRT_ACPI_GED] = 9, [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */ - [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ + [VIRT_SMMU_PCIE] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ + [VIRT_SMMU_SYSBUS] = 78, /* ...to 78 + NUM_SMMU_IRQS - 1 */ [VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */ }; @@ -1514,14 +1516,14 @@ static void create_smmuv3_dev_dtb(VirtMachineState *vms, 0x0, vms->iommu_phandle, 0x0, 0x10000); } -static void create_smmu(const VirtMachineState *vms, +static void create_smmu_pcie(const VirtMachineState *vms, PCIBus *bus) { VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); - int irq = vms->irqmap[VIRT_SMMU]; + int irq = vms->irqmap[VIRT_SMMU_PCIE]; int i; - hwaddr base = vms->memmap[VIRT_SMMU].base; - hwaddr size = vms->memmap[VIRT_SMMU].size; + hwaddr base = vms->memmap[VIRT_SMMU_PCIE].base; + hwaddr size = vms->memmap[VIRT_SMMU_PCIE].size; DeviceState *dev; if (vms->iommu != VIRT_IOMMU_SMMUV3 || !vms->iommu_phandle) { @@ -1533,7 +1535,7 @@ static void create_smmu(const VirtMachineState *vms, if (!vmc->no_nested_smmu) { object_property_set_str(OBJECT(dev), "stage", "nested", &error_fatal); } - object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus), + object_property_set_link(OBJECT(dev), "pci-primary-bus", OBJECT(bus), &error_abort); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); @@ -1544,6 +1546,58 @@ static void create_smmu(const VirtMachineState *vms, create_smmuv3_dt_bindings(vms, base, size, irq); } +static void create_smmu_sysbus(VirtMachineState *vms) +{ + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); + char *node; + const char compat[] = "arm,smmu-v3"; + int irq = vms->irqmap[VIRT_SMMU_SYSBUS]; + int i; + hwaddr base = vms->memmap[VIRT_SMMU_SYSBUS].base; + hwaddr size = vms->memmap[VIRT_SMMU_SYSBUS].size; + const char irq_names[] = "eventq\0priq\0cmdq-sync\0gerror"; + DeviceState *dev; + MachineState *ms = MACHINE(vms); + + vms->sysbus_iommu_phandle = qemu_fdt_alloc_phandle(ms->fdt); + + dev = qdev_new(TYPE_ARM_SMMUV3); + + if (!vmc->no_nested_smmu) { + object_property_set_str(OBJECT(dev), "stage", "nested", &error_fatal); + } + object_property_set_link(OBJECT(dev), "generic-primary-bus", + OBJECT(sysbus_get_default()), &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + for (i = 0; i < NUM_SMMU_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, + qdev_get_gpio_in(vms->gic, irq + i)); + } + + node = g_strdup_printf("/smmuv3@%" PRIx64, base); + qemu_fdt_add_subnode(ms->fdt, node); + qemu_fdt_setprop(ms->fdt, node, "compatible", compat, sizeof(compat)); + qemu_fdt_setprop_sized_cells(ms->fdt, node, "reg", 2, base, 2, size); + + qemu_fdt_setprop_cells(ms->fdt, node, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, irq , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI, + GIC_FDT_IRQ_TYPE_SPI, irq + 1, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI, + GIC_FDT_IRQ_TYPE_SPI, irq + 2, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI, + GIC_FDT_IRQ_TYPE_SPI, irq + 3, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI); + + qemu_fdt_setprop(ms->fdt, node, "interrupt-names", irq_names, + sizeof(irq_names)); + + qemu_fdt_setprop(ms->fdt, node, "dma-coherent", NULL, 0); + + qemu_fdt_setprop_cell(ms->fdt, node, "#iommu-cells", 1); + + qemu_fdt_setprop_cell(ms->fdt, node, "phandle", vms->sysbus_iommu_phandle); + + g_free(node); +} + static void create_virtio_iommu_dt_bindings(VirtMachineState *vms) { const char compat[] = "virtio,pci-iommu\0pci1af4,1057"; @@ -1692,7 +1746,7 @@ static void create_pcie(VirtMachineState *vms) switch (vms->iommu) { case VIRT_IOMMU_SMMUV3: - create_smmu(vms, vms->bus); + create_smmu_pcie(vms, vms->bus); if (!vms->default_bus_bypass_iommu) { qemu_fdt_setprop_cells(ms->fdt, nodename, "iommu-map", 0x0, vms->iommu_phandle, 0x0, 0x10000); @@ -2509,6 +2563,8 @@ static void machvirt_init(MachineState *machine) create_pcie(vms); create_cxl_host_reg_region(vms); + create_smmu_sysbus(vms); + if (aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) { vms->acpi_dev = create_acpi_ged(vms); vms->generic_error_notifier.notify = virt_generic_error_req; diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index c77a33f6df..00b276ecf0 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -63,7 +63,8 @@ enum { VIRT_GIC_VCPU, VIRT_GIC_ITS, VIRT_GIC_REDIST, - VIRT_SMMU, + VIRT_SMMU_PCIE, + VIRT_SMMU_SYSBUS, VIRT_UART0, VIRT_MMIO, VIRT_RTC, @@ -168,6 +169,7 @@ struct VirtMachineState { uint32_t gic_phandle; uint32_t msi_phandle; uint32_t iommu_phandle; + uint32_t sysbus_iommu_phandle; int psci_conduit; hwaddr highest_gpa; DeviceState *gic; -- 2.43.0
