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>
This commit is contained in:
Shameer Kolothum
2026-06-16 11:06:46 +01:00
committed by Peter Maydell
parent f4ec4767ce
commit 92e340997f
3 changed files with 35 additions and 39 deletions
+31 -39
View File
@@ -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;
+3
View File
@@ -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)
+1
View File
@@ -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)