diff options
Diffstat (limited to 'arch/x86/kernel/tlb_32.c')
-rw-r--r-- | arch/x86/kernel/tlb_32.c | 67 |
1 files changed, 29 insertions, 38 deletions
diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c index ce5054642247..ec53818f4e38 100644 --- a/arch/x86/kernel/tlb_32.c +++ b/arch/x86/kernel/tlb_32.c | |||
@@ -20,7 +20,7 @@ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) | |||
20 | * Optimizations Manfred Spraul <manfred@colorfullife.com> | 20 | * Optimizations Manfred Spraul <manfred@colorfullife.com> |
21 | */ | 21 | */ |
22 | 22 | ||
23 | static cpumask_t flush_cpumask; | 23 | static cpumask_var_t flush_cpumask; |
24 | static struct mm_struct *flush_mm; | 24 | static struct mm_struct *flush_mm; |
25 | static unsigned long flush_va; | 25 | static unsigned long flush_va; |
26 | static DEFINE_SPINLOCK(tlbstate_lock); | 26 | static DEFINE_SPINLOCK(tlbstate_lock); |
@@ -92,7 +92,7 @@ void smp_invalidate_interrupt(struct pt_regs *regs) | |||
92 | 92 | ||
93 | cpu = get_cpu(); | 93 | cpu = get_cpu(); |
94 | 94 | ||
95 | if (!cpu_isset(cpu, flush_cpumask)) | 95 | if (!cpumask_test_cpu(cpu, flush_cpumask)) |
96 | goto out; | 96 | goto out; |
97 | /* | 97 | /* |
98 | * This was a BUG() but until someone can quote me the | 98 | * This was a BUG() but until someone can quote me the |
@@ -114,35 +114,22 @@ void smp_invalidate_interrupt(struct pt_regs *regs) | |||
114 | } | 114 | } |
115 | ack_APIC_irq(); | 115 | ack_APIC_irq(); |
116 | smp_mb__before_clear_bit(); | 116 | smp_mb__before_clear_bit(); |
117 | cpu_clear(cpu, flush_cpumask); | 117 | cpumask_clear_cpu(cpu, flush_cpumask); |
118 | smp_mb__after_clear_bit(); | 118 | smp_mb__after_clear_bit(); |
119 | out: | 119 | out: |
120 | put_cpu_no_resched(); | 120 | put_cpu_no_resched(); |
121 | inc_irq_stat(irq_tlb_count); | 121 | inc_irq_stat(irq_tlb_count); |
122 | } | 122 | } |
123 | 123 | ||
124 | void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, | 124 | void native_flush_tlb_others(const struct cpumask *cpumask, |
125 | unsigned long va) | 125 | struct mm_struct *mm, unsigned long va) |
126 | { | 126 | { |
127 | cpumask_t cpumask = *cpumaskp; | ||
128 | |||
129 | /* | 127 | /* |
130 | * A couple of (to be removed) sanity checks: | ||
131 | * | ||
132 | * - current CPU must not be in mask | ||
133 | * - mask must exist :) | 128 | * - mask must exist :) |
134 | */ | 129 | */ |
135 | BUG_ON(cpus_empty(cpumask)); | 130 | BUG_ON(cpumask_empty(cpumask)); |
136 | BUG_ON(cpu_isset(smp_processor_id(), cpumask)); | ||
137 | BUG_ON(!mm); | 131 | BUG_ON(!mm); |
138 | 132 | ||
139 | #ifdef CONFIG_HOTPLUG_CPU | ||
140 | /* If a CPU which we ran on has gone down, OK. */ | ||
141 | cpus_and(cpumask, cpumask, cpu_online_map); | ||
142 | if (unlikely(cpus_empty(cpumask))) | ||
143 | return; | ||
144 | #endif | ||
145 | |||
146 | /* | 133 | /* |
147 | * i'm not happy about this global shared spinlock in the | 134 | * i'm not happy about this global shared spinlock in the |
148 | * MM hot path, but we'll see how contended it is. | 135 | * MM hot path, but we'll see how contended it is. |
@@ -150,9 +137,17 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, | |||
150 | */ | 137 | */ |
151 | spin_lock(&tlbstate_lock); | 138 | spin_lock(&tlbstate_lock); |
152 | 139 | ||
140 | cpumask_andnot(flush_cpumask, cpumask, cpumask_of(smp_processor_id())); | ||
141 | #ifdef CONFIG_HOTPLUG_CPU | ||
142 | /* If a CPU which we ran on has gone down, OK. */ | ||
143 | cpumask_and(flush_cpumask, flush_cpumask, cpu_online_mask); | ||
144 | if (unlikely(cpumask_empty(flush_cpumask))) { | ||
145 | spin_unlock(&tlbstate_lock); | ||
146 | return; | ||
147 | } | ||
148 | #endif | ||
153 | flush_mm = mm; | 149 | flush_mm = mm; |
154 | flush_va = va; | 150 | flush_va = va; |
155 | cpus_or(flush_cpumask, cpumask, flush_cpumask); | ||
156 | 151 | ||
157 | /* | 152 | /* |
158 | * Make the above memory operations globally visible before | 153 | * Make the above memory operations globally visible before |
@@ -163,9 +158,9 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, | |||
163 | * We have to send the IPI only to | 158 | * We have to send the IPI only to |
164 | * CPUs affected. | 159 | * CPUs affected. |
165 | */ | 160 | */ |
166 | send_IPI_mask(&cpumask, INVALIDATE_TLB_VECTOR); | 161 | send_IPI_mask(flush_cpumask, INVALIDATE_TLB_VECTOR); |
167 | 162 | ||
168 | while (!cpus_empty(flush_cpumask)) | 163 | while (!cpumask_empty(flush_cpumask)) |
169 | /* nothing. lockup detection does not belong here */ | 164 | /* nothing. lockup detection does not belong here */ |
170 | cpu_relax(); | 165 | cpu_relax(); |
171 | 166 | ||
@@ -177,25 +172,19 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, | |||
177 | void flush_tlb_current_task(void) | 172 | void flush_tlb_current_task(void) |
178 | { | 173 | { |
179 | struct mm_struct *mm = current->mm; | 174 | struct mm_struct *mm = current->mm; |
180 | cpumask_t cpu_mask; | ||
181 | 175 | ||
182 | preempt_disable(); | 176 | preempt_disable(); |
183 | cpu_mask = mm->cpu_vm_mask; | ||
184 | cpu_clear(smp_processor_id(), cpu_mask); | ||
185 | 177 | ||
186 | local_flush_tlb(); | 178 | local_flush_tlb(); |
187 | if (!cpus_empty(cpu_mask)) | 179 | if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) |
188 | flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL); | 180 | flush_tlb_others(&mm->cpu_vm_mask, mm, TLB_FLUSH_ALL); |
189 | preempt_enable(); | 181 | preempt_enable(); |
190 | } | 182 | } |
191 | 183 | ||
192 | void flush_tlb_mm(struct mm_struct *mm) | 184 | void flush_tlb_mm(struct mm_struct *mm) |
193 | { | 185 | { |
194 | cpumask_t cpu_mask; | ||
195 | 186 | ||
196 | preempt_disable(); | 187 | preempt_disable(); |
197 | cpu_mask = mm->cpu_vm_mask; | ||
198 | cpu_clear(smp_processor_id(), cpu_mask); | ||
199 | 188 | ||
200 | if (current->active_mm == mm) { | 189 | if (current->active_mm == mm) { |
201 | if (current->mm) | 190 | if (current->mm) |
@@ -203,8 +192,8 @@ void flush_tlb_mm(struct mm_struct *mm) | |||
203 | else | 192 | else |
204 | leave_mm(smp_processor_id()); | 193 | leave_mm(smp_processor_id()); |
205 | } | 194 | } |
206 | if (!cpus_empty(cpu_mask)) | 195 | if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) |
207 | flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL); | 196 | flush_tlb_others(&mm->cpu_vm_mask, mm, TLB_FLUSH_ALL); |
208 | 197 | ||
209 | preempt_enable(); | 198 | preempt_enable(); |
210 | } | 199 | } |
@@ -212,11 +201,8 @@ void flush_tlb_mm(struct mm_struct *mm) | |||
212 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) | 201 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) |
213 | { | 202 | { |
214 | struct mm_struct *mm = vma->vm_mm; | 203 | struct mm_struct *mm = vma->vm_mm; |
215 | cpumask_t cpu_mask; | ||
216 | 204 | ||
217 | preempt_disable(); | 205 | preempt_disable(); |
218 | cpu_mask = mm->cpu_vm_mask; | ||
219 | cpu_clear(smp_processor_id(), cpu_mask); | ||
220 | 206 | ||
221 | if (current->active_mm == mm) { | 207 | if (current->active_mm == mm) { |
222 | if (current->mm) | 208 | if (current->mm) |
@@ -225,9 +211,8 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) | |||
225 | leave_mm(smp_processor_id()); | 211 | leave_mm(smp_processor_id()); |
226 | } | 212 | } |
227 | 213 | ||
228 | if (!cpus_empty(cpu_mask)) | 214 | if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) |
229 | flush_tlb_others(cpu_mask, mm, va); | 215 | flush_tlb_others(&mm->cpu_vm_mask, mm, va); |
230 | |||
231 | preempt_enable(); | 216 | preempt_enable(); |
232 | } | 217 | } |
233 | EXPORT_SYMBOL(flush_tlb_page); | 218 | EXPORT_SYMBOL(flush_tlb_page); |
@@ -254,3 +239,9 @@ void reset_lazy_tlbstate(void) | |||
254 | per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; | 239 | per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; |
255 | } | 240 | } |
256 | 241 | ||
242 | static int init_flush_cpumask(void) | ||
243 | { | ||
244 | alloc_cpumask_var(&flush_cpumask, GFP_KERNEL); | ||
245 | return 0; | ||
246 | } | ||
247 | early_initcall(init_flush_cpumask); | ||