summaryrefslogtreecommitdiff
path: root/drivers/iommu
diff options
context:
space:
mode:
authorChintan Pandya <cpandya@codeaurora.org>2014-04-14 15:33:02 +0530
committerChintan Pandya <cpandya@codeaurora.org>2014-04-21 16:49:47 +0530
commit801142a29e986e2b8432e2042c979b88345a696c (patch)
tree7010e11f68523051b4b747ca08184b87286bddf7 /drivers/iommu
parent0be30916e61c6c22a23cc73e7d02b6f97009d52f (diff)
iommu: msm: Workaround for SMMU PTE prefetch HW bug
Some SMMU implementation has speculative pre-fetch to optimize performance by reducing HTW to DDR. MMU-500 also implements such pre-fetching with a limitation that it cannot identify when to stop pre-fetching. This results into pre-fetching junk data after the last PTE from last level of page table. This junk PTE can result into any SMMU issues like incorrect translation, permission fault, page fault etc. Now, to avoid that, we anyway do memset 0 to the entire page allocated to page table. But we flush only those entries to DDR which are part of valid mapping. Any data after the valid page table entries may not be set to zero as we don't issue explicit flush for them. And this results into the problem described above. Do an explicit flush for few guard page table entries and make sure that they reflect 0 in DDR. This stops SMMU to do over pre-fetch. CRs-Fixed: 644219 Change-Id: I4695e50e14d6122356090118e15311797ad5e290 Signed-off-by: Chintan Pandya <cpandya@codeaurora.org>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/msm_iommu_pagetable.c3
-rw-r--r--drivers/iommu/msm_iommu_pagetable_lpae.c5
2 files changed, 5 insertions, 3 deletions
diff --git a/drivers/iommu/msm_iommu_pagetable.c b/drivers/iommu/msm_iommu_pagetable.c
index 797a2214e644..3f86de5af139 100644
--- a/drivers/iommu/msm_iommu_pagetable.c
+++ b/drivers/iommu/msm_iommu_pagetable.c
@@ -26,6 +26,7 @@
#define NUM_FL_PTE 4096
#define NUM_SL_PTE 256
+#define GUARD_PTE 2
#define NUM_TEX_CLASS 8
/* First-level page table bits */
@@ -173,7 +174,7 @@ static u32 *make_second_level(struct msm_iommu_pt *pt,
goto fail;
}
memset(sl, 0, SZ_4K);
- clean_pte(sl, sl + NUM_SL_PTE, pt->redirect);
+ clean_pte(sl, sl + NUM_SL_PTE + GUARD_PTE, pt->redirect);
*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | \
FL_TYPE_TABLE);
diff --git a/drivers/iommu/msm_iommu_pagetable_lpae.c b/drivers/iommu/msm_iommu_pagetable_lpae.c
index 18a4ff6ce3c3..59b4c8484540 100644
--- a/drivers/iommu/msm_iommu_pagetable_lpae.c
+++ b/drivers/iommu/msm_iommu_pagetable_lpae.c
@@ -24,6 +24,7 @@
#define NUM_FL_PTE 4 /* First level */
#define NUM_SL_PTE 512 /* Second level */
#define NUM_TL_PTE 512 /* Third level */
+#define GUARD_PTE 2
#define PTE_SIZE 8
@@ -191,7 +192,7 @@ static inline u64 *make_second_level_tbl(s32 redirect, u64 *fl_pte)
goto fail;
}
memset(sl, 0, SZ_4K);
- clean_pte(sl, sl + NUM_SL_PTE, redirect);
+ clean_pte(sl, sl + NUM_SL_PTE + GUARD_PTE, redirect);
/* Leave APTable bits 0 to let next level decide access permissinons */
*fl_pte = (((phys_addr_t)__pa(sl)) & FLSL_BASE_MASK) | FLSL_TYPE_TABLE;
@@ -209,7 +210,7 @@ static inline u64 *make_third_level_tbl(s32 redirect, u64 *sl_pte)
goto fail;
}
memset(tl, 0, SZ_4K);
- clean_pte(tl, tl + NUM_TL_PTE, redirect);
+ clean_pte(tl, tl + NUM_TL_PTE + GUARD_PTE, redirect);
/* Leave APTable bits 0 to let next level decide access permissions */
*sl_pte = (((phys_addr_t)__pa(tl)) & FLSL_BASE_MASK) | FLSL_TYPE_TABLE;