aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Hansen <dave@sr71.net>2013-09-11 17:20:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:57:08 -0400
commit9824cf9753ecbe8f5b47aa9b2f218207defea211 (patch)
tree5baf98172d2f6bedaf83487b04bbeb579be2ff18
parent822518dc56810a0de44cff0f85a227268818749c (diff)
mm: vmstats: tlb flush counters
I was investigating some TLB flush scaling issues and realized that we do not have any good methods for figuring out how many TLB flushes we are doing. It would be nice to be able to do these in generic code, but the arch-independent calls don't explicitly specify whether we actually need to do remote flushes or not. In the end, we really need to know if we actually _did_ global vs. local invalidations, so that leaves us with few options other than to muck with the counters from arch-specific code. Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Ingo Molnar <mingo@elte.hu> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/x86/mm/tlb.c18
-rw-r--r--include/linux/vm_event_item.h5
-rw-r--r--mm/vmstat.c5
3 files changed, 24 insertions, 4 deletions
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 282375f13c7e..f030cbe669a5 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -103,6 +103,7 @@ static void flush_tlb_func(void *info)
103 if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm)) 103 if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
104 return; 104 return;
105 105
106 count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
106 if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) { 107 if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
107 if (f->flush_end == TLB_FLUSH_ALL) 108 if (f->flush_end == TLB_FLUSH_ALL)
108 local_flush_tlb(); 109 local_flush_tlb();
@@ -130,6 +131,7 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
130 info.flush_start = start; 131 info.flush_start = start;
131 info.flush_end = end; 132 info.flush_end = end;
132 133
134 count_vm_event(NR_TLB_REMOTE_FLUSH);
133 if (is_uv_system()) { 135 if (is_uv_system()) {
134 unsigned int cpu; 136 unsigned int cpu;
135 137
@@ -149,6 +151,7 @@ void flush_tlb_current_task(void)
149 151
150 preempt_disable(); 152 preempt_disable();
151 153
154 count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
152 local_flush_tlb(); 155 local_flush_tlb();
153 if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) 156 if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
154 flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); 157 flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
@@ -211,16 +214,19 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
211 act_entries = mm->total_vm > tlb_entries ? tlb_entries : mm->total_vm; 214 act_entries = mm->total_vm > tlb_entries ? tlb_entries : mm->total_vm;
212 215
213 /* tlb_flushall_shift is on balance point, details in commit log */ 216 /* tlb_flushall_shift is on balance point, details in commit log */
214 if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift) 217 if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift) {
218 count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
215 local_flush_tlb(); 219 local_flush_tlb();
216 else { 220 } else {
217 if (has_large_page(mm, start, end)) { 221 if (has_large_page(mm, start, end)) {
218 local_flush_tlb(); 222 local_flush_tlb();
219 goto flush_all; 223 goto flush_all;
220 } 224 }
221 /* flush range by one by one 'invlpg' */ 225 /* flush range by one by one 'invlpg' */
222 for (addr = start; addr < end; addr += PAGE_SIZE) 226 for (addr = start; addr < end; addr += PAGE_SIZE) {
227 count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
223 __flush_tlb_single(addr); 228 __flush_tlb_single(addr);
229 }
224 230
225 if (cpumask_any_but(mm_cpumask(mm), 231 if (cpumask_any_but(mm_cpumask(mm),
226 smp_processor_id()) < nr_cpu_ids) 232 smp_processor_id()) < nr_cpu_ids)
@@ -256,6 +262,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start)
256 262
257static void do_flush_tlb_all(void *info) 263static void do_flush_tlb_all(void *info)
258{ 264{
265 count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
259 __flush_tlb_all(); 266 __flush_tlb_all();
260 if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY) 267 if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
261 leave_mm(smp_processor_id()); 268 leave_mm(smp_processor_id());
@@ -263,6 +270,7 @@ static void do_flush_tlb_all(void *info)
263 270
264void flush_tlb_all(void) 271void flush_tlb_all(void)
265{ 272{
273 count_vm_event(NR_TLB_REMOTE_FLUSH);
266 on_each_cpu(do_flush_tlb_all, NULL, 1); 274 on_each_cpu(do_flush_tlb_all, NULL, 1);
267} 275}
268 276
@@ -272,8 +280,10 @@ static void do_kernel_range_flush(void *info)
272 unsigned long addr; 280 unsigned long addr;
273 281
274 /* flush range by one by one 'invlpg' */ 282 /* flush range by one by one 'invlpg' */
275 for (addr = f->flush_start; addr < f->flush_end; addr += PAGE_SIZE) 283 for (addr = f->flush_start; addr < f->flush_end; addr += PAGE_SIZE) {
284 count_vm_event(NR_TLB_LOCAL_FLUSH_ONE_KERNEL);
276 __flush_tlb_single(addr); 285 __flush_tlb_single(addr);
286 }
277} 287}
278 288
279void flush_tlb_kernel_range(unsigned long start, unsigned long end) 289void flush_tlb_kernel_range(unsigned long start, unsigned long end)
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index bd6cf61142be..dc2cdf07ac14 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -70,6 +70,11 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
70 THP_ZERO_PAGE_ALLOC, 70 THP_ZERO_PAGE_ALLOC,
71 THP_ZERO_PAGE_ALLOC_FAILED, 71 THP_ZERO_PAGE_ALLOC_FAILED,
72#endif 72#endif
73 NR_TLB_REMOTE_FLUSH, /* cpu tried to flush others' tlbs */
74 NR_TLB_REMOTE_FLUSH_RECEIVED,/* cpu received ipi for flush */
75 NR_TLB_LOCAL_FLUSH_ALL,
76 NR_TLB_LOCAL_FLUSH_ONE,
77 NR_TLB_LOCAL_FLUSH_ONE_KERNEL,
73 NR_VM_EVENT_ITEMS 78 NR_VM_EVENT_ITEMS
74}; 79};
75 80
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 20c2ef4458fa..00382c53f582 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -817,6 +817,11 @@ const char * const vmstat_text[] = {
817 "thp_zero_page_alloc", 817 "thp_zero_page_alloc",
818 "thp_zero_page_alloc_failed", 818 "thp_zero_page_alloc_failed",
819#endif 819#endif
820 "nr_tlb_remote_flush",
821 "nr_tlb_remote_flush_received",
822 "nr_tlb_local_flush_all",
823 "nr_tlb_local_flush_one",
824 "nr_tlb_local_flush_one_kernel",
820 825
821#endif /* CONFIG_VM_EVENTS_COUNTERS */ 826#endif /* CONFIG_VM_EVENTS_COUNTERS */
822}; 827};