Skip to content

Commit 00df35f

Browse files
paulmckIngo Molnar
authored andcommitted
cpu: Defer smpboot kthread unparking until CPU known to scheduler
Currently, smpboot_unpark_threads() is invoked before the incoming CPU has been added to the scheduler's runqueue structures. This might potentially cause the unparked kthread to run on the wrong CPU, since the correct CPU isn't fully set up yet. That causes a sporadic, hard to debug boot crash triggering on some systems, reported by Borislav Petkov, and bisected down to: 2a442c9 ("x86: Use common outgoing-CPU-notification code") This patch places smpboot_unpark_threads() in a CPU hotplug notifier with priority set so that these kthreads are unparked just after the CPU has been added to the runqueues. Reported-and-tested-by: Borislav Petkov <bp@suse.de> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 4bfe186 commit 00df35f

File tree

3 files changed

+34
-3
lines changed

3 files changed

+34
-3
lines changed

include/linux/cpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ enum {
7373
/* migration should happen before other stuff but after perf */
7474
CPU_PRI_PERF = 20,
7575
CPU_PRI_MIGRATION = 10,
76+
CPU_PRI_SMPBOOT = 9,
7677
/* bring up workqueues before normal notifiers and down after */
7778
CPU_PRI_WORKQUEUE_UP = 5,
7879
CPU_PRI_WORKQUEUE_DOWN = -5,
@@ -165,6 +166,7 @@ static inline void __unregister_cpu_notifier(struct notifier_block *nb)
165166
}
166167
#endif
167168

169+
void smpboot_thread_init(void);
168170
int cpu_up(unsigned int cpu);
169171
void notify_cpu_starting(unsigned int cpu);
170172
extern void cpu_maps_update_begin(void);

init/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ static noinline void __init_refok rest_init(void)
384384
int pid;
385385

386386
rcu_scheduler_starting();
387+
smpboot_thread_init();
387388
/*
388389
* We need to spawn init first so that it obtains pid 1, however
389390
* the init task will end up wanting to create kthreads, which, if

kernel/cpu.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,37 @@ int __ref cpu_down(unsigned int cpu)
448448
EXPORT_SYMBOL(cpu_down);
449449
#endif /*CONFIG_HOTPLUG_CPU*/
450450

451+
/*
452+
* Unpark per-CPU smpboot kthreads at CPU-online time.
453+
*/
454+
static int smpboot_thread_call(struct notifier_block *nfb,
455+
unsigned long action, void *hcpu)
456+
{
457+
int cpu = (long)hcpu;
458+
459+
switch (action & ~CPU_TASKS_FROZEN) {
460+
461+
case CPU_ONLINE:
462+
smpboot_unpark_threads(cpu);
463+
break;
464+
465+
default:
466+
break;
467+
}
468+
469+
return NOTIFY_OK;
470+
}
471+
472+
static struct notifier_block smpboot_thread_notifier = {
473+
.notifier_call = smpboot_thread_call,
474+
.priority = CPU_PRI_SMPBOOT,
475+
};
476+
477+
void __cpuinit smpboot_thread_init(void)
478+
{
479+
register_cpu_notifier(&smpboot_thread_notifier);
480+
}
481+
451482
/* Requires cpu_add_remove_lock to be held */
452483
static int _cpu_up(unsigned int cpu, int tasks_frozen)
453484
{
@@ -487,9 +518,6 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen)
487518
goto out_notify;
488519
BUG_ON(!cpu_online(cpu));
489520

490-
/* Wake the per cpu threads */
491-
smpboot_unpark_threads(cpu);
492-
493521
/* Now call notifier in preparation. */
494522
cpu_notify(CPU_ONLINE | mod, hcpu);
495523

0 commit comments

Comments
 (0)