This patch adds pci_device_iommu_context() to get an iommu_context for a given device. A new callback is added in PCIIOMMUOps. Users who wants to listen to events issued by vIOMMU could use this new interface to get an iommu_context and register their own notifiers, then wait for notifications from vIOMMU. e.g. VFIO is the first user of it to listen to the PASID_ALLOC/PASID_BIND/CACHE_INV events and propagate the events to host. Cc: Kevin Tian <kevin.tian@xxxxxxxxx> Cc: Jacob Pan <jacob.jun.pan@xxxxxxxxxxxxxxx> Cc: Peter Xu <peterx@xxxxxxxxxx> Cc: Eric Auger <eric.auger@xxxxxxxxxx> Cc: Yi Sun <yi.y.sun@xxxxxxxxxxxxxxx> Cc: David Gibson <david@xxxxxxxxxxxxxxxxxxxxx> Signed-off-by: Liu Yi L <yi.l.liu@xxxxxxxxx> --- hw/pci/pci.c | 16 ++++++++++++++++ include/hw/pci/pci.h | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index b5ce9ca..4e6af06 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2625,6 +2625,22 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) return &address_space_memory; } +IOMMUContext *pci_device_iommu_context(PCIDevice *dev) +{ + PCIBus *bus = pci_get_bus(dev); + PCIBus *iommu_bus = bus; + + while (iommu_bus && !iommu_bus->iommu_ops && iommu_bus->parent_dev) { + iommu_bus = pci_get_bus(iommu_bus->parent_dev); + } + if (iommu_bus && iommu_bus->iommu_ops && + iommu_bus->iommu_ops->get_iommu_context) { + return iommu_bus->iommu_ops->get_iommu_context(bus, + iommu_bus->iommu_opaque, dev->devfn); + } + return NULL; +} + void pci_setup_iommu(PCIBus *bus, const PCIIOMMUOps *ops, void *opaque) { bus->iommu_ops = ops; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index d9fed8d..ccada47 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -9,6 +9,8 @@ #include "hw/pci/pcie.h" +#include "hw/iommu/iommu.h" + extern bool pci_available; /* PCI bus */ @@ -484,9 +486,12 @@ typedef struct PCIIOMMUOps PCIIOMMUOps; struct PCIIOMMUOps { AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int32_t devfn); + IOMMUContext * (*get_iommu_context)(PCIBus *bus, + void *opaque, int32_t devfn); }; AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); +IOMMUContext *pci_device_iommu_context(PCIDevice *dev); void pci_setup_iommu(PCIBus *bus, const PCIIOMMUOps *iommu_ops, void *opaque); static inline void -- 2.7.4