diff options
Diffstat (limited to 'arch/x86/mm/tlb.c')
-rw-r--r-- | arch/x86/mm/tlb.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index dd8dda167a24..378fbef279d2 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c | |||
@@ -161,23 +161,24 @@ void flush_tlb_current_task(void) | |||
161 | void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, | 161 | void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, |
162 | unsigned long end, unsigned long vmflag) | 162 | unsigned long end, unsigned long vmflag) |
163 | { | 163 | { |
164 | bool need_flush_others_all = true; | ||
164 | unsigned long addr; | 165 | unsigned long addr; |
165 | unsigned act_entries, tlb_entries = 0; | 166 | unsigned act_entries, tlb_entries = 0; |
166 | unsigned long nr_base_pages; | 167 | unsigned long nr_base_pages; |
167 | 168 | ||
168 | preempt_disable(); | 169 | preempt_disable(); |
169 | if (current->active_mm != mm) | 170 | if (current->active_mm != mm) |
170 | goto flush_all; | 171 | goto out; |
171 | 172 | ||
172 | if (!current->mm) { | 173 | if (!current->mm) { |
173 | leave_mm(smp_processor_id()); | 174 | leave_mm(smp_processor_id()); |
174 | goto flush_all; | 175 | goto out; |
175 | } | 176 | } |
176 | 177 | ||
177 | if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1 | 178 | if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1 |
178 | || vmflag & VM_HUGETLB) { | 179 | || vmflag & VM_HUGETLB) { |
179 | local_flush_tlb(); | 180 | local_flush_tlb(); |
180 | goto flush_all; | 181 | goto out; |
181 | } | 182 | } |
182 | 183 | ||
183 | /* In modern CPU, last level tlb used for both data/ins */ | 184 | /* In modern CPU, last level tlb used for both data/ins */ |
@@ -196,22 +197,20 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, | |||
196 | count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); | 197 | count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); |
197 | local_flush_tlb(); | 198 | local_flush_tlb(); |
198 | } else { | 199 | } else { |
200 | need_flush_others_all = false; | ||
199 | /* flush range by one by one 'invlpg' */ | 201 | /* flush range by one by one 'invlpg' */ |
200 | for (addr = start; addr < end; addr += PAGE_SIZE) { | 202 | for (addr = start; addr < end; addr += PAGE_SIZE) { |
201 | count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE); | 203 | count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE); |
202 | __flush_tlb_single(addr); | 204 | __flush_tlb_single(addr); |
203 | } | 205 | } |
204 | |||
205 | if (cpumask_any_but(mm_cpumask(mm), | ||
206 | smp_processor_id()) < nr_cpu_ids) | ||
207 | flush_tlb_others(mm_cpumask(mm), mm, start, end); | ||
208 | preempt_enable(); | ||
209 | return; | ||
210 | } | 206 | } |
211 | 207 | out: | |
212 | flush_all: | 208 | if (need_flush_others_all) { |
209 | start = 0UL; | ||
210 | end = TLB_FLUSH_ALL; | ||
211 | } | ||
213 | if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) | 212 | if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) |
214 | flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); | 213 | flush_tlb_others(mm_cpumask(mm), mm, start, end); |
215 | preempt_enable(); | 214 | preempt_enable(); |
216 | } | 215 | } |
217 | 216 | ||