Skip to content

Commit 84dbf66

Browse files
srikardmpe
authored andcommitted
powerpc/smp: Use GFP_ATOMIC while allocating tmp mask
Qian Cai reported a regression where CPU Hotplug fails with the latest powerpc/next BUG: sleeping function called from invalid context at mm/slab.h:494 in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 0, name: swapper/88 no locks held by swapper/88/0. irq event stamp: 18074448 hardirqs last enabled at (18074447): [<c0000000001a2a7c>] tick_nohz_idle_enter+0x9c/0x110 hardirqs last disabled at (18074448): [<c000000000106798>] do_idle+0x138/0x3b0 do_idle at kernel/sched/idle.c:253 (discriminator 1) softirqs last enabled at (18074440): [<c0000000000bbec4>] irq_enter_rcu+0x94/0xa0 softirqs last disabled at (18074439): [<c0000000000bbea0>] irq_enter_rcu+0x70/0xa0 CPU: 88 PID: 0 Comm: swapper/88 Tainted: G W 5.9.0-rc8-next-20201007 #1 Call Trace: [c00020000a4bfcf0] [c000000000649e98] dump_stack+0xec/0x144 (unreliable) [c00020000a4bfd30] [c0000000000f6c34] ___might_sleep+0x2f4/0x310 [c00020000a4bfdb0] [c000000000354f94] slab_pre_alloc_hook.constprop.82+0x124/0x190 [c00020000a4bfe00] [c00000000035e9e8] __kmalloc_node+0x88/0x3a0 slab_alloc_node at mm/slub.c:2817 (inlined by) __kmalloc_node at mm/slub.c:4013 [c00020000a4bfe80] [c0000000006494d8] alloc_cpumask_var_node+0x38/0x80 kmalloc_node at include/linux/slab.h:577 (inlined by) alloc_cpumask_var_node at lib/cpumask.c:116 [c00020000a4bfef0] [c00000000003eedc] start_secondary+0x27c/0x800 update_mask_by_l2 at arch/powerpc/kernel/smp.c:1267 (inlined by) add_cpu_to_masks at arch/powerpc/kernel/smp.c:1387 (inlined by) start_secondary at arch/powerpc/kernel/smp.c:1420 [c00020000a4bff90] [c00000000000c468] start_secondary_resume+0x10/0x14 Allocating a temporary mask while performing a CPU Hotplug operation with CONFIG_CPUMASK_OFFSTACK enabled, leads to calling a sleepable function from a atomic context. Fix this by allocating the temporary mask with GFP_ATOMIC flag. Also instead of having to allocate twice, allocate the mask in the caller so that we only have to allocate once. If the allocation fails, assume the mask to be same as sibling mask, which will make the scheduler to drop this domain for this CPU. Fixes: 70a9408 ("powerpc/smp: Optimize update_coregroup_mask") Fixes: 3ab33d6 ("powerpc/smp: Optimize update_mask_by_l2") Reported-by: Qian Cai <cai@redhat.com> Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20201019042716.106234-3-srikar@linux.vnet.ibm.com
1 parent 966730a commit 84dbf66

1 file changed

Lines changed: 31 additions & 26 deletions

File tree

arch/powerpc/kernel/smp.c

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,38 +1240,33 @@ static struct device_node *cpu_to_l2cache(int cpu)
12401240
return cache;
12411241
}
12421242

1243-
static bool update_mask_by_l2(int cpu)
1243+
static bool update_mask_by_l2(int cpu, cpumask_var_t *mask)
12441244
{
12451245
struct cpumask *(*submask_fn)(int) = cpu_sibling_mask;
12461246
struct device_node *l2_cache, *np;
1247-
cpumask_var_t mask;
12481247
int i;
12491248

12501249
if (has_big_cores)
12511250
submask_fn = cpu_smallcore_mask;
12521251

12531252
l2_cache = cpu_to_l2cache(cpu);
1254-
if (!l2_cache) {
1255-
/*
1256-
* If no l2cache for this CPU, assume all siblings to share
1257-
* cache with this CPU.
1258-
*/
1253+
if (!l2_cache || !*mask) {
1254+
/* Assume only core siblings share cache with this CPU */
12591255
for_each_cpu(i, submask_fn(cpu))
12601256
set_cpus_related(cpu, i, cpu_l2_cache_mask);
12611257

12621258
return false;
12631259
}
12641260

1265-
alloc_cpumask_var_node(&mask, GFP_KERNEL, cpu_to_node(cpu));
1266-
cpumask_and(mask, cpu_online_mask, cpu_cpu_mask(cpu));
1261+
cpumask_and(*mask, cpu_online_mask, cpu_cpu_mask(cpu));
12671262

12681263
/* Update l2-cache mask with all the CPUs that are part of submask */
12691264
or_cpumasks_related(cpu, cpu, submask_fn, cpu_l2_cache_mask);
12701265

12711266
/* Skip all CPUs already part of current CPU l2-cache mask */
1272-
cpumask_andnot(mask, mask, cpu_l2_cache_mask(cpu));
1267+
cpumask_andnot(*mask, *mask, cpu_l2_cache_mask(cpu));
12731268

1274-
for_each_cpu(i, mask) {
1269+
for_each_cpu(i, *mask) {
12751270
/*
12761271
* when updating the marks the current CPU has not been marked
12771272
* online, but we need to update the cache masks
@@ -1281,15 +1276,14 @@ static bool update_mask_by_l2(int cpu)
12811276
/* Skip all CPUs already part of current CPU l2-cache */
12821277
if (np == l2_cache) {
12831278
or_cpumasks_related(cpu, i, submask_fn, cpu_l2_cache_mask);
1284-
cpumask_andnot(mask, mask, submask_fn(i));
1279+
cpumask_andnot(*mask, *mask, submask_fn(i));
12851280
} else {
1286-
cpumask_andnot(mask, mask, cpu_l2_cache_mask(i));
1281+
cpumask_andnot(*mask, *mask, cpu_l2_cache_mask(i));
12871282
}
12881283

12891284
of_node_put(np);
12901285
}
12911286
of_node_put(l2_cache);
1292-
free_cpumask_var(mask);
12931287

12941288
return true;
12951289
}
@@ -1332,40 +1326,46 @@ static inline void add_cpu_to_smallcore_masks(int cpu)
13321326
}
13331327
}
13341328

1335-
static void update_coregroup_mask(int cpu)
1329+
static void update_coregroup_mask(int cpu, cpumask_var_t *mask)
13361330
{
13371331
struct cpumask *(*submask_fn)(int) = cpu_sibling_mask;
1338-
cpumask_var_t mask;
13391332
int coregroup_id = cpu_to_coregroup_id(cpu);
13401333
int i;
13411334

1342-
alloc_cpumask_var_node(&mask, GFP_KERNEL, cpu_to_node(cpu));
1343-
cpumask_and(mask, cpu_online_mask, cpu_cpu_mask(cpu));
1344-
13451335
if (shared_caches)
13461336
submask_fn = cpu_l2_cache_mask;
13471337

1338+
if (!*mask) {
1339+
/* Assume only siblings are part of this CPU's coregroup */
1340+
for_each_cpu(i, submask_fn(cpu))
1341+
set_cpus_related(cpu, i, cpu_coregroup_mask);
1342+
1343+
return;
1344+
}
1345+
1346+
cpumask_and(*mask, cpu_online_mask, cpu_cpu_mask(cpu));
1347+
13481348
/* Update coregroup mask with all the CPUs that are part of submask */
13491349
or_cpumasks_related(cpu, cpu, submask_fn, cpu_coregroup_mask);
13501350

13511351
/* Skip all CPUs already part of coregroup mask */
1352-
cpumask_andnot(mask, mask, cpu_coregroup_mask(cpu));
1352+
cpumask_andnot(*mask, *mask, cpu_coregroup_mask(cpu));
13531353

1354-
for_each_cpu(i, mask) {
1354+
for_each_cpu(i, *mask) {
13551355
/* Skip all CPUs not part of this coregroup */
13561356
if (coregroup_id == cpu_to_coregroup_id(i)) {
13571357
or_cpumasks_related(cpu, i, submask_fn, cpu_coregroup_mask);
1358-
cpumask_andnot(mask, mask, submask_fn(i));
1358+
cpumask_andnot(*mask, *mask, submask_fn(i));
13591359
} else {
1360-
cpumask_andnot(mask, mask, cpu_coregroup_mask(i));
1360+
cpumask_andnot(*mask, *mask, cpu_coregroup_mask(i));
13611361
}
13621362
}
1363-
free_cpumask_var(mask);
13641363
}
13651364

13661365
static void add_cpu_to_masks(int cpu)
13671366
{
13681367
int first_thread = cpu_first_thread_sibling(cpu);
1368+
cpumask_var_t mask;
13691369
int i;
13701370

13711371
/*
@@ -1379,10 +1379,15 @@ static void add_cpu_to_masks(int cpu)
13791379
set_cpus_related(i, cpu, cpu_sibling_mask);
13801380

13811381
add_cpu_to_smallcore_masks(cpu);
1382-
update_mask_by_l2(cpu);
1382+
1383+
/* In CPU-hotplug path, hence use GFP_ATOMIC */
1384+
alloc_cpumask_var_node(&mask, GFP_ATOMIC, cpu_to_node(cpu));
1385+
update_mask_by_l2(cpu, &mask);
13831386

13841387
if (has_coregroup_support())
1385-
update_coregroup_mask(cpu);
1388+
update_coregroup_mask(cpu, &mask);
1389+
1390+
free_cpumask_var(mask);
13861391
}
13871392

13881393
/* Activate a secondary processor. */

0 commit comments

Comments
 (0)