aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2011-05-26 06:23:43 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-05-26 07:14:33 -0400
commit52af9c6cd863fe37d1103035ec7ee22ac1296458 (patch)
treefd6b4e6d7b3bc2881422fb5e735c5b9eda62662a
parentd427958a46af24f75d0017c45eadd172273bbf33 (diff)
ARM: 6943/1: mm: use TTBR1 instead of reserved context ID
On ARMv7 CPUs that cache first level page table entries (like the Cortex-A15), using a reserved ASID while changing the TTBR or flushing the TLB is unsafe. This is because the CPU may cache the first level entry as the result of a speculative memory access while the reserved ASID is assigned. After the process owning the page tables dies, the memory will be reallocated and may be written with junk values which can be interpreted as global, valid PTEs by the processor. This will result in the TLB being populated with bogus global entries. This patch avoids the use of a reserved context ID in the v7 switch_mm and ASID rollover code by temporarily using the swapper_pg_dir pointed at by TTBR1, which contains only global entries that are not tagged with ASIDs. Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mm/context.c11
-rw-r--r--arch/arm/mm/proc-v7.S10
2 files changed, 10 insertions, 11 deletions
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index b0ee9ba3cfab..0d86298c7279 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -24,9 +24,7 @@ DEFINE_PER_CPU(struct mm_struct *, current_mm);
24 24
25/* 25/*
26 * We fork()ed a process, and we need a new context for the child 26 * We fork()ed a process, and we need a new context for the child
27 * to run in. We reserve version 0 for initial tasks so we will 27 * to run in.
28 * always allocate an ASID. The ASID 0 is reserved for the TTBR
29 * register changing sequence.
30 */ 28 */
31void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) 29void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
32{ 30{
@@ -36,8 +34,11 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
36 34
37static void flush_context(void) 35static void flush_context(void)
38{ 36{
39 /* set the reserved ASID before flushing the TLB */ 37 u32 ttb;
40 asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (0)); 38 /* Copy TTBR1 into TTBR0 */
39 asm volatile("mrc p15, 0, %0, c2, c0, 1\n"
40 "mcr p15, 0, %0, c2, c0, 0"
41 : "=r" (ttb));
41 isb(); 42 isb();
42 local_flush_tlb_all(); 43 local_flush_tlb_all();
43 if (icache_is_vivt_asid_tagged()) { 44 if (icache_is_vivt_asid_tagged()) {
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 3c3867850a30..b3b566ec83d3 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -108,18 +108,16 @@ ENTRY(cpu_v7_switch_mm)
108#ifdef CONFIG_ARM_ERRATA_430973 108#ifdef CONFIG_ARM_ERRATA_430973
109 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB 109 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
110#endif 110#endif
111#ifdef CONFIG_ARM_ERRATA_754322 111 mrc p15, 0, r2, c2, c0, 1 @ load TTB 1
112 dsb 112 mcr p15, 0, r2, c2, c0, 0 @ into TTB 0
113#endif
114 mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID
115 isb
1161: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
117 isb 113 isb
118#ifdef CONFIG_ARM_ERRATA_754322 114#ifdef CONFIG_ARM_ERRATA_754322
119 dsb 115 dsb
120#endif 116#endif
121 mcr p15, 0, r1, c13, c0, 1 @ set context ID 117 mcr p15, 0, r1, c13, c0, 1 @ set context ID
122 isb 118 isb
119 mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
120 isb
123#endif 121#endif
124 mov pc, lr 122 mov pc, lr
125ENDPROC(cpu_v7_switch_mm) 123ENDPROC(cpu_v7_switch_mm)