From eddeed26ac83392053aef823a341f643ea8e3d2f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:14 +0000 Subject: pseries: Reset emulated PCI TCE tables on system reset The emulated PCI host bridge on the pseries machine incorporates an IOMMU (PAPR TCE table). Currently the mappings in this IOMMU are not cleared when we reset the system. This patch fixes this bug. To do this it adds a new reset function to the IOMMU emulation code. The VIO devices already reset their TCE tables, but they do so by destroying and re-creating their DMA context. This doesn't work for the PCI host bridge, because the infrastructure for PCI IOMMUs has already copied/cached the DMA pointer context into the subordinate PCI device structures. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.h | 1 + hw/spapr_iommu.c | 11 +++++++++++ hw/spapr_pci.c | 10 ++++++++++ 3 files changed, 22 insertions(+) diff --git a/hw/spapr.h b/hw/spapr.h index f1fb646a56..f9a7b0fa33 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -338,6 +338,7 @@ typedef struct sPAPRTCE { void spapr_iommu_init(void); DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size); void spapr_tce_free(DMAContext *dma); +void spapr_tce_reset(DMAContext *dma); int spapr_dma_dt(void *fdt, int node_off, const char *propname, uint32_t liobn, uint64_t window, uint32_t size); int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 53b731773a..216aa06809 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -162,6 +162,17 @@ void spapr_tce_free(DMAContext *dma) } } +void spapr_tce_reset(DMAContext *dma) +{ + if (dma) { + sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma); + size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT) + * sizeof(sPAPRTCE); + + memset(tcet->table, 0, table_size); + } +} + static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, target_ulong tce) { diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 661c05bc30..203155e32b 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -595,6 +595,15 @@ static int spapr_phb_init(SysBusDevice *s) return 0; } +static void spapr_phb_reset(DeviceState *qdev) +{ + SysBusDevice *s = sysbus_from_qdev(qdev); + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s); + + /* Reset the IOMMU state */ + spapr_tce_reset(sphb->dma); +} + static Property spapr_phb_properties[] = { DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0), DEFINE_PROP_STRING("busname", sPAPRPHBState, busname), @@ -613,6 +622,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) sdc->init = spapr_phb_init; dc->props = spapr_phb_properties; + dc->reset = spapr_phb_reset; } static const TypeInfo spapr_phb_info = { -- cgit v1.2.3