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); |
