diff mbox

[v3,22/23] pci: give each device its own address space

Message ID 1349800368-15228-23-git-send-email-avi@redhat.com
State New
Headers show

Commit Message

Avi Kivity Oct. 9, 2012, 4:32 p.m. UTC
Accesses from different devices can resolve differently
(depending on bridge settings, iommus, and PCI_COMMAND_MASTER), so
set up an address space for each device.

Currently iommus are expressed outside the memory API, so this doesn't
work if an iommu is present.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pci.c | 14 ++++++++++++++
 hw/pci.h |  1 +
 2 files changed, 15 insertions(+)
diff mbox

Patch

diff --git a/hw/pci.c b/hw/pci.c
index f855cf3..8e8e030 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -33,6 +33,7 @@ 
 #include "qmp-commands.h"
 #include "msi.h"
 #include "msix.h"
+#include "exec-memory.h"
 
 //#define DEBUG_PCI
 #ifdef DEBUG_PCI
@@ -777,6 +778,13 @@  static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pci_dev->bus = bus;
     if (bus->dma_context_fn) {
         pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn);
+    } else {
+        /* FIXME: Make dma_context_fn use MemoryRegions instead, so this path is
+         * taken unconditionally */
+        /* FIXME: inherit memory region from bus creator */
+        address_space_init(&pci_dev->bus_master_as, get_system_memory());
+        pci_dev->dma = g_new(DMAContext, 1);
+        dma_context_init(pci_dev->dma, &pci_dev->bus_master_as, NULL, NULL, NULL);
     }
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
@@ -830,6 +838,12 @@  static void do_pci_unregister_device(PCIDevice *pci_dev)
     qemu_free_irqs(pci_dev->irq);
     pci_dev->bus->devices[pci_dev->devfn] = NULL;
     pci_config_free(pci_dev);
+
+    if (!pci_dev->bus->dma_context_fn) {
+        address_space_destroy(&pci_dev->bus_master_as);
+        g_free(pci_dev->dma);
+        pci_dev->dma = NULL;
+    }
 }
 
 static void pci_unregister_io_regions(PCIDevice *pci_dev)
diff --git a/hw/pci.h b/hw/pci.h
index 4b6ab3d..3192d81 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -211,6 +211,7 @@  struct PCIDevice {
     int32_t devfn;
     char name[64];
     PCIIORegion io_regions[PCI_NUM_REGIONS];
+    AddressSpace bus_master_as;
     DMAContext *dma;
 
     /* do not access the following fields */