This is a note to let you know that I've just added the patch titled printk: Defer legacy printing when holding printk_cpu_sync to the 6.12-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: printk-defer-legacy-printing-when-holding-printk_cpu.patch and it can be found in the queue-6.12 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit a5ba1301f49e51058910567a26f2c8d42d372092 Author: John Ogness <john.ogness@xxxxxxxxxxxxx> Date: Mon Dec 9 12:23:46 2024 +0106 printk: Defer legacy printing when holding printk_cpu_sync [ Upstream commit 0161e2d6950fe66cf6ac1c10d945bae971f33667 ] 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@xxxxxxxxxxx> Closes: https://lore.kernel.org/r/20240715232052.73eb7fb1@xxxxxxxxxxxxxxxxxxxx Signed-off-by: John Ogness <john.ogness@xxxxxxxxxxxxx> Fixes: 55d6af1d6688 ("lib/nmi_backtrace: explicitly serialize banner and regs") Reviewed-by: Petr Mladek <pmladek@xxxxxxxx> Link: https://lore.kernel.org/r/20241209111746.192559-3-john.ogness@xxxxxxxxxxxxx Signed-off-by: Petr Mladek <pmladek@xxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h index 3fcb48502adbd..5eef70000b439 100644 --- a/kernel/printk/internal.h +++ b/kernel/printk/internal.h @@ -335,3 +335,9 @@ bool printk_get_next_message(struct printk_message *pmsg, u64 seq, void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped); void console_prepend_replay(struct printk_message *pmsg); #endif + +#ifdef CONFIG_SMP +bool is_printk_cpu_sync_owner(void); +#else +static inline bool is_printk_cpu_sync_owner(void) { return false; } +#endif diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index beb808f4c367b..7530df62ff7cb 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -4892,6 +4892,11 @@ void console_try_replay_all(void) static atomic_t printk_cpu_sync_owner = ATOMIC_INIT(-1); static atomic_t printk_cpu_sync_nested = ATOMIC_INIT(0); +bool is_printk_cpu_sync_owner(void) +{ + return (atomic_read(&printk_cpu_sync_owner) == raw_smp_processor_id()); +} + /** * __printk_cpu_sync_wait() - Busy wait until the printk cpu-reentrant * spinning lock is not owned by any CPU. diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 2b35a9d3919d8..e6198da7c7354 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -43,10 +43,15 @@ bool is_printk_legacy_deferred(void) /* * The per-CPU variable @printk_context can be read safely in any * context. CPU migration is always disabled when set. + * + * A context holding the printk_cpu_sync must not spin waiting for + * another CPU. For legacy printing, it could be the console_lock + * or the port lock. */ return (force_legacy_kthread() || this_cpu_read(printk_context) || - in_nmi()); + in_nmi() || + is_printk_cpu_sync_owner()); } asmlinkage int vprintk(const char *fmt, va_list args)