aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Medhurst <tixy@linaro.org>2012-12-11 11:46:19 +0000
committerJon Medhurst <tixy@linaro.org>2012-12-11 11:46:19 +0000
commit7476bb386839769ca52374d16aa94031f06be92e (patch)
tree8ffb600ef2d5a2e3b27ad9834852d2402bf0a6fc
parent1994645ebf0b33333ee7aa3f39aa9c95dc413f99 (diff)
parent18c0835022ae3311b8b243a825d551b0f9680382 (diff)
-rw-r--r--arch/arm/mm/fault.c13
-rw-r--r--arch/arm/mm/idmap.c14
-rw-r--r--arch/arm/mm/proc-v7-2level.S4
-rw-r--r--arch/arm/mm/proc-v7-3level.S4
-rw-r--r--arch/arm/mm/proc-v7.S2
5 files changed, 28 insertions, 9 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 5dbf13f954f6..e207aa5f846f 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -446,8 +446,16 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
if (pud_none(*pud_k))
goto bad_area;
- if (!pud_present(*pud))
+ if (!pud_present(*pud)) {
set_pud(pud, *pud_k);
+ /*
+ * There is a small window during free_pgtables() where the
+ * user *pud entry is 0 but the TLB has not been invalidated
+ * and we get a level 2 (pmd) translation fault caused by the
+ * intermediate TLB caching of the old level 1 (pud) entry.
+ */
+ flush_tlb_kernel_page(addr);
+ }
pmd = pmd_offset(pud, addr);
pmd_k = pmd_offset(pud_k, addr);
@@ -470,8 +478,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
#endif
if (pmd_none(pmd_k[index]))
goto bad_area;
+ if (!pmd_present(pmd[index]))
+ copy_pmd(pmd, pmd_k);
- copy_pmd(pmd, pmd_k);
return 0;
bad_area:
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index ab88ed4f8e08..99db769307ec 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -92,6 +92,9 @@ static int __init init_static_idmap(void)
(long long)idmap_start, (long long)idmap_end);
identity_mapping_add(idmap_pgd, idmap_start, idmap_end);
+ /* Flush L1 for the hardware to see this page table content */
+ flush_cache_louis();
+
return 0;
}
early_initcall(init_static_idmap);
@@ -103,12 +106,15 @@ early_initcall(init_static_idmap);
*/
void setup_mm_for_reboot(void)
{
- /* Clean and invalidate L1. */
- flush_cache_all();
-
/* Switch to the identity mapping. */
cpu_switch_mm(idmap_pgd, &init_mm);
- /* Flush the TLB. */
+#ifdef CONFIG_CPU_HAS_ASID
+ /*
+ * We don't have a clean ASID for the identity mapping, which
+ * may clash with virtual addresses of the previous page tables
+ * and therefore potentially in the TLB.
+ */
local_flush_tlb_all();
+#endif
}
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index fd045e706390..b5ae7b754f9e 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -106,7 +106,9 @@ ENTRY(cpu_v7_set_pte_ext)
ARM( str r3, [r0, #2048]! )
THUMB( add r0, r0, #2048 )
THUMB( str r3, [r0] )
- mcr p15, 0, r0, c7, c10, 1 @ flush_pte
+ mrc p15, 0, r3, c0, c1, 7 @ read ID_MMFR3
+ tst r3, #0xf << 20 @ check the coherent walk bits
+ mcreq p15, 0, r0, c7, c10, 1 @ clean D-cache to PoU
#endif
mov pc, lr
ENDPROC(cpu_v7_set_pte_ext)
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index 8de0f1dd1549..6b306057be9d 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -70,7 +70,9 @@ ENTRY(cpu_v7_set_pte_ext)
tst r3, #1 << (55 - 32) @ L_PTE_DIRTY
orreq r2, #L_PTE_RDONLY
1: strd r2, r3, [r0]
- mcr p15, 0, r0, c7, c10, 1 @ flush_pte
+ mrc p15, 0, r3, c0, c1, 7 @ read ID_MMFR3
+ tst r3, #0xf << 20 @ check the coherent walk bits
+ mcreq p15, 0, r0, c7, c10, 1 @ clean D-cache to PoU
#endif
mov pc, lr
ENDPROC(cpu_v7_set_pte_ext)
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 846d279f3176..42cc833aa02f 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -57,7 +57,7 @@ ENTRY(cpu_v7_reset)
THUMB( bic r1, r1, #1 << 30 ) @ SCTLR.TE (Thumb exceptions)
mcr p15, 0, r1, c1, c0, 0 @ disable MMU
isb
- mov pc, r0
+ bx r0
ENDPROC(cpu_v7_reset)
.popsection