This patch extended the current PCI IOMMU functions into operation list, one new op is added to do interrupt remapping.
Currently it is not working since int_remap is always NULL. It only provide a interface to extend PCI MSI to support interrupt remapping in the future. One helper function pci_setup_iommu_ops() is introduced. We can use this instead of the origin pci_setup_iommu() one to extend interrupt remapping on specific platform. Signed-off-by: Peter Xu <[email protected]> --- hw/pci/pci.c | 21 ++++++++++++++++----- include/hw/pci/pci.h | 10 ++++++++++ include/hw/pci/pci_bus.h | 2 +- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 3f58bd4..65046e4 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2404,21 +2404,32 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) PCIBus *bus = PCI_BUS(dev->bus); PCIBus *iommu_bus = bus; - while(iommu_bus && !iommu_bus->iommu_fn && iommu_bus->parent_dev) { + while(iommu_bus && !iommu_bus->iommu_ops.as_lookup && \ + iommu_bus->parent_dev) { iommu_bus = PCI_BUS(iommu_bus->parent_dev->bus); } - if (iommu_bus && iommu_bus->iommu_fn) { - return iommu_bus->iommu_fn(bus, iommu_bus->iommu_opaque, dev->devfn); + if (iommu_bus && iommu_bus->iommu_ops.as_lookup) { + return iommu_bus->iommu_ops.as_lookup(bus, iommu_bus->iommu_opaque, + dev->devfn); } return &address_space_memory; } -void pci_setup_iommu(PCIBus *bus, PCIIOMMUASLookupFunc fn, void *opaque) +void pci_setup_iommu_ops(PCIBus *bus, PCIIOMMUOps *ops, void *opaque) { - bus->iommu_fn = fn; + bus->iommu_ops = *ops; bus->iommu_opaque = opaque; } +void pci_setup_iommu(PCIBus *bus, PCIIOMMUASLookupFunc fn, void *opaque) +{ + PCIIOMMUOps ops = { + .as_lookup = fn, + .int_remap = NULL, + }; + pci_setup_iommu_ops(bus, &ops, opaque); +} + 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 846afee..3636151 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -418,10 +418,20 @@ void pci_bus_get_w64_range(PCIBus *bus, Range *range); void pci_device_deassert_intx(PCIDevice *dev); +/* IOMMU op to find address space for device */ typedef AddressSpace *(*PCIIOMMUASLookupFunc)(PCIBus *, void *, int); +/* IOMMU op to do interrupt remapping */ +typedef int (*PCIIOMMUIntRemapFunc)(void *, MSIMessage *origin, MSIMessage *out); + +struct PCIIOMMUOps { + PCIIOMMUASLookupFunc as_lookup; + PCIIOMMUIntRemapFunc int_remap; +}; +typedef struct PCIIOMMUOps PCIIOMMUOps; AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); void pci_setup_iommu(PCIBus *bus, PCIIOMMUASLookupFunc fn, void *opaque); +void pci_setup_iommu_ops(PCIBus *bus, PCIIOMMUOps *ops, void *opaque); static inline void pci_set_byte(uint8_t *config, uint8_t val) diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index a8ab9c2..034a411 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -20,7 +20,7 @@ typedef struct PCIBusClass { struct PCIBus { BusState qbus; - PCIIOMMUASLookupFunc iommu_fn; + PCIIOMMUOps iommu_ops; void *iommu_opaque; uint8_t devfn_min; pci_set_irq_fn set_irq; -- 2.4.3
