Skip to content

Commit c942919

Browse files
Sebastian Andrzej SiewiorKAGA-KOKO
authored andcommitted
cpu: Make atomic hotplug callbacks run with interrupts disabled on UP
On SMP systems the CPU hotplug callbacks in the "starting" range are invoked while the CPU is brought up and interrupts are still disabled. Callbacks which are added later are invoked via the hotplug-thread on the target CPU and interrupts are explicitly disabled. In the UP case callbacks which are added later are invoked directly without the thread indirection. This is in principle okay since there is just one CPU but those callbacks are invoked with interrupt disabled code. That's incorrect as those callbacks assume interrupt disabled context. Disable interrupts before invoking the callbacks on UP if the state is atomic and interrupts are expected to be disabled. The "save" part is required because this is also invoked early in the boot process while interrupts are disabled and must not be enabled prematurely. Fixes: 06ddd17 ("sched/smp: Always define is_percpu_thread() and scheduler_ipi()") Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://patch.msgid.link/20251127144723.ev9DuXXR@linutronix.de
1 parent cb01581 commit c942919

1 file changed

Lines changed: 16 additions & 9 deletions

File tree

kernel/cpu.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,14 @@ static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
249249
return ret;
250250
}
251251

252+
/*
253+
* The former STARTING/DYING states, ran with IRQs disabled and must not fail.
254+
*/
255+
static bool cpuhp_is_atomic_state(enum cpuhp_state state)
256+
{
257+
return CPUHP_AP_IDLE_DEAD <= state && state < CPUHP_AP_ONLINE;
258+
}
259+
252260
#ifdef CONFIG_SMP
253261
static bool cpuhp_is_ap_state(enum cpuhp_state state)
254262
{
@@ -271,14 +279,6 @@ static inline void complete_ap_thread(struct cpuhp_cpu_state *st, bool bringup)
271279
complete(done);
272280
}
273281

274-
/*
275-
* The former STARTING/DYING states, ran with IRQs disabled and must not fail.
276-
*/
277-
static bool cpuhp_is_atomic_state(enum cpuhp_state state)
278-
{
279-
return CPUHP_AP_IDLE_DEAD <= state && state < CPUHP_AP_ONLINE;
280-
}
281-
282282
/* Synchronization state management */
283283
enum cpuhp_sync_state {
284284
SYNC_STATE_DEAD,
@@ -2364,7 +2364,14 @@ static int cpuhp_issue_call(int cpu, enum cpuhp_state state, bool bringup,
23642364
else
23652365
ret = cpuhp_invoke_callback(cpu, state, bringup, node, NULL);
23662366
#else
2367-
ret = cpuhp_invoke_callback(cpu, state, bringup, node, NULL);
2367+
if (cpuhp_is_atomic_state(state)) {
2368+
guard(irqsave)();
2369+
ret = cpuhp_invoke_callback(cpu, state, bringup, node, NULL);
2370+
/* STARTING/DYING must not fail! */
2371+
WARN_ON_ONCE(ret);
2372+
} else {
2373+
ret = cpuhp_invoke_callback(cpu, state, bringup, node, NULL);
2374+
}
23682375
#endif
23692376
BUG_ON(ret && !bringup);
23702377
return ret;

0 commit comments

Comments
 (0)