Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit d17d8f9

Browse files
hansendcH. Peter Anvin
authored and
H. Peter Anvin
committed
x86/mm: Add tracepoints for TLB flushes
We don't have any good way to figure out what kinds of flushes are being attempted. Right now, we can try to use the vm counters, but those only tell us what we actually did with the hardware (one-by-one vs full) and don't tell us what was actually _requested_. This allows us to select out "interesting" TLB flushes that we might want to optimize (like the ranged ones) and ignore the ones that we have very little control over (the ones at context switch). Signed-off-by: Dave Hansen <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Acked-by: Rik van Riel <[email protected]> Cc: Mel Gorman <[email protected]> Signed-off-by: H. Peter Anvin <[email protected]>
1 parent a23421f commit d17d8f9

File tree

5 files changed

+70
-2
lines changed

5 files changed

+70
-2
lines changed

Diff for: arch/x86/include/asm/mmu_context.h

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
#include <asm/desc.h>
55
#include <linux/atomic.h>
6+
#include <linux/mm_types.h>
7+
8+
#include <trace/events/tlb.h>
9+
610
#include <asm/pgalloc.h>
711
#include <asm/tlbflush.h>
812
#include <asm/paravirt.h>
@@ -44,6 +48,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
4448

4549
/* Re-load page tables */
4650
load_cr3(next->pgd);
51+
trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
4752

4853
/* Stop flush ipis for the previous mm */
4954
cpumask_clear_cpu(cpu, mm_cpumask(prev));
@@ -71,6 +76,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
7176
* to make sure to use no freed page tables.
7277
*/
7378
load_cr3(next->pgd);
79+
trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
7480
load_LDT_nolock(&next->context);
7581
}
7682
}

Diff for: arch/x86/mm/init.c

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
#include <asm/dma.h> /* for MAX_DMA_PFN */
1919
#include <asm/microcode.h>
2020

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+
2128
#include "mm_internal.h"
2229

2330
static unsigned long __initdata pgt_buf_start;

Diff for: arch/x86/mm/tlb.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ void leave_mm(int cpu)
4949
if (cpumask_test_cpu(cpu, mm_cpumask(active_mm))) {
5050
cpumask_clear_cpu(cpu, mm_cpumask(active_mm));
5151
load_cr3(swapper_pg_dir);
52+
trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
5253
}
5354
}
5455
EXPORT_SYMBOL_GPL(leave_mm);
@@ -107,15 +108,19 @@ static void flush_tlb_func(void *info)
107108

108109
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
109110
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) {
111112
local_flush_tlb();
112-
else {
113+
trace_tlb_flush(TLB_REMOTE_SHOOTDOWN, TLB_FLUSH_ALL);
114+
} else {
113115
unsigned long addr;
116+
unsigned long nr_pages =
117+
f->flush_end - f->flush_start / PAGE_SIZE;
114118
addr = f->flush_start;
115119
while (addr < f->flush_end) {
116120
__flush_tlb_single(addr);
117121
addr += PAGE_SIZE;
118122
}
123+
trace_tlb_flush(TLB_REMOTE_SHOOTDOWN, nr_pages);
119124
}
120125
} else
121126
leave_mm(smp_processor_id());
@@ -153,6 +158,7 @@ void flush_tlb_current_task(void)
153158

154159
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
155160
local_flush_tlb();
161+
trace_tlb_flush(TLB_LOCAL_SHOOTDOWN, TLB_FLUSH_ALL);
156162
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
157163
flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
158164
preempt_enable();
@@ -191,6 +197,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
191197
__flush_tlb_single(addr);
192198
}
193199
}
200+
trace_tlb_flush(TLB_LOCAL_MM_SHOOTDOWN, base_pages_to_flush);
194201
out:
195202
if (base_pages_to_flush == TLB_FLUSH_ALL) {
196203
start = 0UL;

Diff for: include/linux/mm_types.h

+8
Original file line numberDiff line numberDiff line change
@@ -516,4 +516,12 @@ struct vm_special_mapping
516516
struct page **pages;
517517
};
518518

519+
enum 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+
519527
#endif /* _LINUX_MM_TYPES_H */

Diff for: include/trace/events/tlb.h

+40
Original file line numberDiff line numberDiff line change
@@ -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+
16+
TRACE_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>

0 commit comments

Comments
 (0)