aboutsummaryrefslogtreecommitdiff
path: root/hw/s390x/s390-pci-inst.c
diff options
context:
space:
mode:
authorYi Min Zhao <zyimin@linux.vnet.ibm.com>2015-11-04 15:50:45 +0800
committerCornelia Huck <cornelia.huck@de.ibm.com>2015-12-01 09:57:28 +0100
commitf0a399dbae6a2d0e2e15eb7ce0783286bbd9fe04 (patch)
tree4d1e64b3c672cba3f8b3fddb2a07515d33287f71 /hw/s390x/s390-pci-inst.c
parent567c88c354904d669dfac6170b8ac5f60b41d9bd (diff)
s390x/pci: fix up IOMMU size
Present code uses @size==UINT64_MAX to initialize IOMMU. It infers that it can map any 64-bit IOVA whatsoever. But in fact, the largest DMA range for each PCI Device on s390x is from ZPCI_SDMA_ADDR to ZPCI_EDMA_ADDR. The largest value is returned from hardware, which is to indicate the largest range hardware can support. But the real IOMMU size for specific PCI Device is obtained once qemu intercepts mpcifc instruction that guest is requesting a DMA range for that PCI Device. Therefore, before intercepting mpcifc instruction, qemu cannot be aware of the size of IOMMU region that guest will use. Moreover, iommu replay during device initialization for the whole region in 4k steps takes a very long time. In conclusion, this patch intializes IOMMU region for each PCI Device when intercept mpcifc instruction which is to register DMA range for the PCI Device. And then, destroy IOMMU region when guest wants to deregister IOAT. Signed-off-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Diffstat (limited to 'hw/s390x/s390-pci-inst.c')
-rw-r--r--hw/s390x/s390-pci-inst.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index f9151a9afb..8c1dc82b1f 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -528,7 +528,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
goto out;
}
- mr = pci_device_iommu_address_space(pbdev->pdev)->root;
+ mr = &pbdev->iommu_mr;
while (start < end) {
entry = mr->iommu_ops->translate(mr, start, 0);
@@ -689,6 +689,9 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
pbdev->pba = pba;
pbdev->pal = pal;
pbdev->g_iota = g_iota;
+
+ s390_pcihost_iommu_configure(pbdev, true);
+
return 0;
}
@@ -697,6 +700,8 @@ static void dereg_ioat(S390PCIBusDevice *pbdev)
pbdev->pba = 0;
pbdev->pal = 0;
pbdev->g_iota = 0;
+
+ s390_pcihost_iommu_configure(pbdev, false);
}
int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)