Message ID | 20240603061023.269738-15-zhenzhong.duan@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add a host IOMMU device abstraction to check with vIOMMU | expand |
On 6/3/24 08:10, Zhenzhong Duan wrote: > Extract out pci_device_get_iommu_bus_devfn() from > pci_device_iommu_address_space() to facilitate > implementation of pci_device_[set|unset]_iommu_device() > in following patch. > > No functional change intended. > > Signed-off-by: Yi Liu <yi.l.liu@intel.com> > Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com> > Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> > Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Eric > --- > hw/pci/pci.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 45 insertions(+), 3 deletions(-) > > diff --git a/hw/pci/pci.c b/hw/pci/pci.c > index 324c1302d2..02a4bb2af6 100644 > --- a/hw/pci/pci.c > +++ b/hw/pci/pci.c > @@ -2648,11 +2648,27 @@ static void pci_device_class_base_init(ObjectClass *klass, void *data) > } > } > > -AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) > +/* > + * Get IOMMU root bus, aliased bus and devfn of a PCI device > + * > + * IOMMU root bus is needed by all call sites to call into iommu_ops. > + * For call sites which don't need aliased BDF, passing NULL to > + * aliased_[bus|devfn] is allowed. > + * > + * @piommu_bus: return root #PCIBus backed by an IOMMU for the PCI device. > + * > + * @aliased_bus: return aliased #PCIBus of the PCI device, optional. > + * > + * @aliased_devfn: return aliased devfn of the PCI device, optional. > + */ > +static void pci_device_get_iommu_bus_devfn(PCIDevice *dev, > + PCIBus **piommu_bus, > + PCIBus **aliased_bus, > + int *aliased_devfn) > { > PCIBus *bus = pci_get_bus(dev); > PCIBus *iommu_bus = bus; > - uint8_t devfn = dev->devfn; > + int devfn = dev->devfn; > > while (iommu_bus && !iommu_bus->iommu_ops && iommu_bus->parent_dev) { > PCIBus *parent_bus = pci_get_bus(iommu_bus->parent_dev); > @@ -2693,7 +2709,33 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) > > iommu_bus = parent_bus; > } > - if (!pci_bus_bypass_iommu(bus) && iommu_bus->iommu_ops) { > + > + assert(0 <= devfn && devfn < PCI_DEVFN_MAX); > + assert(iommu_bus); > + > + if (pci_bus_bypass_iommu(bus) || !iommu_bus->iommu_ops) { > + iommu_bus = NULL; > + } > + > + *piommu_bus = iommu_bus; > + > + if (aliased_bus) { > + *aliased_bus = bus; > + } > + > + if (aliased_devfn) { > + *aliased_devfn = devfn; > + } > +} > + > +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) > +{ > + PCIBus *bus; > + PCIBus *iommu_bus; > + int devfn; > + > + pci_device_get_iommu_bus_devfn(dev, &iommu_bus, &bus, &devfn); > + if (iommu_bus) { > return iommu_bus->iommu_ops->get_address_space(bus, > iommu_bus->iommu_opaque, devfn); > }
diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 324c1302d2..02a4bb2af6 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2648,11 +2648,27 @@ static void pci_device_class_base_init(ObjectClass *klass, void *data) } } -AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) +/* + * Get IOMMU root bus, aliased bus and devfn of a PCI device + * + * IOMMU root bus is needed by all call sites to call into iommu_ops. + * For call sites which don't need aliased BDF, passing NULL to + * aliased_[bus|devfn] is allowed. + * + * @piommu_bus: return root #PCIBus backed by an IOMMU for the PCI device. + * + * @aliased_bus: return aliased #PCIBus of the PCI device, optional. + * + * @aliased_devfn: return aliased devfn of the PCI device, optional. + */ +static void pci_device_get_iommu_bus_devfn(PCIDevice *dev, + PCIBus **piommu_bus, + PCIBus **aliased_bus, + int *aliased_devfn) { PCIBus *bus = pci_get_bus(dev); PCIBus *iommu_bus = bus; - uint8_t devfn = dev->devfn; + int devfn = dev->devfn; while (iommu_bus && !iommu_bus->iommu_ops && iommu_bus->parent_dev) { PCIBus *parent_bus = pci_get_bus(iommu_bus->parent_dev); @@ -2693,7 +2709,33 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) iommu_bus = parent_bus; } - if (!pci_bus_bypass_iommu(bus) && iommu_bus->iommu_ops) { + + assert(0 <= devfn && devfn < PCI_DEVFN_MAX); + assert(iommu_bus); + + if (pci_bus_bypass_iommu(bus) || !iommu_bus->iommu_ops) { + iommu_bus = NULL; + } + + *piommu_bus = iommu_bus; + + if (aliased_bus) { + *aliased_bus = bus; + } + + if (aliased_devfn) { + *aliased_devfn = devfn; + } +} + +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) +{ + PCIBus *bus; + PCIBus *iommu_bus; + int devfn; + + pci_device_get_iommu_bus_devfn(dev, &iommu_bus, &bus, &devfn); + if (iommu_bus) { return iommu_bus->iommu_ops->get_address_space(bus, iommu_bus->iommu_opaque, devfn); }