aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/mmu_context.h6
-rw-r--r--arch/x86/mm/init.c7
-rw-r--r--arch/x86/mm/tlb.c11
-rw-r--r--include/linux/mm_types.h8
-rw-r--r--include/trace/events/tlb.h40
5 files changed, 70 insertions, 2 deletions
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index be12c534fd59..166af2a8e865 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -3,6 +3,10 @@
3 3
4#include <asm/desc.h> 4#include <asm/desc.h>
5#include <linux/atomic.h> 5#include <linux/atomic.h>
6#include <linux/mm_types.h>
7
8#include <trace/events/tlb.h>
9
6#include <asm/pgalloc.h> 10#include <asm/pgalloc.h>
7#include <asm/tlbflush.h> 11#include <asm/tlbflush.h>
8#include <asm/paravirt.h> 12#include <asm/paravirt.h>
@@ -44,6 +48,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
44 48
45 /* Re-load page tables */ 49 /* Re-load page tables */
46 load_cr3(next->pgd); 50 load_cr3(next->pgd);
51 trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
47 52
48 /* Stop flush ipis for the previous mm */ 53 /* Stop flush ipis for the previous mm */
49 cpumask_clear_cpu(cpu, mm_cpumask(prev)); 54 cpumask_clear_cpu(cpu, mm_cpumask(prev));
@@ -71,6 +76,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
71 * to make sure to use no freed page tables. 76 * to make sure to use no freed page tables.
72 */ 77 */
73 load_cr3(next->pgd); 78 load_cr3(next->pgd);
79 trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
74 load_LDT_nolock(&next->context); 80 load_LDT_nolock(&next->context);
75 } 81 }
76 } 82 }
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index f97130618113..66dba36f2343 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -18,6 +18,13 @@
18#include <asm/dma.h> /* for MAX_DMA_PFN */ 18#include <asm/dma.h> /* for MAX_DMA_PFN */
19#include <asm/microcode.h> 19#include <asm/microcode.h>
20 20
21/*
22 * We need to define the tracepoints somewhere, and tlb.c
23 * is only compied when SMP=y.
24 */
25#define CREATE_TRACE_POINTS
26#include <trace/events/tlb.h>
27
21#include "mm_internal.h" 28#include "mm_internal.h"
22 29
23static unsigned long __initdata pgt_buf_start; 30static unsigned long __initdata pgt_buf_start;
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index add5a0fc3c5f..6f00ecb9feeb 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -49,6 +49,7 @@ void leave_mm(int cpu)
49 if (cpumask_test_cpu(cpu, mm_cpumask(active_mm))) { 49 if (cpumask_test_cpu(cpu, mm_cpumask(active_mm))) {
50 cpumask_clear_cpu(cpu, mm_cpumask(active_mm)); 50 cpumask_clear_cpu(cpu, mm_cpumask(active_mm));
51 load_cr3(swapper_pg_dir); 51 load_cr3(swapper_pg_dir);
52 trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
52 } 53 }
53} 54}
54EXPORT_SYMBOL_GPL(leave_mm); 55EXPORT_SYMBOL_GPL(leave_mm);
@@ -107,15 +108,19 @@ static void flush_tlb_func(void *info)
107 108
108 count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED); 109 count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
109 if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) { 110 if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
110 if (f->flush_end == TLB_FLUSH_ALL) 111 if (f->flush_end == TLB_FLUSH_ALL) {
111 local_flush_tlb(); 112 local_flush_tlb();
112 else { 113 trace_tlb_flush(TLB_REMOTE_SHOOTDOWN, TLB_FLUSH_ALL);
114 } else {
113 unsigned long addr; 115 unsigned long addr;
116 unsigned long nr_pages =
117 f->flush_end - f->flush_start / PAGE_SIZE;
114 addr = f->flush_start; 118 addr = f->flush_start;
115 while (addr < f->flush_end) { 119 while (addr < f->flush_end) {
116 __flush_tlb_single(addr); 120 __flush_tlb_single(addr);
117 addr += PAGE_SIZE; 121 addr += PAGE_SIZE;
118 } 122 }
123 trace_tlb_flush(TLB_REMOTE_SHOOTDOWN, nr_pages);
119 } 124 }
120 } else 125 } else
121 leave_mm(smp_processor_id()); 126 leave_mm(smp_processor_id());
@@ -153,6 +158,7 @@ void flush_tlb_current_task(void)
153 158
154 count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); 159 count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
155 local_flush_tlb(); 160 local_flush_tlb();
161 trace_tlb_flush(TLB_LOCAL_SHOOTDOWN, TLB_FLUSH_ALL);
156 if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) 162 if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
157 flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); 163 flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
158 preempt_enable(); 164 preempt_enable();
@@ -191,6 +197,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
191 __flush_tlb_single(addr); 197 __flush_tlb_single(addr);
192 } 198 }
193 } 199 }
200 trace_tlb_flush(TLB_LOCAL_MM_SHOOTDOWN, base_pages_to_flush);
194out: 201out:
195 if (base_pages_to_flush == TLB_FLUSH_ALL) { 202 if (base_pages_to_flush == TLB_FLUSH_ALL) {
196 start = 0UL; 203 start = 0UL;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 96c5750e3110..796deac19fcf 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -516,4 +516,12 @@ struct vm_special_mapping
516 struct page **pages; 516 struct page **pages;
517}; 517};
518 518
519enum tlb_flush_reason {
520 TLB_FLUSH_ON_TASK_SWITCH,
521 TLB_REMOTE_SHOOTDOWN,
522 TLB_LOCAL_SHOOTDOWN,
523 TLB_LOCAL_MM_SHOOTDOWN,
524 NR_TLB_FLUSH_REASONS,
525};
526
519#endif /* _LINUX_MM_TYPES_H */ 527#endif /* _LINUX_MM_TYPES_H */
diff --git a/include/trace/events/tlb.h b/include/trace/events/tlb.h
new file mode 100644
index 000000000000..13391d288107
--- /dev/null
+++ b/include/trace/events/tlb.h
@@ -0,0 +1,40 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM tlb
3
4#if !defined(_TRACE_TLB_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_TLB_H
6
7#include <linux/mm_types.h>
8#include <linux/tracepoint.h>
9
10#define TLB_FLUSH_REASON \
11 { TLB_FLUSH_ON_TASK_SWITCH, "flush on task switch" }, \
12 { TLB_REMOTE_SHOOTDOWN, "remote shootdown" }, \
13 { TLB_LOCAL_SHOOTDOWN, "local shootdown" }, \
14 { TLB_LOCAL_MM_SHOOTDOWN, "local mm shootdown" }
15
16TRACE_EVENT(tlb_flush,
17
18 TP_PROTO(int reason, unsigned long pages),
19 TP_ARGS(reason, pages),
20
21 TP_STRUCT__entry(
22 __field( int, reason)
23 __field(unsigned long, pages)
24 ),
25
26 TP_fast_assign(
27 __entry->reason = reason;
28 __entry->pages = pages;
29 ),
30
31 TP_printk("pages:%ld reason:%s (%d)",
32 __entry->pages,
33 __print_symbolic(__entry->reason, TLB_FLUSH_REASON),
34 __entry->reason)
35);
36
37#endif /* _TRACE_TLB_H */
38
39/* This part must be outside protection */
40#include <trace/define_trace.h>