diff options
Diffstat (limited to 'arch/arm/mm/context.c')
-rw-r--r-- | arch/arm/mm/context.c | 17 |
1 files changed, 8 insertions, 9 deletions
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 8bfae964b133..b0ee9ba3cfab 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c | |||
@@ -24,7 +24,9 @@ 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. | 27 | * to run in. We reserve version 0 for initial tasks so we will |
28 | * always allocate an ASID. The ASID 0 is reserved for the TTBR | ||
29 | * register changing sequence. | ||
28 | */ | 30 | */ |
29 | void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) | 31 | void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) |
30 | { | 32 | { |
@@ -34,11 +36,8 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) | |||
34 | 36 | ||
35 | static void flush_context(void) | 37 | static void flush_context(void) |
36 | { | 38 | { |
37 | u32 ttb; | 39 | /* set the reserved ASID before flushing the TLB */ |
38 | /* Copy TTBR1 into TTBR0 */ | 40 | asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (0)); |
39 | asm volatile("mrc p15, 0, %0, c2, c0, 1\n" | ||
40 | "mcr p15, 0, %0, c2, c0, 0" | ||
41 | : "=r" (ttb)); | ||
42 | isb(); | 41 | isb(); |
43 | local_flush_tlb_all(); | 42 | local_flush_tlb_all(); |
44 | if (icache_is_vivt_asid_tagged()) { | 43 | if (icache_is_vivt_asid_tagged()) { |
@@ -94,7 +93,7 @@ static void reset_context(void *info) | |||
94 | return; | 93 | return; |
95 | 94 | ||
96 | smp_rmb(); | 95 | smp_rmb(); |
97 | asid = cpu_last_asid + cpu; | 96 | asid = cpu_last_asid + cpu + 1; |
98 | 97 | ||
99 | flush_context(); | 98 | flush_context(); |
100 | set_mm_context(mm, asid); | 99 | set_mm_context(mm, asid); |
@@ -144,13 +143,13 @@ void __new_context(struct mm_struct *mm) | |||
144 | * to start a new version and flush the TLB. | 143 | * to start a new version and flush the TLB. |
145 | */ | 144 | */ |
146 | if (unlikely((asid & ~ASID_MASK) == 0)) { | 145 | if (unlikely((asid & ~ASID_MASK) == 0)) { |
147 | asid = cpu_last_asid + smp_processor_id(); | 146 | asid = cpu_last_asid + smp_processor_id() + 1; |
148 | flush_context(); | 147 | flush_context(); |
149 | #ifdef CONFIG_SMP | 148 | #ifdef CONFIG_SMP |
150 | smp_wmb(); | 149 | smp_wmb(); |
151 | smp_call_function(reset_context, NULL, 1); | 150 | smp_call_function(reset_context, NULL, 1); |
152 | #endif | 151 | #endif |
153 | cpu_last_asid += NR_CPUS - 1; | 152 | cpu_last_asid += NR_CPUS; |
154 | } | 153 | } |
155 | 154 | ||
156 | set_mm_context(mm, asid); | 155 | set_mm_context(mm, asid); |