Message ID | 20240603061023.269738-16-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: > From: Yi Liu <yi.l.liu@intel.com> > > pci_device_[set|unset]_iommu_device() call pci_device_get_iommu_bus_devfn() > to get iommu_bus->iommu_ops and call [set|unset]_iommu_device callback to > set/unset HostIOMMUDevice for a given PCI device. > > 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> > --- > include/hw/pci/pci.h | 38 +++++++++++++++++++++++++++++++++++++- > hw/pci/pci.c | 27 +++++++++++++++++++++++++++ > 2 files changed, 64 insertions(+), 1 deletion(-) > > diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h > index eaa3fc99d8..c84cc9b99a 100644 > --- a/include/hw/pci/pci.h > +++ b/include/hw/pci/pci.h > @@ -3,6 +3,7 @@ > > #include "exec/memory.h" > #include "sysemu/dma.h" > +#include "sysemu/host_iommu_device.h" > > /* PCI includes legacy ISA access. */ > #include "hw/isa/isa.h" > @@ -383,10 +384,45 @@ typedef struct PCIIOMMUOps { > * > * @devfn: device and function number > */ > - AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int devfn); > + AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int devfn); > + /** > + * @set_iommu_device: attach a HostIOMMUDevice to a vIOMMU > + * > + * Optional callback, if not implemented in vIOMMU, then vIOMMU can't > + * retrieve host information from the associated HostIOMMUDevice. > + * > + * @bus: the #PCIBus of the PCI device. > + * > + * @opaque: the data passed to pci_setup_iommu(). > + * > + * @devfn: device and function number of the PCI device. > + * > + * @dev: the data structure representing host IOMMU device. the #HostIOMMUDevice to attach? > + * > + * @errp: pass an Error out only when return false > + * > + * Returns: true if HostIOMMUDevice is attached or else false with errp set. > + */ > + bool (*set_iommu_device)(PCIBus *bus, void *opaque, int devfn, > + HostIOMMUDevice *dev, Error **errp); > + /** > + * @unset_iommu_device: detach a HostIOMMUDevice from a vIOMMU > + * > + * Optional callback. > + * > + * @bus: the #PCIBus of the PCI device. > + * > + * @opaque: the data passed to pci_setup_iommu(). > + * > + * @devfn: device and function number of the PCI device. > + */ > + void (*unset_iommu_device)(PCIBus *bus, void *opaque, int devfn); > } PCIIOMMUOps; > > AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); > +bool pci_device_set_iommu_device(PCIDevice *dev, HostIOMMUDevice *hiod, > + Error **errp); > +void pci_device_unset_iommu_device(PCIDevice *dev); > > /** > * pci_setup_iommu: Initialize specific IOMMU handlers for a PCIBus > diff --git a/hw/pci/pci.c b/hw/pci/pci.c > index 02a4bb2af6..c8a8aab306 100644 > --- a/hw/pci/pci.c > +++ b/hw/pci/pci.c > @@ -2742,6 +2742,33 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) > return &address_space_memory; > } > > +bool pci_device_set_iommu_device(PCIDevice *dev, HostIOMMUDevice *hiod, > + Error **errp) > +{ > + PCIBus *iommu_bus; > + > + /* set_iommu_device requires device's direct BDF instead of aliased BDF */ > + pci_device_get_iommu_bus_devfn(dev, &iommu_bus, NULL, NULL); > + if (iommu_bus && iommu_bus->iommu_ops->set_iommu_device) { > + return iommu_bus->iommu_ops->set_iommu_device(pci_get_bus(dev), > + iommu_bus->iommu_opaque, > + dev->devfn, hiod, errp); > + } > + return true; > +} > + > +void pci_device_unset_iommu_device(PCIDevice *dev) > +{ > + PCIBus *iommu_bus; > + > + pci_device_get_iommu_bus_devfn(dev, &iommu_bus, NULL, NULL); > + if (iommu_bus && iommu_bus->iommu_ops->unset_iommu_device) { > + return iommu_bus->iommu_ops->unset_iommu_device(pci_get_bus(dev), > + iommu_bus->iommu_opaque, > + dev->devfn); > + } > +} > + > void pci_setup_iommu(PCIBus *bus, const PCIIOMMUOps *ops, void *opaque) > { > /* Besides Reviewed-by: Eric Auger <eric.auger@redhat.com> Eric
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index eaa3fc99d8..c84cc9b99a 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -3,6 +3,7 @@ #include "exec/memory.h" #include "sysemu/dma.h" +#include "sysemu/host_iommu_device.h" /* PCI includes legacy ISA access. */ #include "hw/isa/isa.h" @@ -383,10 +384,45 @@ typedef struct PCIIOMMUOps { * * @devfn: device and function number */ - AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int devfn); + AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int devfn); + /** + * @set_iommu_device: attach a HostIOMMUDevice to a vIOMMU + * + * Optional callback, if not implemented in vIOMMU, then vIOMMU can't + * retrieve host information from the associated HostIOMMUDevice. + * + * @bus: the #PCIBus of the PCI device. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @devfn: device and function number of the PCI device. + * + * @dev: the data structure representing host IOMMU device. + * + * @errp: pass an Error out only when return false + * + * Returns: true if HostIOMMUDevice is attached or else false with errp set. + */ + bool (*set_iommu_device)(PCIBus *bus, void *opaque, int devfn, + HostIOMMUDevice *dev, Error **errp); + /** + * @unset_iommu_device: detach a HostIOMMUDevice from a vIOMMU + * + * Optional callback. + * + * @bus: the #PCIBus of the PCI device. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @devfn: device and function number of the PCI device. + */ + void (*unset_iommu_device)(PCIBus *bus, void *opaque, int devfn); } PCIIOMMUOps; AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); +bool pci_device_set_iommu_device(PCIDevice *dev, HostIOMMUDevice *hiod, + Error **errp); +void pci_device_unset_iommu_device(PCIDevice *dev); /** * pci_setup_iommu: Initialize specific IOMMU handlers for a PCIBus diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 02a4bb2af6..c8a8aab306 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2742,6 +2742,33 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) return &address_space_memory; } +bool pci_device_set_iommu_device(PCIDevice *dev, HostIOMMUDevice *hiod, + Error **errp) +{ + PCIBus *iommu_bus; + + /* set_iommu_device requires device's direct BDF instead of aliased BDF */ + pci_device_get_iommu_bus_devfn(dev, &iommu_bus, NULL, NULL); + if (iommu_bus && iommu_bus->iommu_ops->set_iommu_device) { + return iommu_bus->iommu_ops->set_iommu_device(pci_get_bus(dev), + iommu_bus->iommu_opaque, + dev->devfn, hiod, errp); + } + return true; +} + +void pci_device_unset_iommu_device(PCIDevice *dev) +{ + PCIBus *iommu_bus; + + pci_device_get_iommu_bus_devfn(dev, &iommu_bus, NULL, NULL); + if (iommu_bus && iommu_bus->iommu_ops->unset_iommu_device) { + return iommu_bus->iommu_ops->unset_iommu_device(pci_get_bus(dev), + iommu_bus->iommu_opaque, + dev->devfn); + } +} + void pci_setup_iommu(PCIBus *bus, const PCIIOMMUOps *ops, void *opaque) { /*