diff options
Diffstat (limited to 'arch/x86/kernel/tlb_uv.c')
-rw-r--r-- | arch/x86/kernel/tlb_uv.c | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index f885023167e0..89fce1b6d01f 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | 12 | ||
13 | #include <asm/mmu_context.h> | 13 | #include <asm/mmu_context.h> |
14 | #include <asm/uv/uv.h> | ||
14 | #include <asm/uv/uv_mmrs.h> | 15 | #include <asm/uv/uv_mmrs.h> |
15 | #include <asm/uv/uv_hub.h> | 16 | #include <asm/uv/uv_hub.h> |
16 | #include <asm/uv/uv_bau.h> | 17 | #include <asm/uv/uv_bau.h> |
@@ -200,6 +201,7 @@ static int uv_wait_completion(struct bau_desc *bau_desc, | |||
200 | destination_timeouts = 0; | 201 | destination_timeouts = 0; |
201 | } | 202 | } |
202 | } | 203 | } |
204 | cpu_relax(); | ||
203 | } | 205 | } |
204 | return FLUSH_COMPLETE; | 206 | return FLUSH_COMPLETE; |
205 | } | 207 | } |
@@ -209,14 +211,15 @@ static int uv_wait_completion(struct bau_desc *bau_desc, | |||
209 | * | 211 | * |
210 | * Send a broadcast and wait for a broadcast message to complete. | 212 | * Send a broadcast and wait for a broadcast message to complete. |
211 | * | 213 | * |
212 | * The cpumaskp mask contains the cpus the broadcast was sent to. | 214 | * The flush_mask contains the cpus the broadcast was sent to. |
213 | * | 215 | * |
214 | * Returns 1 if all remote flushing was done. The mask is zeroed. | 216 | * Returns NULL if all remote flushing was done. The mask is zeroed. |
215 | * Returns 0 if some remote flushing remains to be done. The mask is left | 217 | * Returns @flush_mask if some remote flushing remains to be done. The |
216 | * unchanged. | 218 | * mask will have some bits still set. |
217 | */ | 219 | */ |
218 | int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc, | 220 | const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade, |
219 | cpumask_t *cpumaskp) | 221 | struct bau_desc *bau_desc, |
222 | struct cpumask *flush_mask) | ||
220 | { | 223 | { |
221 | int completion_status = 0; | 224 | int completion_status = 0; |
222 | int right_shift; | 225 | int right_shift; |
@@ -263,59 +266,69 @@ int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc, | |||
263 | * Success, so clear the remote cpu's from the mask so we don't | 266 | * Success, so clear the remote cpu's from the mask so we don't |
264 | * use the IPI method of shootdown on them. | 267 | * use the IPI method of shootdown on them. |
265 | */ | 268 | */ |
266 | for_each_cpu_mask(bit, *cpumaskp) { | 269 | for_each_cpu(bit, flush_mask) { |
267 | blade = uv_cpu_to_blade_id(bit); | 270 | blade = uv_cpu_to_blade_id(bit); |
268 | if (blade == this_blade) | 271 | if (blade == this_blade) |
269 | continue; | 272 | continue; |
270 | cpu_clear(bit, *cpumaskp); | 273 | cpumask_clear_cpu(bit, flush_mask); |
271 | } | 274 | } |
272 | if (!cpus_empty(*cpumaskp)) | 275 | if (!cpumask_empty(flush_mask)) |
273 | return 0; | 276 | return flush_mask; |
274 | return 1; | 277 | return NULL; |
275 | } | 278 | } |
276 | 279 | ||
277 | /** | 280 | /** |
278 | * uv_flush_tlb_others - globally purge translation cache of a virtual | 281 | * uv_flush_tlb_others - globally purge translation cache of a virtual |
279 | * address or all TLB's | 282 | * address or all TLB's |
280 | * @cpumaskp: mask of all cpu's in which the address is to be removed | 283 | * @cpumask: mask of all cpu's in which the address is to be removed |
281 | * @mm: mm_struct containing virtual address range | 284 | * @mm: mm_struct containing virtual address range |
282 | * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu) | 285 | * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu) |
286 | * @cpu: the current cpu | ||
283 | * | 287 | * |
284 | * This is the entry point for initiating any UV global TLB shootdown. | 288 | * This is the entry point for initiating any UV global TLB shootdown. |
285 | * | 289 | * |
286 | * Purges the translation caches of all specified processors of the given | 290 | * Purges the translation caches of all specified processors of the given |
287 | * virtual address, or purges all TLB's on specified processors. | 291 | * virtual address, or purges all TLB's on specified processors. |
288 | * | 292 | * |
289 | * The caller has derived the cpumaskp from the mm_struct and has subtracted | 293 | * The caller has derived the cpumask from the mm_struct. This function |
290 | * the local cpu from the mask. This function is called only if there | 294 | * is called only if there are bits set in the mask. (e.g. flush_tlb_page()) |
291 | * are bits set in the mask. (e.g. flush_tlb_page()) | ||
292 | * | 295 | * |
293 | * The cpumaskp is converted into a nodemask of the nodes containing | 296 | * The cpumask is converted into a nodemask of the nodes containing |
294 | * the cpus. | 297 | * the cpus. |
295 | * | 298 | * |
296 | * Returns 1 if all remote flushing was done. | 299 | * Note that this function should be called with preemption disabled. |
297 | * Returns 0 if some remote flushing remains to be done. | 300 | * |
301 | * Returns NULL if all remote flushing was done. | ||
302 | * Returns pointer to cpumask if some remote flushing remains to be | ||
303 | * done. The returned pointer is valid till preemption is re-enabled. | ||
298 | */ | 304 | */ |
299 | int uv_flush_tlb_others(cpumask_t *cpumaskp, struct mm_struct *mm, | 305 | const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, |
300 | unsigned long va) | 306 | struct mm_struct *mm, |
307 | unsigned long va, unsigned int cpu) | ||
301 | { | 308 | { |
309 | static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask); | ||
310 | struct cpumask *flush_mask = &__get_cpu_var(flush_tlb_mask); | ||
302 | int i; | 311 | int i; |
303 | int bit; | 312 | int bit; |
304 | int blade; | 313 | int blade; |
305 | int cpu; | 314 | int uv_cpu; |
306 | int this_blade; | 315 | int this_blade; |
307 | int locals = 0; | 316 | int locals = 0; |
308 | struct bau_desc *bau_desc; | 317 | struct bau_desc *bau_desc; |
309 | 318 | ||
310 | cpu = uv_blade_processor_id(); | 319 | WARN_ON(!in_atomic()); |
320 | |||
321 | cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu)); | ||
322 | |||
323 | uv_cpu = uv_blade_processor_id(); | ||
311 | this_blade = uv_numa_blade_id(); | 324 | this_blade = uv_numa_blade_id(); |
312 | bau_desc = __get_cpu_var(bau_control).descriptor_base; | 325 | bau_desc = __get_cpu_var(bau_control).descriptor_base; |
313 | bau_desc += UV_ITEMS_PER_DESCRIPTOR * cpu; | 326 | bau_desc += UV_ITEMS_PER_DESCRIPTOR * uv_cpu; |
314 | 327 | ||
315 | bau_nodes_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); | 328 | bau_nodes_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); |
316 | 329 | ||
317 | i = 0; | 330 | i = 0; |
318 | for_each_cpu_mask(bit, *cpumaskp) { | 331 | for_each_cpu(bit, flush_mask) { |
319 | blade = uv_cpu_to_blade_id(bit); | 332 | blade = uv_cpu_to_blade_id(bit); |
320 | BUG_ON(blade > (UV_DISTRIBUTION_SIZE - 1)); | 333 | BUG_ON(blade > (UV_DISTRIBUTION_SIZE - 1)); |
321 | if (blade == this_blade) { | 334 | if (blade == this_blade) { |
@@ -330,17 +343,17 @@ int uv_flush_tlb_others(cpumask_t *cpumaskp, struct mm_struct *mm, | |||
330 | * no off_node flushing; return status for local node | 343 | * no off_node flushing; return status for local node |
331 | */ | 344 | */ |
332 | if (locals) | 345 | if (locals) |
333 | return 0; | 346 | return flush_mask; |
334 | else | 347 | else |
335 | return 1; | 348 | return NULL; |
336 | } | 349 | } |
337 | __get_cpu_var(ptcstats).requestor++; | 350 | __get_cpu_var(ptcstats).requestor++; |
338 | __get_cpu_var(ptcstats).ntargeted += i; | 351 | __get_cpu_var(ptcstats).ntargeted += i; |
339 | 352 | ||
340 | bau_desc->payload.address = va; | 353 | bau_desc->payload.address = va; |
341 | bau_desc->payload.sending_cpu = smp_processor_id(); | 354 | bau_desc->payload.sending_cpu = cpu; |
342 | 355 | ||
343 | return uv_flush_send_and_wait(cpu, this_blade, bau_desc, cpumaskp); | 356 | return uv_flush_send_and_wait(uv_cpu, this_blade, bau_desc, flush_mask); |
344 | } | 357 | } |
345 | 358 | ||
346 | /* | 359 | /* |