> -----Original Message-----
> From: qemu-devel-
> bounces+shameerali.kolothum.thodi=huawei....@nongnu.org <qemu-
> devel-bounces+shameerali.kolothum.thodi=huawei....@nongnu.org> On
> Behalf Of Eric Auger
> Sent: Monday, May 5, 2025 9:40 AM
> To: Shameerali Kolothum Thodi
> <shameerali.kolothum.th...@huawei.com>; qemu-...@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; Linuxarm
> <linux...@huawei.com>; Wangzhou (B) <wangzh...@hisilicon.com>;
> jiangkunkun <jiangkun...@huawei.com>; Jonathan Cameron
> <jonathan.came...@huawei.com>; zhangfei....@linaro.org
> Subject: Re: [PATCH v2 2/6] hw/arm/virt-acpi-build: Update IORT for
> multiple smmuv3 devices
> 
> Hi Shameer,
> 
> On 5/2/25 12:27 PM, Shameer Kolothum wrote:
> > With the soon to be introduced user-creatable SMMUv3 devices for
> > virt, it is possible to have multiple SMMUv3 devices associated
> > with different PCIe root complexes.
> >
> > Update IORT nodes accordingly.
> >
> > Signed-off-by: Shameer Kolothum
> <shameerali.kolothum.th...@huawei.com>
> > ---
> >  hw/arm/virt-acpi-build.c | 162 +++++++++++++++++++++++++++++++--------
> I would recommend to split that patch. I think you can first introduce
> the new struct and adapting the exicting code for the "legacy
> instantiation mode" and then have a saparet patch for handling user
> created instances. It will be easier to review.

Ok. I will split this patch.

> 
> At some point in the series you shall check the user is not attempting
> to use legacy mode and user creatable mode concurrently. I don't know if
> it is done yet.

Yes, it is done in patch #5. See changes to virt_machine_device_pre_plug_cb().


> >  hw/arm/virt.c            |   1 +
> >  include/hw/arm/virt.h    |   1 +
> >  3 files changed, 131 insertions(+), 33 deletions(-)
> >
> > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> > index 3ac8f8e178..3ce70f8fa9 100644
> > --- a/hw/arm/virt-acpi-build.c
> > +++ b/hw/arm/virt-acpi-build.c
> > @@ -43,6 +43,7 @@
> >  #include "hw/acpi/generic_event_device.h"
> >  #include "hw/acpi/tpm.h"
> >  #include "hw/acpi/hmat.h"
> > +#include "hw/arm/smmuv3.h"
> >  #include "hw/pci/pcie_host.h"
> >  #include "hw/pci/pci.h"
> >  #include "hw/pci/pci_bus.h"
> > @@ -266,6 +267,75 @@ static int iort_idmap_compare(gconstpointer a,
> gconstpointer b)
> >      return idmap_a->input_base - idmap_b->input_base;
> >  }
> >
> > +struct SMMUv3Device {
> > +    int irq;
> > +    hwaddr base;
> > +    GArray *smmu_idmaps;
> > +    size_t offset;
> > +};
> > +typedef struct SMMUv3Device SMMUv3Device;
> > +
> > +static int smmuv3_dev_idmap_compare(gconstpointer a, gconstpointer
> b)
> > +{
> > +    SMMUv3Device *sdev_a = (SMMUv3Device *)a;
> > +    SMMUv3Device *sdev_b = (SMMUv3Device *)b;
> > +    AcpiIortIdMapping *map_a = &g_array_index(sdev_a->smmu_idmaps,
> > +                                              AcpiIortIdMapping, 0);
> > +    AcpiIortIdMapping *map_b = &g_array_index(sdev_b->smmu_idmaps,
> > +                                              AcpiIortIdMapping, 0);
> > +    return map_a->input_base - map_b->input_base;
> > +}
> > +
> > +static void
> > +get_smmuv3_legacy_dev(VirtMachineState *vms, GArray *
> smmuv3_devices)
> > +{
> > +    SMMUv3Device sdev;
> > +
> > +    sdev.smmu_idmaps = g_array_new(false, true,
> sizeof(AcpiIortIdMapping));
> > +    object_child_foreach_recursive(object_get_root(),
> > +                                   iort_host_bridges, sdev.smmu_idmaps);
> > +    sdev.base = vms->memmap[VIRT_SMMU].base;
> > +    sdev.irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE;
> > +    g_array_append_val(smmuv3_devices, sdev);
> > +}
> > +
> > +static int get_smmuv3_devices(Object *obj, void *opaque)
> > +{
> > +    PCIBus *bus;
> > +    SMMUv3Device sdev;
> > +    SysBusDevice *sbdev;
> > +    int min_bus, max_bus;
> > +    AcpiIortIdMapping idmap;
> > +    PlatformBusDevice *pbus;
> > +    GArray *sdev_blob = opaque;
> > +    VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine());
> > +
> > +    if (!object_dynamic_cast(obj, TYPE_ARM_SMMUV3)) {
> > +        return 0;
> > +    }
> > +
> > +    bus = PCI_BUS(object_property_get_link(obj, "primary-bus",
> &error_abort));
> > +    if (!bus || pci_bus_bypass_iommu(bus)) {
> can't we simply prevent a user creatable SMMU to be attached to
> 
> pci_bus_bypass_iommu(bus) ?

Ok. I think that can be done.

> 
> > +        return 0;
> > +    }
> > +
> > +    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.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.smmu_idmaps, idmap);
> > +    g_array_append_val(sdev_blob, sdev);
> > +    return 0;
> > +}
> > +
> >  /*
> >   * Input Output Remapping Table (IORT)
> >   * Conforms to "IO Remapping Table System Software on ARM
> Platforms",
> > @@ -274,11 +344,11 @@ 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;
> > +    size_t node_size;
> > +    int num_smmus = 0;
> >      uint32_t id = 0;
> > -    GArray *smmu_idmaps = g_array_new(false, true,
> sizeof(AcpiIortIdMapping));
> > +    GArray *smmuv3_devices = g_array_new(false, true,
> sizeof(SMMUv3Device));
> >      GArray *its_idmaps = g_array_new(false, true,
> sizeof(AcpiIortIdMapping));
> >
> >      AcpiTable table = { .sig = "IORT", .rev = 3, .oem_id = vms->oem_id,
> > @@ -286,28 +356,46 @@ 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};
> > -
> > +    nb_nodes = 2; /* RC, ITS */
> > +    if (vms->legacy_smmuv3_present) {
> > +        get_smmuv3_legacy_dev(vms, smmuv3_devices);
> > +        /*
> > +         * 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.
> > +         */
> > +        SMMUv3Device *s = &g_array_index(smmuv3_devices,
> SMMUv3Device, 0);
> > +        g_array_sort(s->smmu_idmaps, iort_idmap_compare);
> > +    } else {
> >          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);
> > +                                       get_smmuv3_devices, smmuv3_devices);
> > +        /* Sort the smmuv3 devices(if any) by smmu idmap input_base */
> > +        g_array_sort(smmuv3_devices, smmuv3_dev_idmap_compare);
> > +    }
> >
> > +    num_smmus = smmuv3_devices->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;
> extra line needed

Sure. I wonder why the checkpatch --strict doesn't pick these things.

Thanks,
Shameer

Reply via email to