x86, UV: Remove cpumask_t from the stack
authorcpw@sgi.com <cpw@sgi.com>
Tue, 21 Jun 2011 12:21:31 +0000 (07:21 -0500)
committerIngo Molnar <mingo@elte.hu>
Tue, 21 Jun 2011 12:50:33 +0000 (14:50 +0200)
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>
arch/x86/include/asm/uv/uv_bau.h
arch/x86/platform/uv/tlb_uv.c

index fa6a48e..16ce58c 100644 (file)
@@ -488,6 +488,7 @@ struct bau_control {
        struct bau_control      *uvhub_master;
        struct bau_control      *socket_master;
        struct ptc_stats        *statp;
+       cpumask_t               *cpumask;
        unsigned long           timeout_interval;
        unsigned long           set_bau_on_time;
        atomic_t                active_descriptor_count;
index 191ef28..5265842 100644 (file)
@@ -375,13 +375,13 @@ static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
        int pnode;
        int apnode;
        int maskbits;
-       cpumask_t mask;
        int sender = bcp->cpu;
+       cpumask_t *mask = bcp->uvhub_master->cpumask;
        struct bau_control *smaster = bcp->socket_master;
        struct reset_args reset_args;
 
        reset_args.sender = sender;
-       cpus_clear(mask);
+       cpus_clear(*mask);
        /* find a single cpu for each uvhub in this distribution mask */
        maskbits = sizeof(struct pnmask) * BITSPERBYTE;
        /* 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)
                        continue;
                apnode = pnode + bcp->partition_base_pnode;
                cpu = pnode_to_first_cpu(apnode, smaster);
-               cpu_set(cpu, mask);
+               cpu_set(cpu, *mask);
        }
 
        /* IPI all cpus; preemption is already disabled */
-       smp_call_function_many(&mask, do_reset, (void *)&reset_args, 1);
+       smp_call_function_many(mask, do_reset, (void *)&reset_args, 1);
        return;
 }
 
@@ -1695,6 +1695,16 @@ static void make_per_cpu_thp(struct bau_control *smaster)
        }
 }
 
+/*
+ * Each uvhub is to get a local cpumask.
+ */
+static void make_per_hub_cpumask(struct bau_control *hmaster)
+{
+       int sz = sizeof(cpumask_t);
+
+       hmaster->cpumask = kzalloc_node(sz, GFP_KERNEL, hmaster->osnode);
+}
+
 /*
  * Initialize all the per_cpu information for the cpu's on a given socket,
  * given what has been gathered into the socket_desc struct.
@@ -1765,6 +1775,7 @@ static int __init summarize_uvhub_sockets(int nuvhubs,
                        socket++;
                        socket_mask = (socket_mask >> 1);
                }
+               make_per_hub_cpumask(hmaster);
        }
        return 0;
 }