@samitouri / QOSamiQemu / commits / 92e340997f

hw/arm/virt: Use stored SMMUv3 device list for IORT build

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 <eric.auger@redhat.com> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com> Tested-by: Eric Auger <eric.auger@redhat.com> Message-id: 20260609112552.378999-10-skolothumtho@nvidia.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Shameer Kolothum committed Jun 9, 2026 at 12:25 UTC 92e340997f861cc7289da76336d40f65a4a58318
3 files changed +35 -39
hw/arm/virt-acpi-build.c
+31 -39
@@ -392,49 +392,41 @@ static int smmuv3_dev_idmap_compare(gconstpointer a, gconstpointer b)
392 return map_a->input_base - map_b->input_base;
393 }
394
395 -static int iort_smmuv3_devices(Object *obj, void *opaque)
396 -{
397 - VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine());
398 - AcpiIortSMMUv3Dev sdev = {0};
399 - GArray *sdev_blob = opaque;
400 - AcpiIortIdMapping idmap;
401 - PlatformBusDevice *pbus;
402 - int min_bus, max_bus;
403 - SysBusDevice *sbdev;
404 - PCIBus *bus;
405 -
406 - if (!object_dynamic_cast(obj, TYPE_ARM_SMMUV3)) {
407 - return 0;
408 - }
409 -
410 - bus = PCI_BUS(object_property_get_link(obj, "primary-bus", &error_abort));
411 - sdev.accel = object_property_get_bool(obj, "accel", &error_abort);
412 - sdev.ats = smmuv3_ats_enabled(ARM_SMMUV3(obj));
413 - pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
414 - sbdev = SYS_BUS_DEVICE(obj);
415 - sdev.base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
416 - sdev.base += vms->memmap[VIRT_PLATFORM_BUS].base;
417 - sdev.irq = platform_bus_get_irqn(pbus, sbdev, 0);
418 - sdev.irq += vms->irqmap[VIRT_PLATFORM_BUS];
419 - sdev.irq += ARM_SPI_BASE;
420 -
421 - pci_bus_range(bus, &min_bus, &max_bus);
422 - sdev.rc_smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping));
423 - idmap.input_base = min_bus << 8,
424 - idmap.id_count = (max_bus - min_bus + 1) << 8,
425 - g_array_append_val(sdev.rc_smmu_idmaps, idmap);
426 - g_array_append_val(sdev_blob, sdev);
427 - return 0;
428 -}
429 -
395 /*
396 * Populate the struct AcpiIortSMMUv3Dev for all SMMUv3 devices and
397 * return the total number of idmaps.
398 */
434 -static int populate_smmuv3_dev(GArray *sdev_blob)
399 +static int populate_smmuv3_dev(VirtMachineState *vms, GArray *sdev_blob)
400 {
436 - object_child_foreach_recursive(object_get_root(),
437 - iort_smmuv3_devices, sdev_blob);
401 + for (int i = 0; i < vms->smmuv3_devices->len; i++) {
402 + Object *obj = OBJECT(g_ptr_array_index(vms->smmuv3_devices, i));
403 + AcpiIortSMMUv3Dev sdev = {0};
404 + AcpiIortIdMapping idmap;
405 + PlatformBusDevice *pbus;
406 + int min_bus, max_bus;
407 + SysBusDevice *sbdev;
408 + PCIBus *bus;
409 +
410 + bus = PCI_BUS(object_property_get_link(obj, "primary-bus",
411 + &error_abort));
412 + sdev.accel = object_property_get_bool(obj, "accel", &error_abort);
413 + sdev.ats = smmuv3_ats_enabled(ARM_SMMUV3(obj));
414 + pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
415 + sbdev = SYS_BUS_DEVICE(obj);
416 + sdev.base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
417 + sdev.base += vms->memmap[VIRT_PLATFORM_BUS].base;
418 + sdev.irq = platform_bus_get_irqn(pbus, sbdev, 0);
419 + sdev.irq += vms->irqmap[VIRT_PLATFORM_BUS];
420 + sdev.irq += ARM_SPI_BASE;
421 +
422 + pci_bus_range(bus, &min_bus, &max_bus);
423 + sdev.rc_smmu_idmaps = g_array_new(false, true,
424 + sizeof(AcpiIortIdMapping));
425 + idmap.input_base = min_bus << 8;
426 + idmap.id_count = (max_bus - min_bus + 1) << 8;
427 + g_array_append_val(sdev.rc_smmu_idmaps, idmap);
428 + g_array_append_val(sdev_blob, sdev);
429 + }
430 /* Sort the smmuv3 devices(if any) by smmu idmap input_base */
431 g_array_sort(sdev_blob, smmuv3_dev_idmap_compare);
432 /*
@@ -568,7 +560,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
560 if (vms->legacy_smmuv3_present) {
561 rc_smmu_idmaps_len = populate_smmuv3_legacy_dev(smmuv3_devs);
562 } else {
571 - rc_smmu_idmaps_len = populate_smmuv3_dev(smmuv3_devs);
563 + rc_smmu_idmaps_len = populate_smmuv3_dev(vms, smmuv3_devs);
564 }
565
566 num_smmus = smmuv3_devs->len;
hw/arm/virt.c
+3
@@ -3865,6 +3865,7 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
3865 }
3866
3867 create_smmuv3_dev_dtb(vms, dev, bus, errp);
3868 + g_ptr_array_add(vms->smmuv3_devices, dev);
3869 }
3870 }
3871
@@ -4319,6 +4320,8 @@ static void virt_instance_init(Object *obj)
4320 vms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
4321 vms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
4322 cxl_machine_init(obj, &vms->cxl_devices_state);
4323 +
4324 + vms->smmuv3_devices = g_ptr_array_new_with_free_func(NULL);
4325 }
4326
4327 static void virt_instance_finalize(Object *obj)
include/hw/arm/virt.h
+1
@@ -207,6 +207,7 @@ struct VirtMachineState {
207 MemoryRegion *sysmem;
208 MemoryRegion *secure_sysmem;
209 bool pci_preserve_config;
210 + GPtrArray *smmuv3_devices;
211 };
212
213 #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)