]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
arm64: mm: Simplify __flush_tlb_range_limit_excess()
authorWill Deacon <will@kernel.org>
Mon, 2 Mar 2026 13:55:55 +0000 (13:55 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Fri, 13 Mar 2026 17:23:04 +0000 (17:23 +0000)
__flush_tlb_range_limit_excess() is unnecessarily complicated:

  - It takes a 'start', 'end' and 'pages' argument, whereas it only
    needs 'pages' (which the caller has computed from the other two
    arguments!).

  - It erroneously compares 'pages' with MAX_TLBI_RANGE_PAGES when
    the system doesn't support range-based invalidation but the range to
    be invalidated would result in fewer than MAX_DVM_OPS invalidations.

Simplify the function so that it no longer takes the 'start' and 'end'
arguments and only considers the MAX_TLBI_RANGE_PAGES threshold on
systems that implement range-based invalidation.

Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/tlbflush.h

index fb7e541cfdfd9f4bd3a4ab1dc354a6b251a0369f..fd86647db24bb264340c3abac63d5c5e4f9cbf41 100644 (file)
@@ -537,21 +537,19 @@ invalidate_one:
 #define __flush_s2_tlb_range_op(op, start, pages, stride, tlb_level) \
        __flush_tlb_range_op(op, r##op, start, pages, stride, 0, tlb_level, kvm_lpa2_is_enabled())
 
-static inline bool __flush_tlb_range_limit_excess(unsigned long start,
-               unsigned long end, unsigned long pages, unsigned long stride)
+static inline bool __flush_tlb_range_limit_excess(unsigned long pages,
+                                                 unsigned long stride)
 {
        /*
-        * When the system does not support TLB range based flush
-        * operation, (MAX_DVM_OPS - 1) pages can be handled. But
-        * with TLB range based operation, MAX_TLBI_RANGE_PAGES
-        * pages can be handled.
+        * Assume that the worst case number of DVM ops required to flush a
+        * given range on a system that supports tlb-range is 20 (4 scales, 1
+        * final page, 15 for alignment on LPA2 systems), which is much smaller
+        * than MAX_DVM_OPS.
         */
-       if ((!system_supports_tlb_range() &&
-            (end - start) >= (MAX_DVM_OPS * stride)) ||
-           pages > MAX_TLBI_RANGE_PAGES)
-               return true;
+       if (system_supports_tlb_range())
+               return pages > MAX_TLBI_RANGE_PAGES;
 
-       return false;
+       return pages >= (MAX_DVM_OPS * stride) >> PAGE_SHIFT;
 }
 
 static inline void __flush_tlb_range_nosync(struct mm_struct *mm,
@@ -565,7 +563,7 @@ static inline void __flush_tlb_range_nosync(struct mm_struct *mm,
        end = round_up(end, stride);
        pages = (end - start) >> PAGE_SHIFT;
 
-       if (__flush_tlb_range_limit_excess(start, end, pages, stride)) {
+       if (__flush_tlb_range_limit_excess(pages, stride)) {
                flush_tlb_mm(mm);
                return;
        }
@@ -629,7 +627,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
        end = round_up(end, stride);
        pages = (end - start) >> PAGE_SHIFT;
 
-       if (__flush_tlb_range_limit_excess(start, end, pages, stride)) {
+       if (__flush_tlb_range_limit_excess(pages, stride)) {
                flush_tlb_all();
                return;
        }