Hi Shameer, On 11/8/24 13:52, Shameer Kolothum wrote: > From: Nicolin Chen <nicol...@nvidia.com> > > Now that we can have multiple user-creatable smmuv3-nested > devices, each associated with different pci buses, update > IORT ID mappings accordingly. > > Signed-off-by: Nicolin Chen <nicol...@nvidia.com> > Signed-off-by: Shameer Kolothum <shameerali.kolothum.th...@huawei.com> > --- > hw/arm/virt-acpi-build.c | 34 ++++++++++++++++++++++++---------- > include/hw/arm/virt.h | 6 ++++++ > 2 files changed, 30 insertions(+), 10 deletions(-) > > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c > index e10cad86dd..ec4cdfb2d7 100644 > --- a/hw/arm/virt-acpi-build.c > +++ b/hw/arm/virt-acpi-build.c > @@ -276,8 +276,10 @@ 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; > + size_t node_size, *smmu_offset; > AcpiIortIdMapping *idmap; > + hwaddr base; > + int irq, num_smmus = 0; > uint32_t id = 0; > GArray *smmu_idmaps = g_array_new(false, true, > sizeof(AcpiIortIdMapping)); > GArray *its_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); > @@ -287,7 +289,21 @@ 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) { > + if (vms->smmu_nested_count) { > + irq = vms->irqmap[VIRT_SMMU_NESTED] + ARM_SPI_BASE; > + base = vms->memmap[VIRT_SMMU_NESTED].base; > + num_smmus = vms->smmu_nested_count; > + } else if (virt_has_smmuv3(vms)) { > + irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE; > + base = vms->memmap[VIRT_SMMU].base; > + num_smmus = 1; > + } > + > + smmu_offset = g_new0(size_t, num_smmus); > + nb_nodes = 2; /* RC, ITS */ > + nb_nodes += num_smmus; /* SMMU nodes */ > + > + if (virt_has_smmuv3(vms)) { > AcpiIortIdMapping next_range = {0}; > > object_child_foreach_recursive(object_get_root(), > @@ -317,10 +333,8 @@ 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; > } else { > - nb_nodes = 2; /* RC, ITS */ > rc_mapping_count = 1; > } > /* Number of IORT Nodes */ > @@ -342,10 +356,9 @@ 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++) { > + smmu_offset[i] = table_data->len - table.table_offset; > I would have expected changes in the smmu idmap has well. If a given SMMU instance now protects a given bus hierarchy shouldn't it be reflected in a differentiated SMMU idmap for each of them (RID subset of SMMU->pci-bus mapping to a specific IORT SMMU node)? How is it done currently?
Thanks Eric > - smmu_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; > @@ -356,7 +369,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, base + (i * SMMU_IO_LEN), 8); > /* Flags */ > build_append_int_noprefix(table_data, 1 /* COHACC Override */, 4); > build_append_int_noprefix(table_data, 0, 4); /* Reserved */ > @@ -367,6 +380,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, > VirtMachineState *vms) > build_append_int_noprefix(table_data, irq + 1, 4); /* PRI */ > build_append_int_noprefix(table_data, irq + 3, 4); /* GERR */ > build_append_int_noprefix(table_data, irq + 2, 4); /* Sync */ > + irq += NUM_SMMU_IRQS; > build_append_int_noprefix(table_data, 0, 4); /* Proximity domain */ > /* DeviceID mapping index (ignored since interrupts are GSIV based) > */ > build_append_int_noprefix(table_data, 0, 4); > @@ -405,7 +419,7 @@ 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 (virt_has_smmuv3(vms)) { > AcpiIortIdMapping *range; > > /* translated RIDs connect to SMMUv3 node: RC -> SMMUv3 -> ITS */ > @@ -413,7 +427,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, > VirtMachineState *vms) > 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); > + range->id_count, smmu_offset[i]); > } > > /* bypassed RIDs connect to ITS group node directly: RC -> ITS */ > diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h > index 50e47a4ef3..304ab134ae 100644 > --- a/include/hw/arm/virt.h > +++ b/include/hw/arm/virt.h > @@ -219,4 +219,10 @@ static inline int > virt_gicv3_redist_region_count(VirtMachineState *vms) > vms->highmem_redists) ? 2 : 1; > } > > +static inline bool virt_has_smmuv3(const VirtMachineState *vms) > +{ > + return vms->iommu == VIRT_IOMMU_SMMUV3 || > + vms->iommu == VIRT_IOMMU_SMMUV3_NESTED; > +} > + > #endif /* QEMU_ARM_VIRT_H */