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:
committed by
Peter Maydell
parent
f4ec4767ce
commit
92e340997f
+31
-39
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user