Message ID | 20200320165840.30057-9-eric.auger@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | vSMMUv3/pSMMUv3 2 stage VFIO integration | expand |
Hi Eric, Not sure about your preference. I've modified my patch as below, which HostIOMMUContext to provide callbacks for vIOMMU to call into VFIO. Please feel free to give your suggestions. https://patchwork.ozlabs.org/patch/1259665/ Regards, Yi Liu > From: Eric Auger <eric.auger@redhat.com> > Sent: Saturday, March 21, 2020 12:58 AM > To: eric.auger.pro@gmail.com; eric.auger@redhat.com; qemu-devel@nongnu.org; > Subject: [RFC v6 08/24] pci: introduce PCIPASIDOps to PCIDevice > > From: Liu Yi L <yi.l.liu@intel.com> > > This patch introduces PCIPASIDOps for IOMMU related operations. > > https://lists.gnu.org/archive/html/qemu-devel/2018-03/msg00078.html > https://lists.gnu.org/archive/html/qemu-devel/2018-03/msg00940.html > > So far, to setup virt-SVA for assigned SVA capable device, needs to > configure host translation structures for specific pasid. (e.g. bind > guest page table to host and enable nested translation in host). > Besides, vIOMMU emulator needs to forward guest's cache invalidation > to host since host nested translation is enabled. e.g. on VT-d, guest > owns 1st level translation table, thus cache invalidation for 1st > level should be propagated to host. > > This patch adds two functions: alloc_pasid and free_pasid to support > guest pasid allocation and free. The implementations of the callbacks > would be device passthru modules. Like vfio. > > Cc: Kevin Tian <kevin.tian@intel.com> > Cc: Jacob Pan <jacob.jun.pan@linux.intel.com> > Cc: Peter Xu <peterx@redhat.com> > Cc: Eric Auger <eric.auger@redhat.com> > Cc: Yi Sun <yi.y.sun@linux.intel.com> > Cc: David Gibson <david@gibson.dropbear.id.au> > Signed-off-by: Liu Yi L <yi.l.liu@intel.com> > Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com> > --- > hw/pci/pci.c | 34 ++++++++++++++++++++++++++++++++++ > include/hw/pci/pci.h | 11 +++++++++++ > 2 files changed, 45 insertions(+) > > diff --git a/hw/pci/pci.c b/hw/pci/pci.c > index e1ed6677e1..67e03b8db1 100644 > --- a/hw/pci/pci.c > +++ b/hw/pci/pci.c > @@ -2695,6 +2695,40 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, > void *opaque) > bus->iommu_opaque = opaque; > } > > +void pci_setup_pasid_ops(PCIDevice *dev, PCIPASIDOps *ops) > +{ > + assert(ops && !dev->pasid_ops); > + dev->pasid_ops = ops; > +} > + > +bool pci_device_is_pasid_ops_set(PCIBus *bus, int32_t devfn) > +{ > + PCIDevice *dev; > + > + if (!bus) { > + return false; > + } > + > + dev = bus->devices[devfn]; > + return !!(dev && dev->pasid_ops); > +} > + > +int pci_device_set_pasid_table(PCIBus *bus, int32_t devfn, > + IOMMUConfig *config) > +{ > + PCIDevice *dev; > + > + if (!bus) { > + return -EINVAL; > + } > + > + dev = bus->devices[devfn]; > + if (dev && dev->pasid_ops && dev->pasid_ops->set_pasid_table) { > + return dev->pasid_ops->set_pasid_table(bus, devfn, config); > + } > + return -ENOENT; > +} > + > static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque) > { > Range *range = opaque; > diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h > index cfedf5a995..2146cb7519 100644 > --- a/include/hw/pci/pci.h > +++ b/include/hw/pci/pci.h > @@ -8,6 +8,7 @@ > #include "hw/isa/isa.h" > > #include "hw/pci/pcie.h" > +#include "hw/iommu/iommu.h" > > extern bool pci_available; > > @@ -264,6 +265,11 @@ struct PCIReqIDCache { > }; > typedef struct PCIReqIDCache PCIReqIDCache; > > +struct PCIPASIDOps { > + int (*set_pasid_table)(PCIBus *bus, int32_t devfn, IOMMUConfig *config); > +}; > +typedef struct PCIPASIDOps PCIPASIDOps; > + > struct PCIDevice { > DeviceState qdev; > bool partially_hotplugged; > @@ -357,6 +363,7 @@ struct PCIDevice { > > /* ID of standby device in net_failover pair */ > char *failover_pair_id; > + PCIPASIDOps *pasid_ops; > }; > > void pci_register_bar(PCIDevice *pci_dev, int region_num, > @@ -490,6 +497,10 @@ typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void > *, int); > AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); > void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque); > > +void pci_setup_pasid_ops(PCIDevice *dev, PCIPASIDOps *ops); > +bool pci_device_is_pasid_ops_set(PCIBus *bus, int32_t devfn); > +int pci_device_set_pasid_table(PCIBus *bus, int32_t devfn, IOMMUConfig *config); > + > static inline void > pci_set_byte(uint8_t *config, uint8_t val) > { > -- > 2.20.1
diff --git a/hw/pci/pci.c b/hw/pci/pci.c index e1ed6677e1..67e03b8db1 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2695,6 +2695,40 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque) bus->iommu_opaque = opaque; } +void pci_setup_pasid_ops(PCIDevice *dev, PCIPASIDOps *ops) +{ + assert(ops && !dev->pasid_ops); + dev->pasid_ops = ops; +} + +bool pci_device_is_pasid_ops_set(PCIBus *bus, int32_t devfn) +{ + PCIDevice *dev; + + if (!bus) { + return false; + } + + dev = bus->devices[devfn]; + return !!(dev && dev->pasid_ops); +} + +int pci_device_set_pasid_table(PCIBus *bus, int32_t devfn, + IOMMUConfig *config) +{ + PCIDevice *dev; + + if (!bus) { + return -EINVAL; + } + + dev = bus->devices[devfn]; + if (dev && dev->pasid_ops && dev->pasid_ops->set_pasid_table) { + return dev->pasid_ops->set_pasid_table(bus, devfn, config); + } + return -ENOENT; +} + static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque) { Range *range = opaque; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index cfedf5a995..2146cb7519 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -8,6 +8,7 @@ #include "hw/isa/isa.h" #include "hw/pci/pcie.h" +#include "hw/iommu/iommu.h" extern bool pci_available; @@ -264,6 +265,11 @@ struct PCIReqIDCache { }; typedef struct PCIReqIDCache PCIReqIDCache; +struct PCIPASIDOps { + int (*set_pasid_table)(PCIBus *bus, int32_t devfn, IOMMUConfig *config); +}; +typedef struct PCIPASIDOps PCIPASIDOps; + struct PCIDevice { DeviceState qdev; bool partially_hotplugged; @@ -357,6 +363,7 @@ struct PCIDevice { /* ID of standby device in net_failover pair */ char *failover_pair_id; + PCIPASIDOps *pasid_ops; }; void pci_register_bar(PCIDevice *pci_dev, int region_num, @@ -490,6 +497,10 @@ typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int); AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque); +void pci_setup_pasid_ops(PCIDevice *dev, PCIPASIDOps *ops); +bool pci_device_is_pasid_ops_set(PCIBus *bus, int32_t devfn); +int pci_device_set_pasid_table(PCIBus *bus, int32_t devfn, IOMMUConfig *config); + static inline void pci_set_byte(uint8_t *config, uint8_t val) {