diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2012-06-27 14:50:46 +1000 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-06-27 16:33:26 -0500 |
commit | edded454067bd9bda8a4a2a3ef54ae19474407da (patch) | |
tree | 2d04e553becebb144efeb0ca85b53ba45c249bd3 /hw/spapr_iommu.c | |
parent | 5fa45de5623abd3a6d0b9575a4f014cbfe886b36 (diff) |
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_iommu.c')
-rw-r--r-- | hw/spapr_iommu.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 5a769b9f4a..388ffa4b22 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -162,6 +162,22 @@ void spapr_tce_free(DMAContext *dma) } } +static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, + target_ulong tce) +{ + sPAPRTCE *tcep; + + if (ioba >= tcet->window_size) { + hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x" + TARGET_FMT_lx "\n", ioba); + return H_PARAMETER; + } + + tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT); + tcep->tce = tce; + + return H_SUCCESS; +} static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) @@ -170,37 +186,25 @@ static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong ioba = args[1]; target_ulong tce = args[2]; sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn); - sPAPRTCE *tcep; if (liobn & 0xFFFFFFFF00000000ULL) { hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN " TARGET_FMT_lx "\n", liobn); return H_PARAMETER; } - if (!tcet) { - hcall_dprintf("spapr_vio_put_tce on non-existent LIOBN " - TARGET_FMT_lx "\n", liobn); - return H_PARAMETER; - } ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1); + if (tcet) { + return put_tce_emu(tcet, ioba, tce); + } #ifdef DEBUG_TCE - fprintf(stderr, "spapr_vio_put_tce on liobn=" TARGET_FMT_lx /*%s*/ + fprintf(stderr, "%s on liobn=" TARGET_FMT_lx /*%s*/ " ioba 0x" TARGET_FMT_lx " TCE 0x" TARGET_FMT_lx "\n", - liobn, /*dev->qdev.id, */ioba, tce); + __func__, liobn, /*dev->qdev.id, */ioba, tce); #endif - if (ioba >= tcet->window_size) { - hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x" - TARGET_FMT_lx "\n", ioba); - return H_PARAMETER; - } - - tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT); - tcep->tce = tce; - - return H_SUCCESS; + return H_PARAMETER; } void spapr_iommu_init(void) |