From: Christoph Lameter (Ampere) Date: Thu, 7 Dec 2023 04:11:49 +0000 (-0800) Subject: ARM64: Add TLB counter diagnostics X-Git-Url: https://gentwo.org/gitweb/?a=commitdiff_plain;h=56fa8277a111771cdee178287b2db7fce8e63d96;p=linux%2F.git ARM64: Add TLB counter diagnostics x86 uses vmstat counters to display tlb statistics. Use these statistics also on ARM64 and add some new variations that we need for the new TLB handling. We add a hacky variant of count_vm_tlb_event() here that we remove later after the tlb handling functions have been moved. After this patch we can see numbers on how the existing tlb flushing operations work. Signed-off-by: Christoph Lameter (Ampere) --- diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug index 265c4461031f..b6ce24db2a6a 100644 --- a/arch/arm64/Kconfig.debug +++ b/arch/arm64/Kconfig.debug @@ -20,4 +20,11 @@ config ARM64_RELOC_TEST depends on m tristate "Relocation testing module" +config DEBUG_TLBFLUSH + bool "Add vmstat counters to analyze TLB handling" + depends on DEBUG_KERNEL + help + This option allows the user to see the TLB flushing behavior in + /proc/vmstat. + source "drivers/hwtracing/coresight/Kconfig" diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index bb2c2833a987..65144b8d88d4 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -17,6 +17,10 @@ #include #include +/* vmstat.h cannot be include here. We will remove this soon */ +#include +extern void _count_vm_tlb_event(enum vm_event_item); + /* * Raw TLBI operations. * @@ -234,6 +238,7 @@ static inline void local_flush_tlb_all(void) __tlbi(vmalle1); dsb(nsh); isb(); + _count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); } static inline void flush_tlb_all(void) @@ -242,6 +247,7 @@ static inline void flush_tlb_all(void) __tlbi(vmalle1is); dsb(ish); isb(); + _count_vm_tlb_event(NR_TLB_FLUSH_ALL); } static inline void flush_tlb_mm(struct mm_struct *mm) @@ -254,6 +260,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm) __tlbi_user(aside1is, asid); dsb(ish); mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL); + _count_vm_tlb_event(NR_TLB_FLUSH_ALL); } static inline void __flush_tlb_page_nosync(struct mm_struct *mm, @@ -267,6 +274,7 @@ static inline void __flush_tlb_page_nosync(struct mm_struct *mm, __tlbi_user(vale1is, addr); mmu_notifier_arch_invalidate_secondary_tlbs(mm, uaddr & PAGE_MASK, (uaddr & PAGE_MASK) + PAGE_SIZE); + _count_vm_tlb_event(NR_TLB_FLUSH_ONE); } static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, @@ -433,6 +441,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, dsb(ish); mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, start, end); + _count_vm_tlb_event(NR_TLB_FLUSH_RANGE); } static inline void flush_tlb_range(struct vm_area_struct *vma, diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index 188197590fc9..5a06d05251eb 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -420,3 +420,9 @@ static int asids_init(void) return 0; } early_initcall(asids_init); + +void _count_vm_tlb_event(enum vm_event_item x) +{ + count_vm_tlb_event(x); +} + diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h index 8abfa1240040..a490c5f0720a 100644 --- a/include/linux/vm_event_item.h +++ b/include/linux/vm_event_item.h @@ -130,7 +130,12 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, 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_RANGE, NR_TLB_LOCAL_FLUSH_ONE, + NR_TLB_FLUSH_ALL, + NR_TLB_FLUSH_RANGE, + NR_TLB_FLUSH_ONE, + NR_TLB_SKIPPED, #endif /* CONFIG_DEBUG_TLBFLUSH */ #ifdef CONFIG_SWAP SWAP_RA, diff --git a/mm/vmstat.c b/mm/vmstat.c index 359460deb377..8fc2943c69bc 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1385,7 +1385,12 @@ const char * const vmstat_text[] = { "nr_tlb_remote_flush", "nr_tlb_remote_flush_received", "nr_tlb_local_flush_all", + "nr_tlb_local_flush_range", "nr_tlb_local_flush_one", + "nr_tlb_flush_all", + "nr_tlb_flush_range", + "nr_tlb_flush_one", + "nr_tlb_skipped", #endif /* CONFIG_DEBUG_TLBFLUSH */ #ifdef CONFIG_SWAP