diff options
| author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2013-08-10 01:09:08 +1000 |
|---|---|---|
| committer | Michael S. Tsirkin <mst@redhat.com> | 2013-08-27 08:30:48 +0300 |
| commit | 9eda7d373e9c691c070eddcbe3467b991f67f6bd (patch) | |
| tree | 79b9f450dd31dc5ab348b4620ea2852d993181ab /hw/pci/pci.c | |
| parent | 1ae2757c6c4525c9b42f408c86818f843bad7418 (diff) | |
| download | focaccia-qemu-9eda7d373e9c691c070eddcbe3467b991f67f6bd.tar.gz focaccia-qemu-9eda7d373e9c691c070eddcbe3467b991f67f6bd.zip | |
pci: Introduce helper to retrieve a PCI device's DMA address space
A PCI device's DMA address space (possibly an IOMMU) is returned by a method on the PCIBus. At the moment that only has one caller, so the method is simply open coded. We'll need another caller for VFIO, so this patch introduces a helper/wrapper function. If IOMMU is not set, the pci_device_iommu_address_space() function returns the parent's IOMMU skipping the "bus master" address space as otherwise proper emulation would require more effort for no benefit. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> [aik: added inheritance from parent if iommu is not set for the current bus] Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/pci/pci.c')
| -rw-r--r-- | hw/pci/pci.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 4c004f5daa..8c33352c9a 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, } pci_dev->bus = bus; - if (bus->iommu_fn) { - dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn); - } else { - /* FIXME: inherit memory region from bus creator */ - dma_as = &address_space_memory; - } + dma_as = pci_device_iommu_address_space(pci_dev); memory_region_init_alias(&pci_dev->bus_master_enable_region, OBJECT(pci_dev), "bus master", @@ -2239,6 +2234,23 @@ static void pci_device_class_init(ObjectClass *klass, void *data) k->props = pci_props; } +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) +{ + PCIBus *bus = PCI_BUS(dev->bus); + + if (bus->iommu_fn) { + return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn); + } + + if (bus->parent_dev) { + /** We are ignoring the bus master DMA bit of the bridge + * as it would complicate things such as VFIO for no good reason */ + return pci_device_iommu_address_space(bus->parent_dev); + } + + return &address_space_memory; +} + void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque) { bus->iommu_fn = fn; |