Add an "identifier" property to the SMMUv3 device and use it when building the ACPI IORT SMMUv3 node Identifier field.
This avoids relying on device enumeration order and provides a stable per-device identifier. A subsequent patch will use the same identifier when generating the DSDT description for Tegra241 CMDQV, ensuring that the IORT and DSDT entries refer to the same SMMUv3 instance. The identifier is assigned at pre-plug time, accounting for the ITS Group node that build_iort() places before SMMUv3 nodes in the IORT table, so that identifiers are globally unique across all IORT nodes. No functional change: IORT blob content for bios-tables qtest is identical to before. Reviewed-by: Eric Auger <[email protected]> Reviewed-by: Nicolin Chen <[email protected]> Signed-off-by: Shameer Kolothum <[email protected]> --- include/hw/arm/smmuv3.h | 1 + hw/arm/smmuv3.c | 2 ++ hw/arm/virt-acpi-build.c | 5 ++++- hw/arm/virt.c | 12 ++++++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h index aa6a79237a..0fce564619 100644 --- a/include/hw/arm/smmuv3.h +++ b/include/hw/arm/smmuv3.h @@ -64,6 +64,7 @@ struct SMMUv3State { qemu_irq irq[4]; QemuMutex mutex; char *stage; + uint8_t identifier; /* SMMU has HW accelerator support for nested S1 + s2 */ bool accel; diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 665e6a2538..763b86c417 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -2126,6 +2126,8 @@ static const Property smmuv3_properties[] = { * Defaults to stage 1 */ DEFINE_PROP_STRING("stage", SMMUv3State, stage), + /* Identifier used for ACPI IORT SMMUv3 (and DSDT for CMDQV) generation */ + DEFINE_PROP_UINT8("identifier", SMMUv3State, identifier, 0), DEFINE_PROP_BOOL("accel", SMMUv3State, accel, false), /* GPA of MSI doorbell, for SMMUv3 accel use. */ DEFINE_PROP_UINT64("msi-gpa", SMMUv3State, msi_gpa, 0), diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index b00f3477ca..9d05982137 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -349,6 +349,7 @@ static int iort_idmap_compare(gconstpointer a, gconstpointer b) typedef struct AcpiIortSMMUv3Dev { int irq; hwaddr base; + uint8_t id; GArray *rc_smmu_idmaps; /* Offset of the SMMUv3 IORT Node relative to the start of the IORT */ size_t offset; @@ -411,6 +412,7 @@ static int populate_smmuv3_dev(VirtMachineState *vms, GArray *sdev_blob) &error_abort)); sdev.accel = object_property_get_bool(obj, "accel", &error_abort); sdev.ats = smmuv3_ats_enabled(ARM_SMMUV3(obj)); + sdev.id = object_property_get_uint(obj, "identifier", &error_abort); pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev); sbdev = SYS_BUS_DEVICE(obj); sdev.base = platform_bus_get_mmio_addr(pbus, sbdev, 0); @@ -637,7 +639,8 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) (ID_MAPPING_ENTRY_SIZE * smmu_mapping_count); build_append_int_noprefix(table_data, node_size, 2); /* Length */ build_append_int_noprefix(table_data, 4, 1); /* Revision */ - build_append_int_noprefix(table_data, id++, 4); /* Identifier */ + build_append_int_noprefix(table_data, sdev->id, 4); /* Identifier */ + id++; /* advance shared counter for RC/RMR node uniqueness */ /* Number of ID mappings */ build_append_int_noprefix(table_data, smmu_mapping_count, 4); /* Reference to ID Array */ diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 2add7401a1..d8d27f2ef6 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -254,6 +254,9 @@ static MemMapEntry extended_memmap[] = { /* Any CXL Fixed memory windows come here */ }; +/* Counts SMMUv3 devices plugged; used to assign stable IORT identifiers */ +static uint8_t smmuv3_dev_id; + static const int a15irqmap[] = { [VIRT_UART0] = 1, [VIRT_RTC] = 2, @@ -3830,6 +3833,15 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, OBJECT(vms->sysmem), NULL); object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(vms->secure_sysmem), NULL); + /* + * In build_iort(), the ITS node(id=0) precedes SMMUv3 nodes + * when present. Account for it so this SMMUv3's identifier + * is globally unique across all IORT nodes. + */ + uint8_t its_offset = (vms->msi_controller == VIRT_MSI_CTRL_ITS) + ? 1 : 0; + object_property_set_uint(OBJECT(dev), "identifier", + its_offset + smmuv3_dev_id++, NULL); } if (object_property_get_bool(OBJECT(dev), "accel", &error_abort)) { hwaddr db_start = 0; -- 2.43.0
