diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2014-02-14 05:08:48 -0500 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2014-04-06 13:29:17 -0400 |
commit | 04c6b3e2b5e5c1dbd99ad7620033eafd05ff4c26 (patch) | |
tree | a6f93ad79be6262819a5bc6b73f2646c4f4985dd /arch | |
parent | 8585b316bbed9339412d267c1fd8839dd059d69f (diff) |
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/xtensa/include/asm/tlbflush.h | 11 | ||||
-rw-r--r-- | arch/xtensa/kernel/smp.c | 15 | ||||
-rw-r--r-- | arch/xtensa/mm/tlb.c | 15 |
3 files changed, 34 insertions, 7 deletions
diff --git a/arch/xtensa/include/asm/tlbflush.h b/arch/xtensa/include/asm/tlbflush.h index fc34274ce41b..06875feb27c2 100644 --- a/arch/xtensa/include/asm/tlbflush.h +++ b/arch/xtensa/include/asm/tlbflush.h | |||
@@ -36,6 +36,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, | |||
36 | unsigned long page); | 36 | unsigned long page); |
37 | void local_flush_tlb_range(struct vm_area_struct *vma, | 37 | void local_flush_tlb_range(struct vm_area_struct *vma, |
38 | unsigned long start, unsigned long end); | 38 | unsigned long start, unsigned long end); |
39 | void local_flush_tlb_kernel_range(unsigned long start, unsigned long end); | ||
39 | 40 | ||
40 | #ifdef CONFIG_SMP | 41 | #ifdef CONFIG_SMP |
41 | 42 | ||
@@ -44,12 +45,7 @@ void flush_tlb_mm(struct mm_struct *); | |||
44 | void flush_tlb_page(struct vm_area_struct *, unsigned long); | 45 | void flush_tlb_page(struct vm_area_struct *, unsigned long); |
45 | void flush_tlb_range(struct vm_area_struct *, unsigned long, | 46 | void flush_tlb_range(struct vm_area_struct *, unsigned long, |
46 | unsigned long); | 47 | unsigned long); |
47 | 48 | void flush_tlb_kernel_range(unsigned long start, unsigned long end); | |
48 | static inline void flush_tlb_kernel_range(unsigned long start, | ||
49 | unsigned long end) | ||
50 | { | ||
51 | flush_tlb_all(); | ||
52 | } | ||
53 | 49 | ||
54 | #else /* !CONFIG_SMP */ | 50 | #else /* !CONFIG_SMP */ |
55 | 51 | ||
@@ -58,7 +54,8 @@ static inline void flush_tlb_kernel_range(unsigned long start, | |||
58 | #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) | 54 | #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) |
59 | #define flush_tlb_range(vma, vmaddr, end) local_flush_tlb_range(vma, vmaddr, \ | 55 | #define flush_tlb_range(vma, vmaddr, end) local_flush_tlb_range(vma, vmaddr, \ |
60 | end) | 56 | end) |
61 | #define flush_tlb_kernel_range(start, end) local_flush_tlb_all() | 57 | #define flush_tlb_kernel_range(start, end) local_flush_tlb_kernel_range(start, \ |
58 | end) | ||
62 | 59 | ||
63 | #endif /* CONFIG_SMP */ | 60 | #endif /* CONFIG_SMP */ |
64 | 61 | ||
diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c index aa8bd8717927..40b5a3771fb0 100644 --- a/arch/xtensa/kernel/smp.c +++ b/arch/xtensa/kernel/smp.c | |||
@@ -496,6 +496,21 @@ void flush_tlb_range(struct vm_area_struct *vma, | |||
496 | on_each_cpu(ipi_flush_tlb_range, &fd, 1); | 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 | /* Cache flush functions */ | 514 | /* Cache flush functions */ |
500 | 515 | ||
501 | static void ipi_flush_cache_all(void *arg) | 516 | static void ipi_flush_cache_all(void *arg) |
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c index ade623826788..5ece856c5725 100644 --- a/arch/xtensa/mm/tlb.c +++ b/arch/xtensa/mm/tlb.c | |||
@@ -149,6 +149,21 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
149 | local_irq_restore(flags); | 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 | #ifdef CONFIG_DEBUG_TLB_SANITY | 167 | #ifdef CONFIG_DEBUG_TLB_SANITY |
153 | 168 | ||
154 | static unsigned get_pte_for_vaddr(unsigned vaddr) | 169 | static unsigned get_pte_for_vaddr(unsigned vaddr) |