diff options
-rw-r--r-- | hw/spapr.h | 1 | ||||
-rw-r--r-- | hw/spapr_iommu.c | 11 | ||||
-rw-r--r-- | hw/spapr_pci.c | 10 |
3 files changed, 22 insertions, 0 deletions
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 = { |