summaryrefslogtreecommitdiff
path: root/hw/spapr_pci.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2012-06-27 14:50:46 +1000
committerAnthony Liguori <aliguori@us.ibm.com>2012-06-27 16:33:26 -0500
commitedded454067bd9bda8a4a2a3ef54ae19474407da (patch)
tree2d04e553becebb144efeb0ca85b53ba45c249bd3 /hw/spapr_pci.c
parent5fa45de5623abd3a6d0b9575a4f014cbfe886b36 (diff)
downloadqemu-edded454067bd9bda8a4a2a3ef54ae19474407da.tar.gz
qemu-edded454067bd9bda8a4a2a3ef54ae19474407da.tar.bz2
qemu-edded454067bd9bda8a4a2a3ef54ae19474407da.zip
pseries: Implement IOMMU and DMA for PAPR PCI devices
Currently the pseries machine emulation does not support DMA for emulated PCI devices, because the PAPR spec always requires a (guest visible, paravirtualized) IOMMU which was not implemented. Now that we have infrastructure for IOMMU emulation, we can correct this and allow PCI DMA for pseries. With the existing PAPR IOMMU code used for VIO devices, this is almost trivial. We use a single DMAContext for each (virtual) PCI host bridge, which is the usual configuration on real PAPR machines (which often have _many_ PCI host bridges). Cc: Alex Graf <agraf@suse.de> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/spapr_pci.c')
-rw-r--r--hw/spapr_pci.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 97d417a997..47ba5ff770 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -266,12 +266,21 @@ static const MemoryRegionOps spapr_io_ops = {
/*
* PHB PCI device
*/
+static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque,
+ int devfn)
+{
+ sPAPRPHBState *phb = opaque;
+
+ return phb->dma;
+}
+
static int spapr_phb_init(SysBusDevice *s)
{
sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s);
char *namebuf;
int i;
PCIBus *bus;
+ uint32_t liobn;
phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid);
namebuf = alloca(strlen(phb->dtbusname) + 32);
@@ -312,6 +321,10 @@ static int spapr_phb_init(SysBusDevice *s)
PCI_DEVFN(0, 0), PCI_NUM_PINS);
phb->host_state.bus = bus;
+ liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
+ phb->dma = spapr_tce_new_dma_context(liobn, 0x40000000);
+ pci_setup_iommu(bus, spapr_pci_dma_context_fn, phb);
+
QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
/* Initialize the LSI table */
@@ -472,6 +485,8 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
_FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
sizeof(interrupt_map)));
+ spapr_dma_dt(fdt, bus_off, "ibm,dma-window", phb->dma);
+
return 0;
}