mmu_gather: Remove per arch tlb_{start,end}_vma()
authorPeter Zijlstra <peterz@infradead.org>
Fri, 8 Jul 2022 07:18:03 +0000 (09:18 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Jul 2022 17:50:13 +0000 (10:50 -0700)
Scattered across the archs are 3 basic forms of tlb_{start,end}_vma().
Provide two new MMU_GATHER_knobs to enumerate them and remove the per
arch tlb_{start,end}_vma() implementations.

 - MMU_GATHER_NO_FLUSH_CACHE indicates the arch has flush_cache_range()
   but does *NOT* want to call it for each VMA.

 - MMU_GATHER_MERGE_VMAS indicates the arch wants to merge the
   invalidate across multiple VMAs if possible.

With these it is possible to capture the three forms:

  1) empty stubs;
     select MMU_GATHER_NO_FLUSH_CACHE and MMU_GATHER_MERGE_VMAS

  2) start: flush_cache_range(), end: empty;
     select MMU_GATHER_MERGE_VMAS

  3) start: flush_cache_range(), end: flush_tlb_range();
     default

Obviously, if the architecture does not have flush_cache_range() then
it also doesn't need to select MMU_GATHER_NO_FLUSH_CACHE.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Will Deacon <will@kernel.org>
Cc: David Miller <davem@davemloft.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
13 files changed:
arch/Kconfig
arch/csky/include/asm/tlb.h
arch/loongarch/Kconfig
arch/loongarch/include/asm/tlb.h
arch/powerpc/Kconfig
arch/powerpc/include/asm/tlb.h
arch/s390/Kconfig
arch/s390/include/asm/tlb.h
arch/sparc/Kconfig
arch/sparc/include/asm/tlb_64.h
arch/x86/Kconfig
arch/x86/include/asm/tlb.h
include/asm-generic/tlb.h

index fcf9a41a4ef5b15efaac04bc85c420a435603fb8..71b9272acb28bf0e4f23226954c1d2a3be1fd256 100644 (file)
@@ -438,6 +438,13 @@ config MMU_GATHER_PAGE_SIZE
 
 config MMU_GATHER_NO_RANGE
        bool
+       select MMU_GATHER_MERGE_VMAS
+
+config MMU_GATHER_NO_FLUSH_CACHE
+       bool
+
+config MMU_GATHER_MERGE_VMAS
+       bool
 
 config MMU_GATHER_NO_GATHER
        bool
index 3498e65f59f8eb15e45b24d8dfa9844d4b4cf940..750d041938d8735a7de6e5f726c5cc06fd3567c0 100644 (file)
@@ -4,19 +4,6 @@
 #define __ASM_CSKY_TLB_H
 
 #include <asm/cacheflush.h>
-
-#define tlb_start_vma(tlb, vma) \
-       do { \
-               if (!(tlb)->fullmm) \
-                       flush_cache_range(vma, (vma)->vm_start, (vma)->vm_end); \
-       }  while (0)
-
-#define tlb_end_vma(tlb, vma) \
-       do { \
-               if (!(tlb)->fullmm) \
-                       flush_tlb_range(vma, (vma)->vm_start, (vma)->vm_end); \
-       }  while (0)
-
 #define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
 
 #include <asm-generic/tlb.h>
index 53a912befb626b53bfb866fd63d8b6f62bd25c26..b57daee98b89c0988f200b7d0217350d939fb1f2 100644 (file)
@@ -108,6 +108,7 @@ config LOONGARCH
        select TRACE_IRQFLAGS_SUPPORT
        select USE_PERCPU_NUMA_NODE_ID
        select ZONE_DMA32
+       select MMU_GATHER_MERGE_VMAS if MMU
 
 config 32BIT
        bool
index 4f629ae9d5a9d0609d63e9140bdef3acb75862d6..dd24f5898f651cf9e264c9d6bf23fc8e3190e3ac 100644 (file)
@@ -137,16 +137,6 @@ static inline void invtlb_all(u32 op, u32 info, u64 addr)
                );
 }
 
-/*
- * LoongArch doesn't need any special per-pte or per-vma handling, except
- * we need to flush cache for area to be unmapped.
- */
-#define tlb_start_vma(tlb, vma)                                        \
-       do {                                                    \
-               if (!(tlb)->fullmm)                             \
-                       flush_cache_range(vma, vma->vm_start, vma->vm_end); \
-       }  while (0)
-#define tlb_end_vma(tlb, vma) do { } while (0)
 #define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
 
 static void tlb_flush(struct mmu_gather *tlb);
index 7aa12e88c5800df99123852f15c09e3054951e2e..c235648fae23afd14393a24859927b52012a7ee9 100644 (file)
@@ -256,6 +256,7 @@ config PPC
        select IRQ_FORCED_THREADING
        select MMU_GATHER_PAGE_SIZE
        select MMU_GATHER_RCU_TABLE_FREE
+       select MMU_GATHER_MERGE_VMAS
        select MODULES_USE_ELF_RELA
        select NEED_DMA_MAP_STATE               if PPC64 || NOT_COHERENT_CACHE
        select NEED_PER_CPU_EMBED_FIRST_CHUNK   if PPC64
index 09a9ae5f3656173698fe941a0523cf7e195b392e..b3de6102a90779739a598d9784ab9b55ab6e1ee0 100644 (file)
@@ -19,8 +19,6 @@
 
 #include <linux/pagemap.h>
 
-#define tlb_start_vma(tlb, vma)        do { } while (0)
-#define tlb_end_vma(tlb, vma)  do { } while (0)
 #define __tlb_remove_tlb_entry __tlb_remove_tlb_entry
 
 #define tlb_flush tlb_flush
index 8cd9e56c629ba8c374ab9cd0c0117663809cbd27..5a1a8dfda6f8e5d0ee45acd83574187c2661cf8d 100644 (file)
@@ -204,6 +204,7 @@ config S390
        select IOMMU_SUPPORT            if PCI
        select MMU_GATHER_NO_GATHER
        select MMU_GATHER_RCU_TABLE_FREE
+       select MMU_GATHER_MERGE_VMAS
        select MODULES_USE_ELF_RELA
        select NEED_DMA_MAP_STATE       if PCI
        select NEED_SG_DMA_LENGTH       if PCI
index fe6407f0eb1b7e4ef4a51e67c446ce20de96985e..3a5c8fb590e55ddfda72e6908ced1f4626e2c7c0 100644 (file)
@@ -27,9 +27,6 @@ static inline void tlb_flush(struct mmu_gather *tlb);
 static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
                                          struct page *page, int page_size);
 
-#define tlb_start_vma(tlb, vma)                        do { } while (0)
-#define tlb_end_vma(tlb, vma)                  do { } while (0)
-
 #define tlb_flush tlb_flush
 #define pte_free_tlb pte_free_tlb
 #define pmd_free_tlb pmd_free_tlb
index ba449c47effd8d975abf2f1130acef46e46662f9..4f7d1dfbc6086fbd01620e14ae76340c70984c92 100644 (file)
@@ -67,6 +67,8 @@ config SPARC64
        select HAVE_KRETPROBES
        select HAVE_KPROBES
        select MMU_GATHER_RCU_TABLE_FREE if SMP
+       select MMU_GATHER_MERGE_VMAS
+       select MMU_GATHER_NO_FLUSH_CACHE
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FTRACE_MCOUNT_RECORD
index 779a5a0f06080216cc0ce5ce30ca638b365b3b3d..3037187482db7ebe3334f99cb3e4e7af095933b7 100644 (file)
@@ -22,8 +22,6 @@ void smp_flush_tlb_mm(struct mm_struct *mm);
 void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *);
 void flush_tlb_pending(void);
 
-#define tlb_start_vma(tlb, vma) do { } while (0)
-#define tlb_end_vma(tlb, vma)  do { } while (0)
 #define tlb_flush(tlb) flush_tlb_pending()
 
 /*
index e58798f636d474d277af5eb59dc9b6a42b2c31d0..7fff10e159693ec61cc16fe1f7ddab6ee12db949 100644 (file)
@@ -245,6 +245,7 @@ config X86
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
        select MMU_GATHER_RCU_TABLE_FREE        if PARAVIRT
+       select MMU_GATHER_MERGE_VMAS
        select HAVE_POSIX_CPU_TIMERS_TASK_WORK
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_RELIABLE_STACKTRACE         if UNWINDER_ORC || STACK_VALIDATION
index 1bfe979bb9bcd25c1bc8d5c9ec82e581bb21bafc..580636cdc257b78930db0d9b9236cfa9fd62ed21 100644 (file)
@@ -2,9 +2,6 @@
 #ifndef _ASM_X86_TLB_H
 #define _ASM_X86_TLB_H
 
-#define tlb_start_vma(tlb, vma) do { } while (0)
-#define tlb_end_vma(tlb, vma) do { } while (0)
-
 #define tlb_flush tlb_flush
 static inline void tlb_flush(struct mmu_gather *tlb);
 
index ff3e82553a76c16baeaf25d00c849bfb5f90b2db..c1f03c1acbfc04aecabac16a4a9df133b8a44969 100644 (file)
  *  Useful if your architecture doesn't use IPIs for remote TLB invalidates
  *  and therefore doesn't naturally serialize with software page-table walkers.
  *
+ *  MMU_GATHER_NO_FLUSH_CACHE
+ *
+ *  Indicates the architecture has flush_cache_range() but it needs *NOT* be called
+ *  before unmapping a VMA.
+ *
+ *  NOTE: strictly speaking we shouldn't have this knob and instead rely on
+ *       flush_cache_range() being a NOP, except Sparc64 seems to be
+ *       different here.
+ *
+ *  MMU_GATHER_MERGE_VMAS
+ *
+ *  Indicates the architecture wants to merge ranges over VMAs; typical when
+ *  multiple range invalidates are more expensive than a full invalidate.
+ *
  *  MMU_GATHER_NO_RANGE
  *
- *  Use this if your architecture lacks an efficient flush_tlb_range().
+ *  Use this if your architecture lacks an efficient flush_tlb_range(). This
+ *  option implies MMU_GATHER_MERGE_VMAS above.
  *
  *  MMU_GATHER_NO_GATHER
  *
@@ -493,14 +508,16 @@ static inline void tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *
                return;
 
        tlb_update_vma_flags(tlb, vma);
+#ifndef CONFIG_MMU_GATHER_NO_FLUSH_CACHE
        flush_cache_range(vma, vma->vm_start, vma->vm_end);
+#endif
 }
 #endif
 
 #ifndef tlb_end_vma
 static inline void tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
 {
-       if (tlb->fullmm)
+       if (tlb->fullmm || IS_ENABLED(CONFIG_MMU_GATHER_MERGE_VMAS))
                return;
 
        /*