Hi Eric,
> -----Original Message-----
> From: Eric Auger <[email protected]>
> Sent: 06 November 2025 17:05
> To: Shameer Kolothum <[email protected]>; Jason Gunthorpe
> <[email protected]>; Nicolin Chen <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> Nathan Chen <[email protected]>; Matt Ochs <[email protected]>;
> [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> Krishnakant Jaju <[email protected]>
> Subject: Re: [PATCH v5 15/32] hw/pci/pci: Introduce optional
> get_msi_address_space() callback
>
[...]
>
> > I have tried to address the “translate” issue below. This introduces a new
> > get_msi_address() callback to retrieve the MSI doorbell address directly
> > from the vIOMMU, so we can drop the existing get_msi_address_space()
> logic.
> > Please take a look and let me know your thoughts.
> >
> > Thanks,
> > Shameer
> >
> > ---
> > hw/arm/smmuv3-accel.c | 10 ++++++++++
> > hw/arm/smmuv3.c | 1 +
> > hw/arm/virt.c | 4 ++++
> > hw/pci/pci.c | 17 +++++++++++++++++
> > include/hw/arm/smmuv3.h | 1 +
> > include/hw/pci/pci.h | 15 +++++++++++++++
> > target/arm/kvm.c | 14 ++++++++++++--
> > 7 files changed, 60 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c
> > index e6c81c4786..8b2a45a915 100644
> > --- a/hw/arm/smmuv3-accel.c
> > +++ b/hw/arm/smmuv3-accel.c
> > @@ -667,6 +667,15 @@ static void
> smmuv3_accel_unset_iommu_device(PCIBus *bus, void *opaque,
> > }
> > }
> >
> > +static uint64_t smmuv3_accel_get_msi_address(PCIBus *bus, void
> *opaque,
> > + int devfn)
> > +{
> > + SMMUState *bs = opaque;
> > + SMMUv3State *s = ARM_SMMUV3(bs);
> > +
> > + g_assert(s->msi_doorbell);
> > + return s->msi_doorbell;
> > +}
> > static AddressSpace *smmuv3_accel_get_msi_as(PCIBus *bus, void
> *opaque,
> > int devfn)
> > {
> > @@ -788,6 +797,7 @@ static const PCIIOMMUOps smmuv3_accel_ops = {
> > .set_iommu_device = smmuv3_accel_set_iommu_device,
> > .unset_iommu_device = smmuv3_accel_unset_iommu_device,
> > .get_msi_address_space = smmuv3_accel_get_msi_as,
> to be removed then
Yes, Of course. Will drop that.
> > + .get_msi_address = smmuv3_accel_get_msi_address,
> > };
> >
> > void smmuv3_accel_idr_override(SMMUv3State *s)
> > diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
> > index 43d297698b..3f2ee8bcce 100644
> > --- a/hw/arm/smmuv3.c
> > +++ b/hw/arm/smmuv3.c
> > @@ -2120,6 +2120,7 @@ static const Property smmuv3_properties[] = {
> > DEFINE_PROP_BOOL("ats", SMMUv3State, ats, false),
> > DEFINE_PROP_UINT8("oas", SMMUv3State, oas, 44),
> > DEFINE_PROP_BOOL("pasid", SMMUv3State, pasid, false),
> > + DEFINE_PROP_UINT64("msi-doorbell", SMMUv3State, msi_doorbell, 0),
> > };
> >
> > static void smmuv3_instance_init(Object *obj)
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index 2498e3beff..d2dcb89235 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -3097,6 +3097,8 @@ static void
> virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
> >
> > create_smmuv3_dev_dtb(vms, dev, bus, errp);
> > if (object_property_get_bool(OBJECT(dev), "accel",
> > &error_abort)) {
> > + hwaddr db_start = base_memmap[VIRT_GIC_ITS].base +
> > + ITS_TRANS_SIZE + GITS_TRANSLATER;
> there are still use cases where you count target GICv2M doorbell so at
> least you would need to add some logic to switch between both
But with KVM, virt doesn't support GICv2 , right?
That reminds me we should probably add a check to see KVM enabled
for SMMUV3 accel=on case.
> > char *stage;
> > stage = object_property_get_str(OBJECT(dev), "stage",
> > &error_fatal);
> > @@ -3107,6 +3109,8 @@ static void
> virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
> > return;
> > }
> > vms->pci_preserve_config = true;
> > + object_property_set_uint(OBJECT(dev), "msi-doorbell",
> > db_start,
> > + &error_abort);
> > }
> > }
> > }
> > diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> > index 1edd711247..45e79a3c23 100644
> > --- a/hw/pci/pci.c
> > +++ b/hw/pci/pci.c
> > @@ -2982,6 +2982,23 @@ AddressSpace
> *pci_device_iommu_address_space(PCIDevice *dev)
> > return &address_space_memory;
> > }
> >
> > +bool pci_device_iommu_msi_direct_address(PCIDevice *dev, hwaddr
> *out_doorbell)
> > +{
> > + PCIBus *bus;
> > + PCIBus *iommu_bus;
> > + int devfn;
> > +
> > + pci_device_get_iommu_bus_devfn(dev, &iommu_bus, &bus, &devfn);
> > + if (iommu_bus) {
> > + if (iommu_bus->iommu_ops->get_msi_address) {
> > + *out_doorbell = iommu_bus->iommu_ops->get_msi_address(bus,
> > + iommu_bus->iommu_opaque, devfn);
> > + return true;
> > + }
> > + }
> > + return false;
> > +}
> > +
> > AddressSpace *pci_device_iommu_msi_address_space(PCIDevice *dev)
> > {
> > PCIBus *bus;
> > diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
> > index ee0b5ed74f..f50d8c72bd 100644
> > --- a/include/hw/arm/smmuv3.h
> > +++ b/include/hw/arm/smmuv3.h
> > @@ -72,6 +72,7 @@ struct SMMUv3State {
> > bool ats;
> > uint8_t oas;
> > bool pasid;
> > + uint64_t msi_doorbell;
> > };
> >
> > typedef enum {
> > diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> > index b731443c67..e1709b0bfe 100644
> > --- a/include/hw/pci/pci.h
> > +++ b/include/hw/pci/pci.h
> > @@ -679,6 +679,20 @@ typedef struct PCIIOMMUOps {
> > */
> > AddressSpace * (*get_msi_address_space)(PCIBus *bus, void *opaque,
> > int devfn);
> > + /**
> > + * @get_msi_address: get the address of MSI doorbell for the device
> (gpa) address
> > + * on a PCI bus.
> > + *
> > + * Optional callback, if implemented must return a valid MSI doorbell
> > + * address.
> > + *
> > + * @bus: the #PCIBus being accessed.
> > + *
> > + * @opaque: the data passed to pci_setup_iommu().
> > + *
> > + * @devfn: device and function number
> > + */
> > + uint64_t (*get_msi_address)(PCIBus *bus, void *opaque, int devfn);
> > } PCIIOMMUOps;
> >
> > bool pci_device_get_iommu_bus_devfn(PCIDevice *dev, PCIBus
> **piommu_bus,
> > @@ -688,6 +702,7 @@ bool pci_device_set_iommu_device(PCIDevice *dev,
> HostIOMMUDevice *hiod,
> > Error **errp);
> > void pci_device_unset_iommu_device(PCIDevice *dev);
> > AddressSpace *pci_device_iommu_msi_address_space(PCIDevice *dev);
> > +bool pci_device_iommu_msi_direct_address(PCIDevice *dev, hwaddr
> *out_doorbell);
> >
> > /**
> > * pci_device_get_viommu_flags: get vIOMMU flags.
> > diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> > index 0df41128d0..8d4d2be0bc 100644
> > --- a/target/arm/kvm.c
> > +++ b/target/arm/kvm.c
> > @@ -1611,35 +1611,45 @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq,
> int level)
> > int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
> > uint64_t address, uint32_t data, PCIDevice
> > *dev)
> > {
> > - AddressSpace *as = pci_device_iommu_msi_address_space(dev);
> > + AddressSpace *as;
> > hwaddr xlat, len, doorbell_gpa;
> > MemoryRegionSection mrs;
> > MemoryRegion *mr;
> >
> > + /* Check if there is a direct msi address available */
> > + if (pci_device_iommu_msi_direct_address(dev, &doorbell_gpa)) {
> > + goto set_doorbell;
> > + }
> > +
> > + as = pci_device_iommu_msi_address_space(dev);
> logically this should be after the test below (ie. meaning we have an
> IOMMU). But this means that you shall use an as which is not the
> address_space_memory.
Ok. I will move it then.
>
> This works but it is not neat either because it totally ignored the
> @address. So you have to build a solid commit msg to explain readers why
> this is needed ;-)
Sure. I will try to do a solid one explaining why we don’t need @address for
this path😊.
Thanks,
Shameer