Introduce a GPtrArray in VirtMachineState to track all SMMUv3 devices created on the virt machine, and use it when building the IORT table instead of relying on object_child_foreach_recursive() walks of the object tree.
This avoids recursive object traversal and provides a foundation for subsequent patches that need direct access to SMMUv3 instances for CMDQV-related handling. No functional change. No bios-tables qtest failures observed. Reviewed-by: Eric Auger <[email protected]> Reviewed-by: Nicolin Chen <[email protected]> Signed-off-by: Shameer Kolothum <[email protected]> --- include/hw/arm/virt.h | 1 + hw/arm/virt-acpi-build.c | 70 ++++++++++++++++++---------------------- hw/arm/virt.c | 3 ++ 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 3ba33b4bd2..171d44c644 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -207,6 +207,7 @@ struct VirtMachineState { MemoryRegion *sysmem; MemoryRegion *secure_sysmem; bool pci_preserve_config; + GPtrArray *smmuv3_devices; }; #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 3f285ff6c7..b00f3477ca 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -392,49 +392,41 @@ static int smmuv3_dev_idmap_compare(gconstpointer a, gconstpointer b) return map_a->input_base - map_b->input_base; } -static int iort_smmuv3_devices(Object *obj, void *opaque) -{ - VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine()); - AcpiIortSMMUv3Dev sdev = {0}; - GArray *sdev_blob = opaque; - AcpiIortIdMapping idmap; - PlatformBusDevice *pbus; - int min_bus, max_bus; - SysBusDevice *sbdev; - PCIBus *bus; - - if (!object_dynamic_cast(obj, TYPE_ARM_SMMUV3)) { - return 0; - } - - bus = PCI_BUS(object_property_get_link(obj, "primary-bus", &error_abort)); - sdev.accel = object_property_get_bool(obj, "accel", &error_abort); - sdev.ats = smmuv3_ats_enabled(ARM_SMMUV3(obj)); - pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev); - sbdev = SYS_BUS_DEVICE(obj); - sdev.base = platform_bus_get_mmio_addr(pbus, sbdev, 0); - sdev.base += vms->memmap[VIRT_PLATFORM_BUS].base; - sdev.irq = platform_bus_get_irqn(pbus, sbdev, 0); - sdev.irq += vms->irqmap[VIRT_PLATFORM_BUS]; - sdev.irq += ARM_SPI_BASE; - - pci_bus_range(bus, &min_bus, &max_bus); - sdev.rc_smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); - idmap.input_base = min_bus << 8, - idmap.id_count = (max_bus - min_bus + 1) << 8, - g_array_append_val(sdev.rc_smmu_idmaps, idmap); - g_array_append_val(sdev_blob, sdev); - return 0; -} - /* * Populate the struct AcpiIortSMMUv3Dev for all SMMUv3 devices and * return the total number of idmaps. */ -static int populate_smmuv3_dev(GArray *sdev_blob) +static int populate_smmuv3_dev(VirtMachineState *vms, GArray *sdev_blob) { - object_child_foreach_recursive(object_get_root(), - iort_smmuv3_devices, sdev_blob); + for (int i = 0; i < vms->smmuv3_devices->len; i++) { + Object *obj = OBJECT(g_ptr_array_index(vms->smmuv3_devices, i)); + AcpiIortSMMUv3Dev sdev = {0}; + AcpiIortIdMapping idmap; + PlatformBusDevice *pbus; + int min_bus, max_bus; + SysBusDevice *sbdev; + PCIBus *bus; + + bus = PCI_BUS(object_property_get_link(obj, "primary-bus", + &error_abort)); + sdev.accel = object_property_get_bool(obj, "accel", &error_abort); + sdev.ats = smmuv3_ats_enabled(ARM_SMMUV3(obj)); + pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev); + sbdev = SYS_BUS_DEVICE(obj); + sdev.base = platform_bus_get_mmio_addr(pbus, sbdev, 0); + sdev.base += vms->memmap[VIRT_PLATFORM_BUS].base; + sdev.irq = platform_bus_get_irqn(pbus, sbdev, 0); + sdev.irq += vms->irqmap[VIRT_PLATFORM_BUS]; + sdev.irq += ARM_SPI_BASE; + + pci_bus_range(bus, &min_bus, &max_bus); + sdev.rc_smmu_idmaps = g_array_new(false, true, + sizeof(AcpiIortIdMapping)); + idmap.input_base = min_bus << 8; + idmap.id_count = (max_bus - min_bus + 1) << 8; + g_array_append_val(sdev.rc_smmu_idmaps, idmap); + g_array_append_val(sdev_blob, sdev); + } /* Sort the smmuv3 devices(if any) by smmu idmap input_base */ g_array_sort(sdev_blob, smmuv3_dev_idmap_compare); /* @@ -568,7 +560,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) if (vms->legacy_smmuv3_present) { rc_smmu_idmaps_len = populate_smmuv3_legacy_dev(smmuv3_devs); } else { - rc_smmu_idmaps_len = populate_smmuv3_dev(smmuv3_devs); + rc_smmu_idmaps_len = populate_smmuv3_dev(vms, smmuv3_devs); } num_smmus = smmuv3_devs->len; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index b090233893..ac0606fe87 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -3865,6 +3865,7 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, } create_smmuv3_dev_dtb(vms, dev, bus, errp); + g_ptr_array_add(vms->smmuv3_devices, dev); } } @@ -4319,6 +4320,8 @@ static void virt_instance_init(Object *obj) vms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); vms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); cxl_machine_init(obj, &vms->cxl_devices_state); + + vms->smmuv3_devices = g_ptr_array_new_with_free_func(NULL); } static void virt_instance_finalize(Object *obj) -- 2.43.0
