Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xtensa: optimize local_flush_tlb_kernel_range

Don't flush whole TLB if only a small kernel range is requested.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>

+34 -7
+4 -7
arch/xtensa/include/asm/tlbflush.h
··· 36 36 unsigned long page); 37 37 void local_flush_tlb_range(struct vm_area_struct *vma, 38 38 unsigned long start, unsigned long end); 39 + void local_flush_tlb_kernel_range(unsigned long start, unsigned long end); 39 40 40 41 #ifdef CONFIG_SMP 41 42 ··· 45 44 void flush_tlb_page(struct vm_area_struct *, unsigned long); 46 45 void flush_tlb_range(struct vm_area_struct *, unsigned long, 47 46 unsigned long); 48 - 49 - static inline void flush_tlb_kernel_range(unsigned long start, 50 - unsigned long end) 51 - { 52 - flush_tlb_all(); 53 - } 47 + void flush_tlb_kernel_range(unsigned long start, unsigned long end); 54 48 55 49 #else /* !CONFIG_SMP */ 56 50 ··· 54 58 #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) 55 59 #define flush_tlb_range(vma, vmaddr, end) local_flush_tlb_range(vma, vmaddr, \ 56 60 end) 57 - #define flush_tlb_kernel_range(start, end) local_flush_tlb_all() 61 + #define flush_tlb_kernel_range(start, end) local_flush_tlb_kernel_range(start, \ 62 + end) 58 63 59 64 #endif /* CONFIG_SMP */ 60 65
+15
arch/xtensa/kernel/smp.c
··· 496 496 on_each_cpu(ipi_flush_tlb_range, &fd, 1); 497 497 } 498 498 499 + static void ipi_flush_tlb_kernel_range(void *arg) 500 + { 501 + struct flush_data *fd = arg; 502 + local_flush_tlb_kernel_range(fd->addr1, fd->addr2); 503 + } 504 + 505 + void flush_tlb_kernel_range(unsigned long start, unsigned long end) 506 + { 507 + struct flush_data fd = { 508 + .addr1 = start, 509 + .addr2 = end, 510 + }; 511 + on_each_cpu(ipi_flush_tlb_kernel_range, &fd, 1); 512 + } 513 + 499 514 /* Cache flush functions */ 500 515 501 516 static void ipi_flush_cache_all(void *arg)
+15
arch/xtensa/mm/tlb.c
··· 149 149 local_irq_restore(flags); 150 150 } 151 151 152 + void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) 153 + { 154 + if (end > start && start >= TASK_SIZE && end <= PAGE_OFFSET && 155 + end - start < _TLB_ENTRIES << PAGE_SHIFT) { 156 + start &= PAGE_MASK; 157 + while (start < end) { 158 + invalidate_itlb_mapping(start); 159 + invalidate_dtlb_mapping(start); 160 + start += PAGE_SIZE; 161 + } 162 + } else { 163 + local_flush_tlb_all(); 164 + } 165 + } 166 + 152 167 #ifdef CONFIG_DEBUG_TLB_SANITY 153 168 154 169 static unsigned get_pte_for_vaddr(unsigned vaddr)