Skip to content

Commit

Permalink
mm, x86: Account for TLB flushes only when debugging
Browse files Browse the repository at this point in the history
Bisection between 3.11 and 3.12 fingered commit 9824cf9 ("mm:
vmstats: tlb flush counters") to cause overhead problems.

The counters are undeniably useful but how often do we really
need to debug TLB flush related issues?  It does not justify
taking the penalty everywhere so make it a debugging option.

Signed-off-by: Mel Gorman <[email protected]>
Tested-by: Davidlohr Bueso <[email protected]>
Reviewed-by: Rik van Riel <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: Alex Shi <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
Mel Gorman authored and Ingo Molnar committed Jan 25, 2014
1 parent 2993ae3 commit ec65993
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 14 deletions.
6 changes: 3 additions & 3 deletions arch/x86/include/asm/tlbflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static inline void __flush_tlb_all(void)

static inline void __flush_tlb_one(unsigned long addr)
{
count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE);
__flush_tlb_single(addr);
}

Expand Down Expand Up @@ -93,13 +93,13 @@ static inline void __flush_tlb_one(unsigned long addr)
*/
static inline void __flush_tlb_up(void)
{
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
__flush_tlb();
}

static inline void flush_tlb_all(void)
{
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
__flush_tlb_all();
}

Expand Down
4 changes: 2 additions & 2 deletions arch/x86/kernel/cpu/mtrr/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
}

/* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
__flush_tlb();

/* Save MTRR state */
Expand All @@ -697,7 +697,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
static void post_set(void) __releases(set_atomicity_lock)
{
/* Flush TLBs (no need to flush caches - they are disabled) */
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
__flush_tlb();

/* Intel (P6) standard MTRRs */
Expand Down
14 changes: 7 additions & 7 deletions arch/x86/mm/tlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ static void flush_tlb_func(void *info)
if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
return;

count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
if (f->flush_end == TLB_FLUSH_ALL)
local_flush_tlb();
Expand Down Expand Up @@ -131,7 +131,7 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
info.flush_start = start;
info.flush_end = end;

count_vm_event(NR_TLB_REMOTE_FLUSH);
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH);
if (is_uv_system()) {
unsigned int cpu;

Expand All @@ -151,7 +151,7 @@ void flush_tlb_current_task(void)

preempt_disable();

count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
local_flush_tlb();
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
Expand Down Expand Up @@ -215,7 +215,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,

/* tlb_flushall_shift is on balance point, details in commit log */
if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift) {
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
local_flush_tlb();
} else {
if (has_large_page(mm, start, end)) {
Expand All @@ -224,7 +224,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
}
/* flush range by one by one 'invlpg' */
for (addr = start; addr < end; addr += PAGE_SIZE) {
count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE);
__flush_tlb_single(addr);
}

Expand Down Expand Up @@ -262,15 +262,15 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start)

static void do_flush_tlb_all(void *info)
{
count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
__flush_tlb_all();
if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
leave_mm(smp_processor_id());
}

void flush_tlb_all(void)
{
count_vm_event(NR_TLB_REMOTE_FLUSH);
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH);
on_each_cpu(do_flush_tlb_all, NULL, 1);
}

Expand Down
4 changes: 3 additions & 1 deletion include/linux/vm_event_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
THP_ZERO_PAGE_ALLOC,
THP_ZERO_PAGE_ALLOC_FAILED,
#endif
#ifdef CONFIG_DEBUG_TLBFLUSH
#ifdef CONFIG_SMP
NR_TLB_REMOTE_FLUSH, /* cpu tried to flush others' tlbs */
NR_TLB_REMOTE_FLUSH_RECEIVED,/* cpu received ipi for flush */
#endif
#endif /* CONFIG_SMP */
NR_TLB_LOCAL_FLUSH_ALL,
NR_TLB_LOCAL_FLUSH_ONE,
#endif /* CONFIG_DEBUG_TLBFLUSH */
NR_VM_EVENT_ITEMS
};

Expand Down
8 changes: 8 additions & 0 deletions include/linux/vmstat.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ static inline void vm_events_fold_cpu(int cpu)
#define count_vm_numa_events(x, y) do { (void)(y); } while (0)
#endif /* CONFIG_NUMA_BALANCING */

#ifdef CONFIG_DEBUG_TLBFLUSH
#define count_vm_tlb_event(x) count_vm_event(x)
#define count_vm_tlb_events(x, y) count_vm_events(x, y)
#else
#define count_vm_tlb_event(x) do {} while (0)
#define count_vm_tlb_events(x, y) do { (void)(y); } while (0)
#endif

#define __count_zone_vm_events(item, zone, delta) \
__count_vm_events(item##_NORMAL - ZONE_NORMAL + \
zone_idx(zone), delta)
Expand Down
4 changes: 3 additions & 1 deletion mm/vmstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -851,12 +851,14 @@ const char * const vmstat_text[] = {
"thp_zero_page_alloc",
"thp_zero_page_alloc_failed",
#endif
#ifdef CONFIG_DEBUG_TLBFLUSH
#ifdef CONFIG_SMP
"nr_tlb_remote_flush",
"nr_tlb_remote_flush_received",
#endif
#endif /* CONFIG_SMP */
"nr_tlb_local_flush_all",
"nr_tlb_local_flush_one",
#endif /* CONFIG_DEBUG_TLBFLUSH */

#endif /* CONFIG_VM_EVENTS_COUNTERS */
};
Expand Down

0 comments on commit ec65993

Please sign in to comment.