Hi Eric, > -----Original Message----- > From: Eric Auger <eric.au...@redhat.com> > Sent: Thursday, June 5, 2025 10:40 AM > To: Shameer Kolothum <shameerali.kolothum.th...@huawei.com>; qemu- > a...@nongnu.org; qemu-devel@nongnu.org > Cc: peter.mayd...@linaro.org; j...@nvidia.com; nicol...@nvidia.com; > ddut...@redhat.com; berra...@redhat.com; nath...@nvidia.com; > mo...@nvidia.com; smost...@google.com; linux...@huawei.com; > wangzh...@hisilicon.com; jiangkun...@huawei.com; > jonathan.came...@huawei.com; zhangfei....@linaro.org > Subject: Re: [PATCH v3 2/6] hw/arm/virt-acpi-build: Re-arrange SMMUv3 > IORT build > > Hi Shameer, > > On 6/2/25 5:41 PM, Shameer Kolothum wrote: > > Introduces a new struct AcpiIortSMMUv3Dev to hold all the information > > required for SMMUv3 IORT node and use that for populating the node. > > > > The current machine wide SMMUv3 is named as legacy SMMUv3 as we > will > > soon add support for user-creatable SMMUv3 devices. These changes will > > be useful to have common code paths when we add that support. > > > > Signed-off-by: Shameer Kolothum > <shameerali.kolothum.th...@huawei.com> > > --- > > hw/arm/virt-acpi-build.c | 112 +++++++++++++++++++++++++++------------ > > hw/arm/virt.c | 1 + > > include/hw/arm/virt.h | 1 + > > 3 files changed, 80 insertions(+), 34 deletions(-) > > > > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c > > index 7e8e0f0298..bd26853ef6 100644 > > --- a/hw/arm/virt-acpi-build.c > > +++ b/hw/arm/virt-acpi-build.c > > @@ -266,6 +266,28 @@ static int iort_idmap_compare(gconstpointer a, > gconstpointer b) > > return idmap_a->input_base - idmap_b->input_base; > > } > > > > +struct AcpiIortSMMUv3Dev { > > + int irq; > > + hwaddr base; > > + GArray *idmaps; > > + size_t offset; > I would suggest to comment at least the offset field which is not obvious
Ok. > > +}; > > +typedef struct AcpiIortSMMUv3Dev AcpiIortSMMUv3Dev; > > + > > +static void > > +get_smmuv3_legacy_dev(VirtMachineState *vms, void *opaque) > > +{ > > + GArray *sdev_blob = opaque; > I don't get why we use an opaque pointer here. Yeah. That was based on a previous comment from Nicolin I guess to make it similar to the new SMMUv3 dev handling code in next patch, get_smmuv3_devices(). I will revisit and see if that still makes sense. Otherwise will get rid of it. > > + AcpiIortSMMUv3Dev sdev; > > + > > + sdev.idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); > > + object_child_foreach_recursive(object_get_root(), > > + iort_host_bridges, sdev.idmaps); > > + sdev.base = vms->memmap[VIRT_SMMU].base; > > + sdev.irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE; > > + g_array_append_val(sdev_blob, sdev); > So if I understand correctly this helper populate an AcpiIortSMMUv3Dev > object with the legacy iommu info and add it in the array of > AcpiIortSMMUv3Dev. The name of the helper does not really reflect what > it does and generally get is associated with a put. I would suggest to > rename. I see that afterwards you call > > sdev = &g_array_index(smmuv3_devs, AcpiIortSMMUv3Dev, 0); > to retrieve the first element and then sort the ipmap array. > > Why can't you do all that stuff in the helper? Ok. I will revisit this and may be good to fold everything into one function. > > > +} > > + > > /* > > * Input Output Remapping Table (IORT) > > * Conforms to "IO Remapping Table System Software on ARM > Platforms", > > @@ -274,11 +296,12 @@ static int iort_idmap_compare(gconstpointer a, > gconstpointer b) > > static void > > build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState > *vms) > > { > > - int i, nb_nodes, rc_mapping_count; > > - size_t node_size, smmu_offset = 0; > > - AcpiIortIdMapping *idmap; > > + int i, j, nb_nodes, rc_mapping_count; > > + AcpiIortSMMUv3Dev *sdev; > > + size_t node_size; > > + int num_smmus = 0; > > uint32_t id = 0; > > - GArray *smmu_idmaps = g_array_new(false, true, > sizeof(AcpiIortIdMapping)); > > + GArray *smmuv3_devs = g_array_new(false, true, > sizeof(AcpiIortSMMUv3Dev)); > > GArray *its_idmaps = g_array_new(false, true, > sizeof(AcpiIortIdMapping)); > > > > AcpiTable table = { .sig = "IORT", .rev = 3, .oem_id = vms->oem_id, > > @@ -286,28 +309,41 @@ build_iort(GArray *table_data, BIOSLinker > *linker, VirtMachineState *vms) > > /* Table 2 The IORT */ > > acpi_table_begin(&table, table_data); > > > > - if (vms->iommu == VIRT_IOMMU_SMMUV3) { > > - AcpiIortIdMapping next_range = {0}; > > - > > - object_child_foreach_recursive(object_get_root(), > > - iort_host_bridges, smmu_idmaps); > > - > > - /* Sort the smmu idmap by input_base */ > > - g_array_sort(smmu_idmaps, iort_idmap_compare); > > + nb_nodes = 2; /* RC, ITS */ > > + if (vms->legacy_smmuv3_present) { > > + get_smmuv3_legacy_dev(vms, smmuv3_devs); > > + /* > > + * There will be only one legacy SMMUv3 as it is a machine wide > one. > > + * And since it covers all the PCIe RCs in the machine, may have > > + * multiple SMMUv3 idmaps. Sort it by input_base. > > + */ > > + sdev = &g_array_index(smmuv3_devs, AcpiIortSMMUv3Dev, 0); > > + g_array_sort(sdev->idmaps, iort_idmap_compare); > > + } > > > > + num_smmus = smmuv3_devs->len; > > + if (num_smmus) { > > + AcpiIortIdMapping next_range = {0}; > > + int smmu_map_cnt = 0; > > /* > > * Split the whole RIDs by mapping from RC to SMMU, > > * build the ID mapping from RC to ITS directly. > > */ > > - for (i = 0; i < smmu_idmaps->len; i++) { > > - idmap = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i); > > - > > - if (next_range.input_base < idmap->input_base) { > > - next_range.id_count = idmap->input_base - > next_range.input_base; > > - g_array_append_val(its_idmaps, next_range); > > + for (i = 0; i < num_smmus; i++) { > > + AcpiIortIdMapping *idmap; > could belong to the inner block > > Otherwise looks good to me Thanks, Shameer > Cheers > > Eric > > + sdev = &g_array_index(smmuv3_devs, AcpiIortSMMUv3Dev, i); > > + > > + for (j = 0; j < sdev->idmaps->len; j++) { > > + idmap = &g_array_index(sdev->idmaps, AcpiIortIdMapping, j); > > + > > + if (next_range.input_base < idmap->input_base) { > > + next_range.id_count = idmap->input_base - > > + next_range.input_base; > > + g_array_append_val(its_idmaps, next_range); > > + } > > + next_range.input_base = idmap->input_base + idmap- > >id_count; > > + smmu_map_cnt++; > > } > > - > > - next_range.input_base = idmap->input_base + idmap->id_count; > > } > > > > /* Append the last RC -> ITS ID mapping */ > > @@ -316,10 +352,9 @@ build_iort(GArray *table_data, BIOSLinker > *linker, VirtMachineState *vms) > > g_array_append_val(its_idmaps, next_range); > > } > > > > - nb_nodes = 3; /* RC, ITS, SMMUv3 */ > > - rc_mapping_count = smmu_idmaps->len + its_idmaps->len; > > + nb_nodes += num_smmus; > > + rc_mapping_count = smmu_map_cnt + its_idmaps->len; > > } else { > > - nb_nodes = 2; /* RC, ITS */ > > rc_mapping_count = 1; > > } > > /* Number of IORT Nodes */ > > @@ -341,10 +376,11 @@ build_iort(GArray *table_data, BIOSLinker > *linker, VirtMachineState *vms) > > /* GIC ITS Identifier Array */ > > build_append_int_noprefix(table_data, 0 /* MADT translation_id */, > 4); > > > > - if (vms->iommu == VIRT_IOMMU_SMMUV3) { > > - int irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE; > > + for (i = 0; i < num_smmus; i++) { > > + sdev = &g_array_index(smmuv3_devs, AcpiIortSMMUv3Dev, i); > > + int irq = sdev->irq; > > > > - smmu_offset = table_data->len - table.table_offset; > > + sdev->offset = table_data->len - table.table_offset; > > /* Table 9 SMMUv3 Format */ > > build_append_int_noprefix(table_data, 4 /* SMMUv3 */, 1); /* Type > */ > > node_size = SMMU_V3_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE; > > @@ -355,7 +391,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, > VirtMachineState *vms) > > /* Reference to ID Array */ > > build_append_int_noprefix(table_data, SMMU_V3_ENTRY_SIZE, 4); > > /* Base address */ > > - build_append_int_noprefix(table_data, vms- > >memmap[VIRT_SMMU].base, 8); > > + build_append_int_noprefix(table_data, sdev->base, 8); > > /* Flags */ > > build_append_int_noprefix(table_data, 1 /* COHACC Override */, 4); > > build_append_int_noprefix(table_data, 0, 4); /* Reserved */ > > @@ -404,15 +440,19 @@ build_iort(GArray *table_data, BIOSLinker > *linker, VirtMachineState *vms) > > build_append_int_noprefix(table_data, 0, 3); /* Reserved */ > > > > /* Output Reference */ > > - if (vms->iommu == VIRT_IOMMU_SMMUV3) { > > + if (num_smmus) { > > AcpiIortIdMapping *range; > > > > /* translated RIDs connect to SMMUv3 node: RC -> SMMUv3 -> ITS > */ > > - for (i = 0; i < smmu_idmaps->len; i++) { > > - range = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i); > > - /* output IORT node is the smmuv3 node */ > > - build_iort_id_mapping(table_data, range->input_base, > > - range->id_count, smmu_offset); > > + for (i = 0; i < num_smmus; i++) { > > + sdev = &g_array_index(smmuv3_devs, AcpiIortSMMUv3Dev, i); > > + > > + for (j = 0; j < sdev->idmaps->len; j++) { > > + range = &g_array_index(sdev->idmaps, AcpiIortIdMapping, j); > > + /* output IORT node is the smmuv3 node */ > > + build_iort_id_mapping(table_data, range->input_base, > > + range->id_count, sdev->offset); > > + } > > } > > > > /* bypassed RIDs connect to ITS group node directly: RC -> ITS */ > > @@ -428,8 +468,12 @@ build_iort(GArray *table_data, BIOSLinker > *linker, VirtMachineState *vms) > > } > > > > acpi_table_end(linker, &table); > > - g_array_free(smmu_idmaps, true); > > g_array_free(its_idmaps, true); > > + for (i = 0; i < num_smmus; i++) { > > + sdev = &g_array_index(smmuv3_devs, AcpiIortSMMUv3Dev, i); > > + g_array_free(sdev->idmaps, true); > > + } > > + g_array_free(smmuv3_devs, true); > > } > > > > /* > > diff --git a/hw/arm/virt.c b/hw/arm/virt.c > > index 9a6cd085a3..73bd2bd5f2 100644 > > --- a/hw/arm/virt.c > > +++ b/hw/arm/virt.c > > @@ -1614,6 +1614,7 @@ static void create_pcie(VirtMachineState *vms) > > create_smmu(vms, vms->bus); > > qemu_fdt_setprop_cells(ms->fdt, nodename, "iommu-map", > > 0x0, vms->iommu_phandle, 0x0, 0x10000); > > + vms->legacy_smmuv3_present = true; > > break; > > default: > > g_assert_not_reached(); > > diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h > > index 9a1b0f53d2..8b1404b5f6 100644 > > --- a/include/hw/arm/virt.h > > +++ b/include/hw/arm/virt.h > > @@ -174,6 +174,7 @@ struct VirtMachineState { > > char *oem_id; > > char *oem_table_id; > > bool ns_el2_virt_timer_irq; > > + bool legacy_smmuv3_present; > > }; > > > > #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : > VIRT_PCIE_ECAM) >