diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2017-04-26 07:38:30 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2017-04-27 08:20:05 -0400 |
commit | cf4f08bed876fbc50e64da92d2e1cfdf7653ddb2 (patch) | |
tree | 40135afefaf8b0d3378f16296c89c4661d8ebfe7 | |
parent | 45b21cfeb22087795f0b49397fbe529efeb99baf (diff) |
powerpc/mm/radix: Optimise Page Walk Cache flush
Currently we implement flushing of the page walk cache (PWC) by calling
_tlbiel_pid() with a RIC (Radix Invalidation Control) value of 1 which says to
only flush the PWC.
But _tlbiel_pid() loops over each set (congruence class) of the TLB, which is
not necessary when we're just flushing the PWC.
In fact the set argument is ignored for a PWC flush, so essentially we're just
flushing the PWC 127 extra times for no benefit.
Fix it by adding tlbiel_pwc() which just does a single flush of the PWC.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
[mpe: Split out of combined patch, drop _ in name, rewrite change log]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r-- | arch/powerpc/mm/tlb-radix.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c index b68b5219cf45..ae2e799822bd 100644 --- a/arch/powerpc/mm/tlb-radix.c +++ b/arch/powerpc/mm/tlb-radix.c | |||
@@ -53,6 +53,17 @@ static inline void _tlbiel_pid(unsigned long pid, unsigned long ric) | |||
53 | asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); | 53 | asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline void tlbiel_pwc(unsigned long pid) | ||
57 | { | ||
58 | asm volatile("ptesync": : :"memory"); | ||
59 | |||
60 | /* For PWC flush, we don't look at set number */ | ||
61 | __tlbiel_pid(pid, 0, RIC_FLUSH_PWC); | ||
62 | |||
63 | asm volatile("ptesync": : :"memory"); | ||
64 | asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); | ||
65 | } | ||
66 | |||
56 | static inline void _tlbie_pid(unsigned long pid, unsigned long ric) | 67 | static inline void _tlbie_pid(unsigned long pid, unsigned long ric) |
57 | { | 68 | { |
58 | unsigned long rb,rs,prs,r; | 69 | unsigned long rb,rs,prs,r; |
@@ -140,7 +151,7 @@ void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr) | |||
140 | 151 | ||
141 | pid = mm->context.id; | 152 | pid = mm->context.id; |
142 | if (pid != MMU_NO_CONTEXT) | 153 | if (pid != MMU_NO_CONTEXT) |
143 | _tlbiel_pid(pid, RIC_FLUSH_PWC); | 154 | tlbiel_pwc(pid); |
144 | 155 | ||
145 | preempt_enable(); | 156 | preempt_enable(); |
146 | } | 157 | } |
@@ -222,7 +233,7 @@ void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr) | |||
222 | if (lock_tlbie) | 233 | if (lock_tlbie) |
223 | raw_spin_unlock(&native_tlbie_lock); | 234 | raw_spin_unlock(&native_tlbie_lock); |
224 | } else | 235 | } else |
225 | _tlbiel_pid(pid, RIC_FLUSH_PWC); | 236 | tlbiel_pwc(pid); |
226 | no_context: | 237 | no_context: |
227 | preempt_enable(); | 238 | preempt_enable(); |
228 | } | 239 | } |