diff options
author | Chintan Pandya <cpandya@codeaurora.org> | 2014-04-14 15:33:02 +0530 |
---|---|---|
committer | Chintan Pandya <cpandya@codeaurora.org> | 2014-04-21 16:49:47 +0530 |
commit | 801142a29e986e2b8432e2042c979b88345a696c (patch) | |
tree | 7010e11f68523051b4b747ca08184b87286bddf7 /drivers/iommu | |
parent | 0be30916e61c6c22a23cc73e7d02b6f97009d52f (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.c | 3 | ||||
-rw-r--r-- | drivers/iommu/msm_iommu_pagetable_lpae.c | 5 |
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; |