aboutsummaryrefslogtreecommitdiff
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2015-06-12 12:39:25 +0200
committerJoerg Roedel <jroedel@suse.de>2015-06-16 10:59:35 +0200
commitc3361f2f6e1d64bc7e7b8148bbd1c66b8007a898 (patch)
treee1021d3d5780e43aa1646ecdb8501b24322fa771 /drivers/iommu
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>
Diffstat (limited to 'drivers/iommu')
-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)
unsigned long flags;
u64 rtaddr_reg;
int bus, ret;
- bool ext;
+ bool new_ext, ext;
rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
+ new_ext = !!ecap_ecs(iommu->ecap);
+
+ /*
+ * The RTT bit can only be changed when translation is disabled,
+ * but disabling translation means to open a window for data
+ * corruption. So bail out and don't copy anything if we would
+ * have to change the bit.
+ */
+ if (new_ext != ext)
+ return -EINVAL;
old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
if (!old_rt_phys)