* Dave Hansen <[email protected]> wrote:

> 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 <[email protected]>
> ---
> 
>  linux.git-davehans/arch/x86/mm/tlb.c             |   18 ++++++++++++++----
>  linux.git-davehans/include/linux/vm_event_item.h |    5 +++++
>  linux.git-davehans/mm/vmstat.c                   |    5 +++++
>  3 files changed, 24 insertions(+), 4 deletions(-)
> 
> diff -puN arch/x86/mm/tlb.c~tlb-vmstats arch/x86/mm/tlb.c
> --- linux.git/arch/x86/mm/tlb.c~tlb-vmstats   2013-07-16 16:41:56.476280350 
> -0700
> +++ linux.git-davehans/arch/x86/mm/tlb.c      2013-07-16 16:41:56.483280658 
> -0700
> @@ -103,6 +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);
>       if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
>               if (f->flush_end == TLB_FLUSH_ALL)
>                       local_flush_tlb();
> @@ -130,6 +131,7 @@ void native_flush_tlb_others(const struc
>       info.flush_start = start;
>       info.flush_end = end;
>  
> +     count_vm_event(NR_TLB_REMOTE_FLUSH);
>       if (is_uv_system()) {
>               unsigned int cpu;
>  
> @@ -149,6 +151,7 @@ void flush_tlb_current_task(void)
>  
>       preempt_disable();
>  
> +     count_vm_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);
> @@ -211,16 +214,19 @@ void flush_tlb_mm_range(struct mm_struct
>       act_entries = mm->total_vm > tlb_entries ? tlb_entries : mm->total_vm;
>  
>       /* tlb_flushall_shift is on balance point, details in commit log */
> -     if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift)
> +     if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift) {
> +             count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
>               local_flush_tlb();
> -     else {
> +     } else {
>               if (has_large_page(mm, start, end)) {
>                       local_flush_tlb();
>                       goto flush_all;
>               }
>               /* flush range by one by one 'invlpg' */
> -             for (addr = start; addr < end;  addr += PAGE_SIZE)
> +             for (addr = start; addr < end;  addr += PAGE_SIZE) {
> +                     count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
>                       __flush_tlb_single(addr);
> +             }
>  
>               if (cpumask_any_but(mm_cpumask(mm),
>                               smp_processor_id()) < nr_cpu_ids)
> @@ -256,6 +262,7 @@ void flush_tlb_page(struct vm_area_struc
>  
>  static void do_flush_tlb_all(void *info)
>  {
> +     count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
>       __flush_tlb_all();
>       if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
>               leave_mm(smp_processor_id());
> @@ -263,6 +270,7 @@ static void do_flush_tlb_all(void *info)
>  
>  void flush_tlb_all(void)
>  {
> +     count_vm_event(NR_TLB_REMOTE_FLUSH);
>       on_each_cpu(do_flush_tlb_all, NULL, 1);
>  }
>  
> @@ -272,8 +280,10 @@ static void do_kernel_range_flush(void *
>       unsigned long addr;
>  
>       /* flush range by one by one 'invlpg' */
> -     for (addr = f->flush_start; addr < f->flush_end; addr += PAGE_SIZE)
> +     for (addr = f->flush_start; addr < f->flush_end; addr += PAGE_SIZE) {
> +             count_vm_event(NR_TLB_LOCAL_FLUSH_ONE_KERNEL);
>               __flush_tlb_single(addr);
> +     }
>  }
>  
>  void flush_tlb_kernel_range(unsigned long start, unsigned long end)
> diff -puN include/linux/vm_event_item.h~tlb-vmstats 
> include/linux/vm_event_item.h
> --- linux.git/include/linux/vm_event_item.h~tlb-vmstats       2013-07-16 
> 16:41:56.478280438 -0700
> +++ linux.git-davehans/include/linux/vm_event_item.h  2013-07-16 
> 16:41:56.483280658 -0700
> @@ -70,6 +70,11 @@ enum vm_event_item { PGPGIN, PGPGOUT, PS
>               THP_ZERO_PAGE_ALLOC,
>               THP_ZERO_PAGE_ALLOC_FAILED,
>  #endif
>
> +             NR_TLB_REMOTE_FLUSH,    /* cpu tried to flush others' tlbs */
> +             NR_TLB_REMOTE_FLUSH_RECEIVED,/* cpu received ipi for flush */
> +             NR_TLB_LOCAL_FLUSH_ALL,
> +             NR_TLB_LOCAL_FLUSH_ONE,
> +             NR_TLB_LOCAL_FLUSH_ONE_KERNEL,

Please fix the vertical alignment of comments.

>               NR_VM_EVENT_ITEMS
>  };
>  
> diff -puN mm/vmstat.c~tlb-vmstats mm/vmstat.c
> --- linux.git/mm/vmstat.c~tlb-vmstats 2013-07-16 16:41:56.480280525 -0700
> +++ linux.git-davehans/mm/vmstat.c    2013-07-16 16:41:56.484280703 -0700
> @@ -817,6 +817,11 @@ const char * const vmstat_text[] = {
>       "thp_zero_page_alloc",
>       "thp_zero_page_alloc_failed",
>  #endif
> +     "nr_tlb_remote_flush",
> +     "nr_tlb_remote_flush_received",
> +     "nr_tlb_local_flush_all",
> +     "nr_tlb_local_flush_one",
> +     "nr_tlb_local_flush_one_kernel",

At first sight this seems pretty x86 specific. No range flush events, etc.

But no strong objections from me, if Andrew likes it.

Thanks,

        Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to