diff options
Diffstat (limited to 'arch/arm/mm/context.c')
-rw-r--r-- | arch/arm/mm/context.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index b0ee9ba3cfab..8bfae964b133 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 | */ |
31 | void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) | 29 | void __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 | ||
37 | static void flush_context(void) | 35 | static 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()) { |
@@ -93,7 +94,7 @@ static void reset_context(void *info) | |||
93 | return; | 94 | return; |
94 | 95 | ||
95 | smp_rmb(); | 96 | smp_rmb(); |
96 | asid = cpu_last_asid + cpu + 1; | 97 | asid = cpu_last_asid + cpu; |
97 | 98 | ||
98 | flush_context(); | 99 | flush_context(); |
99 | set_mm_context(mm, asid); | 100 | set_mm_context(mm, asid); |
@@ -143,13 +144,13 @@ void __new_context(struct mm_struct *mm) | |||
143 | * to start a new version and flush the TLB. | 144 | * to start a new version and flush the TLB. |
144 | */ | 145 | */ |
145 | if (unlikely((asid & ~ASID_MASK) == 0)) { | 146 | if (unlikely((asid & ~ASID_MASK) == 0)) { |
146 | asid = cpu_last_asid + smp_processor_id() + 1; | 147 | asid = cpu_last_asid + smp_processor_id(); |
147 | flush_context(); | 148 | flush_context(); |
148 | #ifdef CONFIG_SMP | 149 | #ifdef CONFIG_SMP |
149 | smp_wmb(); | 150 | smp_wmb(); |
150 | smp_call_function(reset_context, NULL, 1); | 151 | smp_call_function(reset_context, NULL, 1); |
151 | #endif | 152 | #endif |
152 | cpu_last_asid += NR_CPUS; | 153 | cpu_last_asid += NR_CPUS - 1; |
153 | } | 154 | } |
154 | 155 | ||
155 | set_mm_context(mm, asid); | 156 | set_mm_context(mm, asid); |