Commit 03b505eae6a276b8c38b6222694afb6cea10b1cc
1 parent
10034aabca
Exists in
master
and in
7 other branches
ARM: SMP: split out software TLB maintainence broadcasting
smp.c is becoming too large, so split out the TLB maintainence broadcasting into a separate smp_tlb.c file. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Showing 3 changed files with 140 additions and 127 deletions Side-by-side Diff
arch/arm/kernel/Makefile
... | ... | @@ -29,7 +29,7 @@ |
29 | 29 | obj-$(CONFIG_ARTHUR) += arthur.o |
30 | 30 | obj-$(CONFIG_ISA_DMA) += dma-isa.o |
31 | 31 | obj-$(CONFIG_PCI) += bios32.o isa.o |
32 | -obj-$(CONFIG_SMP) += smp.o | |
32 | +obj-$(CONFIG_SMP) += smp.o smp_tlb.o | |
33 | 33 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o |
34 | 34 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o |
35 | 35 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
arch/arm/kernel/smp.c
... | ... | @@ -38,7 +38,6 @@ |
38 | 38 | #include <asm/tlbflush.h> |
39 | 39 | #include <asm/ptrace.h> |
40 | 40 | #include <asm/localtimer.h> |
41 | -#include <asm/smp_plat.h> | |
42 | 41 | |
43 | 42 | /* |
44 | 43 | * as from 2.5, kernels no longer have an init_tasks structure |
... | ... | @@ -654,130 +653,5 @@ |
654 | 653 | int setup_profiling_timer(unsigned int multiplier) |
655 | 654 | { |
656 | 655 | return -EINVAL; |
657 | -} | |
658 | - | |
659 | -static void | |
660 | -on_each_cpu_mask(void (*func)(void *), void *info, int wait, | |
661 | - const struct cpumask *mask) | |
662 | -{ | |
663 | - preempt_disable(); | |
664 | - | |
665 | - smp_call_function_many(mask, func, info, wait); | |
666 | - if (cpumask_test_cpu(smp_processor_id(), mask)) | |
667 | - func(info); | |
668 | - | |
669 | - preempt_enable(); | |
670 | -} | |
671 | - | |
672 | -/**********************************************************************/ | |
673 | - | |
674 | -/* | |
675 | - * TLB operations | |
676 | - */ | |
677 | -struct tlb_args { | |
678 | - struct vm_area_struct *ta_vma; | |
679 | - unsigned long ta_start; | |
680 | - unsigned long ta_end; | |
681 | -}; | |
682 | - | |
683 | -static inline void ipi_flush_tlb_all(void *ignored) | |
684 | -{ | |
685 | - local_flush_tlb_all(); | |
686 | -} | |
687 | - | |
688 | -static inline void ipi_flush_tlb_mm(void *arg) | |
689 | -{ | |
690 | - struct mm_struct *mm = (struct mm_struct *)arg; | |
691 | - | |
692 | - local_flush_tlb_mm(mm); | |
693 | -} | |
694 | - | |
695 | -static inline void ipi_flush_tlb_page(void *arg) | |
696 | -{ | |
697 | - struct tlb_args *ta = (struct tlb_args *)arg; | |
698 | - | |
699 | - local_flush_tlb_page(ta->ta_vma, ta->ta_start); | |
700 | -} | |
701 | - | |
702 | -static inline void ipi_flush_tlb_kernel_page(void *arg) | |
703 | -{ | |
704 | - struct tlb_args *ta = (struct tlb_args *)arg; | |
705 | - | |
706 | - local_flush_tlb_kernel_page(ta->ta_start); | |
707 | -} | |
708 | - | |
709 | -static inline void ipi_flush_tlb_range(void *arg) | |
710 | -{ | |
711 | - struct tlb_args *ta = (struct tlb_args *)arg; | |
712 | - | |
713 | - local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end); | |
714 | -} | |
715 | - | |
716 | -static inline void ipi_flush_tlb_kernel_range(void *arg) | |
717 | -{ | |
718 | - struct tlb_args *ta = (struct tlb_args *)arg; | |
719 | - | |
720 | - local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); | |
721 | -} | |
722 | - | |
723 | -void flush_tlb_all(void) | |
724 | -{ | |
725 | - if (tlb_ops_need_broadcast()) | |
726 | - on_each_cpu(ipi_flush_tlb_all, NULL, 1); | |
727 | - else | |
728 | - local_flush_tlb_all(); | |
729 | -} | |
730 | - | |
731 | -void flush_tlb_mm(struct mm_struct *mm) | |
732 | -{ | |
733 | - if (tlb_ops_need_broadcast()) | |
734 | - on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm)); | |
735 | - else | |
736 | - local_flush_tlb_mm(mm); | |
737 | -} | |
738 | - | |
739 | -void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) | |
740 | -{ | |
741 | - if (tlb_ops_need_broadcast()) { | |
742 | - struct tlb_args ta; | |
743 | - ta.ta_vma = vma; | |
744 | - ta.ta_start = uaddr; | |
745 | - on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm)); | |
746 | - } else | |
747 | - local_flush_tlb_page(vma, uaddr); | |
748 | -} | |
749 | - | |
750 | -void flush_tlb_kernel_page(unsigned long kaddr) | |
751 | -{ | |
752 | - if (tlb_ops_need_broadcast()) { | |
753 | - struct tlb_args ta; | |
754 | - ta.ta_start = kaddr; | |
755 | - on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); | |
756 | - } else | |
757 | - local_flush_tlb_kernel_page(kaddr); | |
758 | -} | |
759 | - | |
760 | -void flush_tlb_range(struct vm_area_struct *vma, | |
761 | - unsigned long start, unsigned long end) | |
762 | -{ | |
763 | - if (tlb_ops_need_broadcast()) { | |
764 | - struct tlb_args ta; | |
765 | - ta.ta_vma = vma; | |
766 | - ta.ta_start = start; | |
767 | - ta.ta_end = end; | |
768 | - on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm)); | |
769 | - } else | |
770 | - local_flush_tlb_range(vma, start, end); | |
771 | -} | |
772 | - | |
773 | -void flush_tlb_kernel_range(unsigned long start, unsigned long end) | |
774 | -{ | |
775 | - if (tlb_ops_need_broadcast()) { | |
776 | - struct tlb_args ta; | |
777 | - ta.ta_start = start; | |
778 | - ta.ta_end = end; | |
779 | - on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); | |
780 | - } else | |
781 | - local_flush_tlb_kernel_range(start, end); | |
782 | 656 | } |
arch/arm/kernel/smp_tlb.c
1 | +/* | |
2 | + * linux/arch/arm/kernel/smp_tlb.c | |
3 | + * | |
4 | + * Copyright (C) 2002 ARM Limited, All Rights Reserved. | |
5 | + * | |
6 | + * This program is free software; you can redistribute it and/or modify | |
7 | + * it under the terms of the GNU General Public License version 2 as | |
8 | + * published by the Free Software Foundation. | |
9 | + */ | |
10 | +#include <linux/preempt.h> | |
11 | +#include <linux/smp.h> | |
12 | + | |
13 | +#include <asm/smp_plat.h> | |
14 | +#include <asm/tlbflush.h> | |
15 | + | |
16 | +static void on_each_cpu_mask(void (*func)(void *), void *info, int wait, | |
17 | + const struct cpumask *mask) | |
18 | +{ | |
19 | + preempt_disable(); | |
20 | + | |
21 | + smp_call_function_many(mask, func, info, wait); | |
22 | + if (cpumask_test_cpu(smp_processor_id(), mask)) | |
23 | + func(info); | |
24 | + | |
25 | + preempt_enable(); | |
26 | +} | |
27 | + | |
28 | +/**********************************************************************/ | |
29 | + | |
30 | +/* | |
31 | + * TLB operations | |
32 | + */ | |
33 | +struct tlb_args { | |
34 | + struct vm_area_struct *ta_vma; | |
35 | + unsigned long ta_start; | |
36 | + unsigned long ta_end; | |
37 | +}; | |
38 | + | |
39 | +static inline void ipi_flush_tlb_all(void *ignored) | |
40 | +{ | |
41 | + local_flush_tlb_all(); | |
42 | +} | |
43 | + | |
44 | +static inline void ipi_flush_tlb_mm(void *arg) | |
45 | +{ | |
46 | + struct mm_struct *mm = (struct mm_struct *)arg; | |
47 | + | |
48 | + local_flush_tlb_mm(mm); | |
49 | +} | |
50 | + | |
51 | +static inline void ipi_flush_tlb_page(void *arg) | |
52 | +{ | |
53 | + struct tlb_args *ta = (struct tlb_args *)arg; | |
54 | + | |
55 | + local_flush_tlb_page(ta->ta_vma, ta->ta_start); | |
56 | +} | |
57 | + | |
58 | +static inline void ipi_flush_tlb_kernel_page(void *arg) | |
59 | +{ | |
60 | + struct tlb_args *ta = (struct tlb_args *)arg; | |
61 | + | |
62 | + local_flush_tlb_kernel_page(ta->ta_start); | |
63 | +} | |
64 | + | |
65 | +static inline void ipi_flush_tlb_range(void *arg) | |
66 | +{ | |
67 | + struct tlb_args *ta = (struct tlb_args *)arg; | |
68 | + | |
69 | + local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end); | |
70 | +} | |
71 | + | |
72 | +static inline void ipi_flush_tlb_kernel_range(void *arg) | |
73 | +{ | |
74 | + struct tlb_args *ta = (struct tlb_args *)arg; | |
75 | + | |
76 | + local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); | |
77 | +} | |
78 | + | |
79 | +void flush_tlb_all(void) | |
80 | +{ | |
81 | + if (tlb_ops_need_broadcast()) | |
82 | + on_each_cpu(ipi_flush_tlb_all, NULL, 1); | |
83 | + else | |
84 | + local_flush_tlb_all(); | |
85 | +} | |
86 | + | |
87 | +void flush_tlb_mm(struct mm_struct *mm) | |
88 | +{ | |
89 | + if (tlb_ops_need_broadcast()) | |
90 | + on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm)); | |
91 | + else | |
92 | + local_flush_tlb_mm(mm); | |
93 | +} | |
94 | + | |
95 | +void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) | |
96 | +{ | |
97 | + if (tlb_ops_need_broadcast()) { | |
98 | + struct tlb_args ta; | |
99 | + ta.ta_vma = vma; | |
100 | + ta.ta_start = uaddr; | |
101 | + on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm)); | |
102 | + } else | |
103 | + local_flush_tlb_page(vma, uaddr); | |
104 | +} | |
105 | + | |
106 | +void flush_tlb_kernel_page(unsigned long kaddr) | |
107 | +{ | |
108 | + if (tlb_ops_need_broadcast()) { | |
109 | + struct tlb_args ta; | |
110 | + ta.ta_start = kaddr; | |
111 | + on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); | |
112 | + } else | |
113 | + local_flush_tlb_kernel_page(kaddr); | |
114 | +} | |
115 | + | |
116 | +void flush_tlb_range(struct vm_area_struct *vma, | |
117 | + unsigned long start, unsigned long end) | |
118 | +{ | |
119 | + if (tlb_ops_need_broadcast()) { | |
120 | + struct tlb_args ta; | |
121 | + ta.ta_vma = vma; | |
122 | + ta.ta_start = start; | |
123 | + ta.ta_end = end; | |
124 | + on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm)); | |
125 | + } else | |
126 | + local_flush_tlb_range(vma, start, end); | |
127 | +} | |
128 | + | |
129 | +void flush_tlb_kernel_range(unsigned long start, unsigned long end) | |
130 | +{ | |
131 | + if (tlb_ops_need_broadcast()) { | |
132 | + struct tlb_args ta; | |
133 | + ta.ta_start = start; | |
134 | + ta.ta_end = end; | |
135 | + on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); | |
136 | + } else | |
137 | + local_flush_tlb_kernel_range(start, end); | |
138 | +} |