Skip to content

Commit

Permalink
printk/panic: Add option to allow non-panic CPUs to write to the ring…
Browse files Browse the repository at this point in the history
… buffer.

Commit 779dbc2 ("printk: Avoid non-panic CPUs writing to ringbuffer")
aimed to isolate panic-related messages. However, when panic() itself
malfunctions, messages from non-panic CPUs become crucial for debugging.

While commit bcc954c ("printk/panic: Allow cpu backtraces to
be written into ringbuffer during panic") enables non-panic CPU
backtraces, it may not provide sufficient diagnostic information.

Introduce the "debug_non_panic_cpus" command-line option, enabling
non-panic CPU messages to be stored in the ring buffer during a panic.
This also prevents discarding non-finalized messages from non-panic CPUs
during console flushing, providing a more comprehensive view of system
state during critical failures.

Link: https://lore.kernel.org/all/Z8cLEkqLL2IOyNIj@pathway/
Signed-off-by: Donghyeok Choe <d7271.choe@samsung.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20250318022320.2428155-1-d7271.choe@samsung.com
[pmladek@suse.com: Added documentation, added module_parameter, removed printk_ prefix.]
Tested-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
  • Loading branch information
Donghyeok Choe authored and Petr Mladek committed Mar 20, 2025
1 parent 2f1f778 commit c1aa3da
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 6 deletions.
8 changes: 8 additions & 0 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5013,6 +5013,14 @@
Format: <bool>
default: 0 (auto_verbose is enabled)

printk.debug_non_panic_cpus=
Allows storing messages from non-panic CPUs into
the printk log buffer during panic(). They are
flushed to consoles by the panic-CPU on
a best-effort basis.
Format: <bool> (1/Y/y=enable, 0/N/n=disable)
Default: disabled

printk.devkmsg={on,off,ratelimit}
Control writing to /dev/kmsg.
on - unlimited logging to /dev/kmsg from userspace
Expand Down
1 change: 1 addition & 0 deletions kernel/printk/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ struct dev_printk_info;

extern struct printk_ringbuffer *prb;
extern bool printk_kthreads_running;
extern bool debug_non_panic_cpus;

__printf(4, 0)
int vprintk_store(int facility, int level,
Expand Down
20 changes: 19 additions & 1 deletion kernel/printk/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -2375,6 +2375,22 @@ void printk_legacy_allow_panic_sync(void)
}
}

bool __read_mostly debug_non_panic_cpus;

#ifdef CONFIG_PRINTK_CALLER
static int __init debug_non_panic_cpus_setup(char *str)
{
debug_non_panic_cpus = true;
pr_info("allow messages from non-panic CPUs in panic()\n");

return 0;
}
early_param("debug_non_panic_cpus", debug_non_panic_cpus_setup);
module_param(debug_non_panic_cpus, bool, 0644);
MODULE_PARM_DESC(debug_non_panic_cpus,
"allow messages from non-panic CPUs in panic()");
#endif

asmlinkage int vprintk_emit(int facility, int level,
const struct dev_printk_info *dev_info,
const char *fmt, va_list args)
Expand All @@ -2391,7 +2407,9 @@ asmlinkage int vprintk_emit(int facility, int level,
* non-panic CPUs are generating any messages, they will be
* silently dropped.
*/
if (other_cpu_in_panic() && !panic_triggering_all_cpu_backtrace)
if (other_cpu_in_panic() &&
!debug_non_panic_cpus &&
!panic_triggering_all_cpu_backtrace)
return 0;

printk_get_console_flush_type(&ft);
Expand Down
13 changes: 8 additions & 5 deletions kernel/printk/printk_ringbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2133,20 +2133,23 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
* there may be other finalized records beyond that
* need to be printed for a panic situation. If this
* is the panic CPU, skip this
* non-existent/non-finalized record unless it is
* at or beyond the head, in which case it is not
* possible to continue.
* non-existent/non-finalized record unless non-panic
* CPUs are still running and their debugging is
* explicitly enabled.
*
* Note that new messages printed on panic CPU are
* finalized when we are here. The only exception
* might be the last message without trailing newline.
* But it would have the sequence number returned
* by "prb_next_reserve_seq() - 1".
*/
if (this_cpu_in_panic() && ((*seq + 1) < prb_next_reserve_seq(rb)))
if (this_cpu_in_panic() &&
(!debug_non_panic_cpus || legacy_allow_panic_sync) &&
((*seq + 1) < prb_next_reserve_seq(rb))) {
(*seq)++;
else
} else {
return false;
}
}
}

Expand Down

0 comments on commit c1aa3da

Please sign in to comment.