diff options
author | cpw@sgi.com <cpw@sgi.com> | 2011-06-21 08:21:31 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-06-21 08:50:33 -0400 |
commit | 442d3924926c62741912d8a930220af253922007 (patch) | |
tree | 7ea9f7c0e8133037d36e31e7c4f033fae95abcca /arch | |
parent | a456eaab87461e33d94e748565eabd474283a475 (diff) |
x86, UV: Remove cpumask_t from the stack
Remove the large stack-resident cpumask_t from
reset_with_ipi()'s stack by allocating one per uvhub.
Due to the limited size of the stack the potentially huge cpumask_t may
cause stack overrun. We haven't seen it happen yet, but we need to make it
a practice not to push such structures onto the stack.
Signed-off-by: Cliff Wickman <cpw@sgi.com>
Reviewed-by: Pekka Enberg <penberg@kernel.org>
Link: http://lkml.kernel.org/r/20110621122242.832589130@sgi.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/uv/uv_bau.h | 1 | ||||
-rw-r--r-- | arch/x86/platform/uv/tlb_uv.c | 19 |
2 files changed, 16 insertions, 4 deletions
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index fa6a48e264b3..16ce58c6d252 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h | |||
@@ -488,6 +488,7 @@ struct bau_control { | |||
488 | struct bau_control *uvhub_master; | 488 | struct bau_control *uvhub_master; |
489 | struct bau_control *socket_master; | 489 | struct bau_control *socket_master; |
490 | struct ptc_stats *statp; | 490 | struct ptc_stats *statp; |
491 | cpumask_t *cpumask; | ||
491 | unsigned long timeout_interval; | 492 | unsigned long timeout_interval; |
492 | unsigned long set_bau_on_time; | 493 | unsigned long set_bau_on_time; |
493 | atomic_t active_descriptor_count; | 494 | atomic_t active_descriptor_count; |
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 191ef28ea173..5265842b8d0b 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c | |||
@@ -375,13 +375,13 @@ static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp) | |||
375 | int pnode; | 375 | int pnode; |
376 | int apnode; | 376 | int apnode; |
377 | int maskbits; | 377 | int maskbits; |
378 | cpumask_t mask; | ||
379 | int sender = bcp->cpu; | 378 | int sender = bcp->cpu; |
379 | cpumask_t *mask = bcp->uvhub_master->cpumask; | ||
380 | struct bau_control *smaster = bcp->socket_master; | 380 | struct bau_control *smaster = bcp->socket_master; |
381 | struct reset_args reset_args; | 381 | struct reset_args reset_args; |
382 | 382 | ||
383 | reset_args.sender = sender; | 383 | reset_args.sender = sender; |
384 | cpus_clear(mask); | 384 | cpus_clear(*mask); |
385 | /* find a single cpu for each uvhub in this distribution mask */ | 385 | /* find a single cpu for each uvhub in this distribution mask */ |
386 | maskbits = sizeof(struct pnmask) * BITSPERBYTE; | 386 | maskbits = sizeof(struct pnmask) * BITSPERBYTE; |
387 | /* each bit is a pnode relative to the partition base pnode */ | 387 | /* each bit is a pnode relative to the partition base pnode */ |
@@ -391,11 +391,11 @@ static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp) | |||
391 | continue; | 391 | continue; |
392 | apnode = pnode + bcp->partition_base_pnode; | 392 | apnode = pnode + bcp->partition_base_pnode; |
393 | cpu = pnode_to_first_cpu(apnode, smaster); | 393 | cpu = pnode_to_first_cpu(apnode, smaster); |
394 | cpu_set(cpu, mask); | 394 | cpu_set(cpu, *mask); |
395 | } | 395 | } |
396 | 396 | ||
397 | /* IPI all cpus; preemption is already disabled */ | 397 | /* IPI all cpus; preemption is already disabled */ |
398 | smp_call_function_many(&mask, do_reset, (void *)&reset_args, 1); | 398 | smp_call_function_many(mask, do_reset, (void *)&reset_args, 1); |
399 | return; | 399 | return; |
400 | } | 400 | } |
401 | 401 | ||
@@ -1696,6 +1696,16 @@ static void make_per_cpu_thp(struct bau_control *smaster) | |||
1696 | } | 1696 | } |
1697 | 1697 | ||
1698 | /* | 1698 | /* |
1699 | * Each uvhub is to get a local cpumask. | ||
1700 | */ | ||
1701 | static void make_per_hub_cpumask(struct bau_control *hmaster) | ||
1702 | { | ||
1703 | int sz = sizeof(cpumask_t); | ||
1704 | |||
1705 | hmaster->cpumask = kzalloc_node(sz, GFP_KERNEL, hmaster->osnode); | ||
1706 | } | ||
1707 | |||
1708 | /* | ||
1699 | * Initialize all the per_cpu information for the cpu's on a given socket, | 1709 | * Initialize all the per_cpu information for the cpu's on a given socket, |
1700 | * given what has been gathered into the socket_desc struct. | 1710 | * given what has been gathered into the socket_desc struct. |
1701 | * And reports the chosen hub and socket masters back to the caller. | 1711 | * And reports the chosen hub and socket masters back to the caller. |
@@ -1765,6 +1775,7 @@ static int __init summarize_uvhub_sockets(int nuvhubs, | |||
1765 | socket++; | 1775 | socket++; |
1766 | socket_mask = (socket_mask >> 1); | 1776 | socket_mask = (socket_mask >> 1); |
1767 | } | 1777 | } |
1778 | make_per_hub_cpumask(hmaster); | ||
1768 | } | 1779 | } |
1769 | return 0; | 1780 | return 0; |
1770 | } | 1781 | } |