diff options
| author | Vineet Gupta <vgupta@synopsys.com> | 2013-08-23 09:46:34 -0400 |
|---|---|---|
| committer | Vineet Gupta <vgupta@synopsys.com> | 2013-11-06 00:11:45 -0500 |
| commit | 63eca94ca206e342bad4a06a86d8e7eda3053a4e (patch) | |
| tree | 8037367b1c0a2d428ad5add62c842223eb290520 /arch/arc/include/asm | |
| parent | b6fe8e7c0189d017fdba90d1cd134337098c19c3 (diff) | |
ARC: [SMP] ASID allocation
-Track a Per CPU ASID counter
-mm-per-cpu ASID (multiple threads, or mm migrated around)
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/include/asm')
| -rw-r--r-- | arch/arc/include/asm/mmu.h | 2 | ||||
| -rw-r--r-- | arch/arc/include/asm/mmu_context.h | 44 |
2 files changed, 29 insertions, 17 deletions
diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h index c2663b32866b..8c84ae98c337 100644 --- a/arch/arc/include/asm/mmu.h +++ b/arch/arc/include/asm/mmu.h | |||
| @@ -48,7 +48,7 @@ | |||
| 48 | #ifndef __ASSEMBLY__ | 48 | #ifndef __ASSEMBLY__ |
| 49 | 49 | ||
| 50 | typedef struct { | 50 | typedef struct { |
| 51 | unsigned long asid; /* 8 bit MMU PID + Generation cycle */ | 51 | unsigned long asid[NR_CPUS]; /* 8 bit MMU PID + Generation cycle */ |
| 52 | } mm_context_t; | 52 | } mm_context_t; |
| 53 | 53 | ||
| 54 | #ifdef CONFIG_ARC_DBG_TLB_PARANOIA | 54 | #ifdef CONFIG_ARC_DBG_TLB_PARANOIA |
diff --git a/arch/arc/include/asm/mmu_context.h b/arch/arc/include/asm/mmu_context.h index 43a1b51bb8cc..45f06f566b02 100644 --- a/arch/arc/include/asm/mmu_context.h +++ b/arch/arc/include/asm/mmu_context.h | |||
| @@ -30,13 +30,13 @@ | |||
| 30 | * "Fast Context Switch" i.e. no TLB flush on ctxt-switch | 30 | * "Fast Context Switch" i.e. no TLB flush on ctxt-switch |
| 31 | * | 31 | * |
| 32 | * Linux assigns each task a unique ASID. A simple round-robin allocation | 32 | * Linux assigns each task a unique ASID. A simple round-robin allocation |
| 33 | * of H/w ASID is done using software tracker @asid_cache. | 33 | * of H/w ASID is done using software tracker @asid_cpu. |
| 34 | * When it reaches max 255, the allocation cycle starts afresh by flushing | 34 | * When it reaches max 255, the allocation cycle starts afresh by flushing |
| 35 | * the entire TLB and wrapping ASID back to zero. | 35 | * the entire TLB and wrapping ASID back to zero. |
| 36 | * | 36 | * |
| 37 | * A new allocation cycle, post rollover, could potentially reassign an ASID | 37 | * A new allocation cycle, post rollover, could potentially reassign an ASID |
| 38 | * to a different task. Thus the rule is to refresh the ASID in a new cycle. | 38 | * to a different task. Thus the rule is to refresh the ASID in a new cycle. |
| 39 | * The 32 bit @asid_cache (and mm->asid) have 8 bits MMU PID and rest 24 bits | 39 | * The 32 bit @asid_cpu (and mm->asid) have 8 bits MMU PID and rest 24 bits |
| 40 | * serve as cycle/generation indicator and natural 32 bit unsigned math | 40 | * serve as cycle/generation indicator and natural 32 bit unsigned math |
| 41 | * automagically increments the generation when lower 8 bits rollover. | 41 | * automagically increments the generation when lower 8 bits rollover. |
| 42 | */ | 42 | */ |
| @@ -47,9 +47,11 @@ | |||
| 47 | #define MM_CTXT_FIRST_CYCLE (MM_CTXT_ASID_MASK + 1) | 47 | #define MM_CTXT_FIRST_CYCLE (MM_CTXT_ASID_MASK + 1) |
| 48 | #define MM_CTXT_NO_ASID 0UL | 48 | #define MM_CTXT_NO_ASID 0UL |
| 49 | 49 | ||
| 50 | #define hw_pid(mm) (mm->context.asid & MM_CTXT_ASID_MASK) | 50 | #define asid_mm(mm, cpu) mm->context.asid[cpu] |
| 51 | #define hw_pid(mm, cpu) (asid_mm(mm, cpu) & MM_CTXT_ASID_MASK) | ||
| 51 | 52 | ||
| 52 | extern unsigned int asid_cache; | 53 | DECLARE_PER_CPU(unsigned int, asid_cache); |
| 54 | #define asid_cpu(cpu) per_cpu(asid_cache, cpu) | ||
| 53 | 55 | ||
| 54 | /* | 56 | /* |
| 55 | * Get a new ASID if task doesn't have a valid one (unalloc or from prev cycle) | 57 | * Get a new ASID if task doesn't have a valid one (unalloc or from prev cycle) |
| @@ -57,6 +59,7 @@ extern unsigned int asid_cache; | |||
| 57 | */ | 59 | */ |
| 58 | static inline void get_new_mmu_context(struct mm_struct *mm) | 60 | static inline void get_new_mmu_context(struct mm_struct *mm) |
| 59 | { | 61 | { |
| 62 | const unsigned int cpu = smp_processor_id(); | ||
| 60 | unsigned long flags; | 63 | unsigned long flags; |
| 61 | 64 | ||
| 62 | local_irq_save(flags); | 65 | local_irq_save(flags); |
| @@ -71,11 +74,11 @@ static inline void get_new_mmu_context(struct mm_struct *mm) | |||
| 71 | * first need to destroy the context, setting it to invalid | 74 | * first need to destroy the context, setting it to invalid |
| 72 | * value. | 75 | * value. |
| 73 | */ | 76 | */ |
| 74 | if (!((mm->context.asid ^ asid_cache) & MM_CTXT_CYCLE_MASK)) | 77 | if (!((asid_mm(mm, cpu) ^ asid_cpu(cpu)) & MM_CTXT_CYCLE_MASK)) |
| 75 | goto set_hw; | 78 | goto set_hw; |
| 76 | 79 | ||
| 77 | /* move to new ASID and handle rollover */ | 80 | /* move to new ASID and handle rollover */ |
| 78 | if (unlikely(!(++asid_cache & MM_CTXT_ASID_MASK))) { | 81 | if (unlikely(!(++asid_cpu(cpu) & MM_CTXT_ASID_MASK))) { |
| 79 | 82 | ||
| 80 | flush_tlb_all(); | 83 | flush_tlb_all(); |
| 81 | 84 | ||
| @@ -84,15 +87,15 @@ static inline void get_new_mmu_context(struct mm_struct *mm) | |||
| 84 | * If the container itself wrapped around, set it to a non zero | 87 | * If the container itself wrapped around, set it to a non zero |
| 85 | * "generation" to distinguish from no context | 88 | * "generation" to distinguish from no context |
| 86 | */ | 89 | */ |
| 87 | if (!asid_cache) | 90 | if (!asid_cpu(cpu)) |
| 88 | asid_cache = MM_CTXT_FIRST_CYCLE; | 91 | asid_cpu(cpu) = MM_CTXT_FIRST_CYCLE; |
| 89 | } | 92 | } |
| 90 | 93 | ||
| 91 | /* Assign new ASID to tsk */ | 94 | /* Assign new ASID to tsk */ |
| 92 | mm->context.asid = asid_cache; | 95 | asid_mm(mm, cpu) = asid_cpu(cpu); |
| 93 | 96 | ||
| 94 | set_hw: | 97 | set_hw: |
| 95 | write_aux_reg(ARC_REG_PID, hw_pid(mm) | MMU_ENABLE); | 98 | write_aux_reg(ARC_REG_PID, hw_pid(mm, cpu) | MMU_ENABLE); |
| 96 | 99 | ||
| 97 | local_irq_restore(flags); | 100 | local_irq_restore(flags); |
| 98 | } | 101 | } |
| @@ -104,10 +107,24 @@ set_hw: | |||
| 104 | static inline int | 107 | static inline int |
| 105 | init_new_context(struct task_struct *tsk, struct mm_struct *mm) | 108 | init_new_context(struct task_struct *tsk, struct mm_struct *mm) |
| 106 | { | 109 | { |
| 107 | mm->context.asid = MM_CTXT_NO_ASID; | 110 | int i; |
| 111 | |||
| 112 | for_each_possible_cpu(i) | ||
| 113 | asid_mm(mm, i) = MM_CTXT_NO_ASID; | ||
| 114 | |||
| 108 | return 0; | 115 | return 0; |
| 109 | } | 116 | } |
| 110 | 117 | ||
| 118 | static inline void destroy_context(struct mm_struct *mm) | ||
| 119 | { | ||
| 120 | unsigned long flags; | ||
| 121 | |||
| 122 | /* Needed to elide CONFIG_DEBUG_PREEMPT warning */ | ||
| 123 | local_irq_save(flags); | ||
| 124 | asid_mm(mm, smp_processor_id()) = MM_CTXT_NO_ASID; | ||
| 125 | local_irq_restore(flags); | ||
| 126 | } | ||
| 127 | |||
| 111 | /* Prepare the MMU for task: setup PID reg with allocated ASID | 128 | /* Prepare the MMU for task: setup PID reg with allocated ASID |
| 112 | If task doesn't have an ASID (never alloc or stolen, get a new ASID) | 129 | If task doesn't have an ASID (never alloc or stolen, get a new ASID) |
| 113 | */ | 130 | */ |
| @@ -131,11 +148,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | |||
| 131 | */ | 148 | */ |
| 132 | #define activate_mm(prev, next) switch_mm(prev, next, NULL) | 149 | #define activate_mm(prev, next) switch_mm(prev, next, NULL) |
| 133 | 150 | ||
| 134 | static inline void destroy_context(struct mm_struct *mm) | ||
| 135 | { | ||
| 136 | mm->context.asid = MM_CTXT_NO_ASID; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* it seemed that deactivate_mm( ) is a reasonable place to do book-keeping | 151 | /* it seemed that deactivate_mm( ) is a reasonable place to do book-keeping |
| 140 | * for retiring-mm. However destroy_context( ) still needs to do that because | 152 | * for retiring-mm. However destroy_context( ) still needs to do that because |
| 141 | * between mm_release( ) = >deactive_mm( ) and | 153 | * between mm_release( ) = >deactive_mm( ) and |
