aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2015-06-12 06:39:25 -0400
committerJoerg Roedel <jroedel@suse.de>2015-06-16 04:59:35 -0400
commitc3361f2f6e1d64bc7e7b8148bbd1c66b8007a898 (patch)
treee1021d3d5780e43aa1646ecdb8501b24322fa771
parenta87f491890e994dca4bee64690d7e5183a19264e (diff)
iommu/vt-d: Don't copy translation tables if RTT bit needs to be changed
We can't change the RTT bit when translation is enabled, so don't copy translation tables when we would change the bit with our new root entry. Tested-by: ZhenHua Li <zhen-hual@hp.com> Tested-by: Baoquan He <bhe@redhat.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/intel-iommu.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 3b32aa55f27c..ca7d37c3981f 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2934,10 +2934,20 @@ static int copy_translation_tables(struct intel_iommu *iommu)
2934 unsigned long flags; 2934 unsigned long flags;
2935 u64 rtaddr_reg; 2935 u64 rtaddr_reg;
2936 int bus, ret; 2936 int bus, ret;
2937 bool ext; 2937 bool new_ext, ext;
2938 2938
2939 rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG); 2939 rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
2940 ext = !!(rtaddr_reg & DMA_RTADDR_RTT); 2940 ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
2941 new_ext = !!ecap_ecs(iommu->ecap);
2942
2943 /*
2944 * The RTT bit can only be changed when translation is disabled,
2945 * but disabling translation means to open a window for data
2946 * corruption. So bail out and don't copy anything if we would
2947 * have to change the bit.
2948 */
2949 if (new_ext != ext)
2950 return -EINVAL;
2941 2951
2942 old_rt_phys = rtaddr_reg & VTD_PAGE_MASK; 2952 old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
2943 if (!old_rt_phys) 2953 if (!old_rt_phys)