Skip to content

Commit 0161e2d

Browse files
jognesspmladek
authored andcommitted
printk: Defer legacy printing when holding printk_cpu_sync
The documentation of printk_cpu_sync_get() clearly states that the owner must never perform any activities where it waits for a CPU. For legacy printing there can be spinning on the console_lock and on the port lock. Therefore legacy printing must be deferred when holding the printk_cpu_sync. Note that in the case of emergency states, atomic consoles are not prevented from printing when printk is deferred. This is appropriate because they do not spin-wait indefinitely for other CPUs. Reported-by: Rik van Riel <riel@surriel.com> Closes: https://lore.kernel.org/r/20240715232052.73eb7fb1@imladris.surriel.com Signed-off-by: John Ogness <john.ogness@linutronix.de> Fixes: 55d6af1 ("lib/nmi_backtrace: explicitly serialize banner and regs") Reviewed-by: Petr Mladek <pmladek@suse.com> Link: https://lore.kernel.org/r/20241209111746.192559-3-john.ogness@linutronix.de Signed-off-by: Petr Mladek <pmladek@suse.com>
1 parent f1c21cf commit 0161e2d

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

kernel/printk/internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,3 +338,9 @@ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
338338
void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped);
339339
void console_prepend_replay(struct printk_message *pmsg);
340340
#endif
341+
342+
#ifdef CONFIG_SMP
343+
bool is_printk_cpu_sync_owner(void);
344+
#else
345+
static inline bool is_printk_cpu_sync_owner(void) { return false; }
346+
#endif

kernel/printk/printk.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4922,6 +4922,11 @@ void console_try_replay_all(void)
49224922
static atomic_t printk_cpu_sync_owner = ATOMIC_INIT(-1);
49234923
static atomic_t printk_cpu_sync_nested = ATOMIC_INIT(0);
49244924

4925+
bool is_printk_cpu_sync_owner(void)
4926+
{
4927+
return (atomic_read(&printk_cpu_sync_owner) == raw_smp_processor_id());
4928+
}
4929+
49254930
/**
49264931
* __printk_cpu_sync_wait() - Busy wait until the printk cpu-reentrant
49274932
* spinning lock is not owned by any CPU.

kernel/printk/printk_safe.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,15 @@ bool is_printk_legacy_deferred(void)
6161
/*
6262
* The per-CPU variable @printk_context can be read safely in any
6363
* context. CPU migration is always disabled when set.
64+
*
65+
* A context holding the printk_cpu_sync must not spin waiting for
66+
* another CPU. For legacy printing, it could be the console_lock
67+
* or the port lock.
6468
*/
6569
return (force_legacy_kthread() ||
6670
this_cpu_read(printk_context) ||
67-
in_nmi());
71+
in_nmi() ||
72+
is_printk_cpu_sync_owner());
6873
}
6974

7075
asmlinkage int vprintk(const char *fmt, va_list args)

0 commit comments

Comments
 (0)