From e9cec4487cb789645a8c84b13a9ce54c2d89e3bb Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 26 Feb 2025 16:59:01 -0300 Subject: [PATCH 1/7] printk: Rename suspend_console to console_suspend_all The function suspend_console has a misleading name, since it suspends all consoles, so rename it accordingly. Signed-off-by: Marcos Paulo de Souza Reviewed-by: Petr Mladek Reviewed-by: John Ogness Link: https://lore.kernel.org/r/20250226-printk-renaming-v1-1-0b878577f2e6@suse.com [pmladek@suse.com: Fixed typo in the commit message.] Signed-off-by: Petr Mladek --- include/linux/console.h | 2 +- kernel/kexec_core.c | 2 +- kernel/power/hibernate.c | 8 ++++---- kernel/power/suspend.c | 2 +- kernel/printk/printk.c | 4 ++-- tools/power/pm-graph/config/custom-timeline-functions.cfg | 2 +- tools/power/pm-graph/sleepgraph.py | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/linux/console.h b/include/linux/console.h index eba367bf605da..fa5941f4f9c54 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -648,7 +648,7 @@ static inline void console_sysfs_notify(void) extern bool console_suspend_enabled; /* Suspend and resume console messages over PM events */ -extern void suspend_console(void); +extern void console_suspend_all(void); extern void resume_console(void); int mda_console_init(void); diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index c0caa14880c3b..8f95870030a33 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -1007,7 +1007,7 @@ int kernel_kexec(void) error = -EBUSY; goto Restore_console; } - suspend_console(); + console_suspend_all(); error = dpm_suspend_start(PMSG_FREEZE); if (error) goto Resume_console; diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 1f87aa01ba44f..a18f6016ce6ca 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -411,7 +411,7 @@ int hibernation_snapshot(int platform_mode) goto Thaw; } - suspend_console(); + console_suspend_all(); pm_restrict_gfp_mask(); error = dpm_suspend(PMSG_FREEZE); @@ -547,7 +547,7 @@ int hibernation_restore(int platform_mode) int error; pm_prepare_console(); - suspend_console(); + console_suspend_all(); pm_restrict_gfp_mask(); error = dpm_suspend_start(PMSG_QUIESCE); if (!error) { @@ -586,7 +586,7 @@ int hibernation_platform_enter(void) goto Close; entering_platform_hibernation = true; - suspend_console(); + console_suspend_all(); error = dpm_suspend_start(PMSG_HIBERNATE); if (error) { if (hibernation_ops->recover) @@ -896,7 +896,7 @@ int hibernate_quiet_exec(int (*func)(void *data), void *data) if (error) goto dpm_complete; - suspend_console(); + console_suspend_all(); error = dpm_suspend(PMSG_FREEZE); if (error) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 09f8397bae15f..f296dd0a1a187 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -502,7 +502,7 @@ int suspend_devices_and_enter(suspend_state_t state) if (error) goto Close; - suspend_console(); + console_suspend_all(); suspend_test_start(); error = dpm_suspend_start(PMSG_SUSPEND); if (error) { diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 07668433644b8..0666d3e098972 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2733,11 +2733,11 @@ module_param_named(console_no_auto_verbose, printk_console_no_auto_verbose, bool MODULE_PARM_DESC(console_no_auto_verbose, "Disable console loglevel raise to highest on oops/panic/etc"); /** - * suspend_console - suspend the console subsystem + * console_suspend_all - suspend the console subsystem * * This disables printk() while we go into suspend states */ -void suspend_console(void) +void console_suspend_all(void) { struct console *con; diff --git a/tools/power/pm-graph/config/custom-timeline-functions.cfg b/tools/power/pm-graph/config/custom-timeline-functions.cfg index 4f80ad7d72755..80ba55250163d 100644 --- a/tools/power/pm-graph/config/custom-timeline-functions.cfg +++ b/tools/power/pm-graph/config/custom-timeline-functions.cfg @@ -122,7 +122,7 @@ freeze_processes: freeze_kernel_threads: pm_restrict_gfp_mask: acpi_suspend_begin: -suspend_console: +console_suspend_all: acpi_pm_prepare: syscore_suspend: arch_enable_nonboot_cpus_end: diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py index 918eae58b0b45..114c3d0c66192 100755 --- a/tools/power/pm-graph/sleepgraph.py +++ b/tools/power/pm-graph/sleepgraph.py @@ -210,7 +210,7 @@ class SystemValues: 'hibernate_preallocate_memory': {}, 'create_basic_memory_bitmaps': {}, 'swsusp_write': {}, - 'suspend_console': {}, + 'console_suspend_all': {}, 'acpi_pm_prepare': {}, 'syscore_suspend': {}, 'arch_enable_nonboot_cpus_end': {}, From 63830aef74188354806ea3c9043dd3929c6e47f3 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 26 Feb 2025 16:59:02 -0300 Subject: [PATCH 2/7] printk: Rename resume_console to console_resume_all The function resume_console has a misleading name, since it resumes all consoles, so rename it accordingly. Signed-off-by: Marcos Paulo de Souza Reviewed-by: Petr Mladek Reviewed-by: John Ogness Link: https://lore.kernel.org/r/20250226-printk-renaming-v1-2-0b878577f2e6@suse.com [pmladek@suse.com: Fixed typo in the commit message.] Signed-off-by: Petr Mladek --- include/linux/console.h | 2 +- kernel/kexec_core.c | 2 +- kernel/power/hibernate.c | 8 ++++---- kernel/power/suspend.c | 6 +++--- kernel/printk/printk.c | 2 +- tools/power/pm-graph/config/custom-timeline-functions.cfg | 2 +- tools/power/pm-graph/sleepgraph.py | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/linux/console.h b/include/linux/console.h index fa5941f4f9c54..0d48e0deb2139 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -649,7 +649,7 @@ extern bool console_suspend_enabled; /* Suspend and resume console messages over PM events */ extern void console_suspend_all(void); -extern void resume_console(void); +extern void console_resume_all(void); int mda_console_init(void); diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index 8f95870030a33..6fcc46f3eb39c 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -1061,7 +1061,7 @@ int kernel_kexec(void) Resume_devices: dpm_resume_end(PMSG_RESTORE); Resume_console: - resume_console(); + console_resume_all(); thaw_processes(); Restore_console: pm_restore_console(); diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index a18f6016ce6ca..c9f60670a2610 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -437,7 +437,7 @@ int hibernation_snapshot(int platform_mode) if (error || !in_suspend) pm_restore_gfp_mask(); - resume_console(); + console_resume_all(); dpm_complete(msg); Close: @@ -561,7 +561,7 @@ int hibernation_restore(int platform_mode) } dpm_resume_end(PMSG_RECOVER); pm_restore_gfp_mask(); - resume_console(); + console_resume_all(); pm_restore_console(); return error; } @@ -634,7 +634,7 @@ int hibernation_platform_enter(void) Resume_devices: entering_platform_hibernation = false; dpm_resume_end(PMSG_RESTORE); - resume_console(); + console_resume_all(); Close: hibernation_ops->end(); @@ -920,7 +920,7 @@ int hibernate_quiet_exec(int (*func)(void *data), void *data) dpm_resume: dpm_resume(PMSG_THAW); - resume_console(); + console_resume_all(); dpm_complete: dpm_complete(PMSG_THAW); diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index f296dd0a1a187..c3da3db58cdf8 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -521,9 +521,9 @@ int suspend_devices_and_enter(suspend_state_t state) suspend_test_start(); dpm_resume_end(PMSG_RESUME); suspend_test_finish("resume devices"); - trace_suspend_resume(TPS("resume_console"), state, true); - resume_console(); - trace_suspend_resume(TPS("resume_console"), state, false); + trace_suspend_resume(TPS("console_resume_all"), state, true); + console_resume_all(); + trace_suspend_resume(TPS("console_resume_all"), state, false); Close: platform_resume_end(state); diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 0666d3e098972..128d671e97a32 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2760,7 +2760,7 @@ void console_suspend_all(void) synchronize_srcu(&console_srcu); } -void resume_console(void) +void console_resume_all(void) { struct console_flush_type ft; struct console *con; diff --git a/tools/power/pm-graph/config/custom-timeline-functions.cfg b/tools/power/pm-graph/config/custom-timeline-functions.cfg index 80ba55250163d..0321b59518f39 100644 --- a/tools/power/pm-graph/config/custom-timeline-functions.cfg +++ b/tools/power/pm-graph/config/custom-timeline-functions.cfg @@ -128,7 +128,7 @@ syscore_suspend: arch_enable_nonboot_cpus_end: syscore_resume: acpi_pm_finish: -resume_console: +console_resume_all: acpi_pm_end: pm_restore_gfp_mask: thaw_processes: diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py index 114c3d0c66192..e2261f33a0829 100755 --- a/tools/power/pm-graph/sleepgraph.py +++ b/tools/power/pm-graph/sleepgraph.py @@ -216,7 +216,7 @@ class SystemValues: 'arch_enable_nonboot_cpus_end': {}, 'syscore_resume': {}, 'acpi_pm_finish': {}, - 'resume_console': {}, + 'console_resume_all': {}, 'acpi_pm_end': {}, 'pm_restore_gfp_mask': {}, 'thaw_processes': {}, @@ -3459,7 +3459,7 @@ def parseTraceLog(live=False): tracewatch = ['irq_wakeup'] if sysvals.usekprobes: tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', - 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON', + 'syscore_resume', 'console_resume_all', 'thaw_processes', 'CPU_ON', 'CPU_OFF', 'acpi_suspend'] # extract the callgraph and traceevent data From 242fafe3faa761ccc27dc2ebb978ca1ec04adc25 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 26 Feb 2025 16:59:03 -0300 Subject: [PATCH 3/7] printk: Rename console_stop to console_suspend The intent of console_stop was in fact to suspend it, so rename the function accordingly. Signed-off-by: Marcos Paulo de Souza Reviewed-by: Petr Mladek Reviewed-by: John Ogness Link: https://lore.kernel.org/r/20250226-printk-renaming-v1-3-0b878577f2e6@suse.com [pmladek@suse.com: Fixed typo in the commit message. Updated also new drm_log.c] Signed-off-by: Petr Mladek --- drivers/gpu/drm/clients/drm_log.c | 2 +- drivers/tty/serial/serial_core.c | 4 ++-- include/linux/console.h | 2 +- kernel/printk/printk.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/clients/drm_log.c b/drivers/gpu/drm/clients/drm_log.c index 379850c83e511..755b41512d815 100644 --- a/drivers/gpu/drm/clients/drm_log.c +++ b/drivers/gpu/drm/clients/drm_log.c @@ -323,7 +323,7 @@ static int drm_log_client_suspend(struct drm_client_dev *client, bool _console_l { struct drm_log *dlog = client_to_drm_log(client); - console_stop(&dlog->con); + console_suspend(&dlog->con); return 0; } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 74fa02b237729..ff2499dbbb822 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2442,10 +2442,10 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) } /* - * Disable the console device before suspending. + * Suspend the console device before suspending the port. */ if (uart_console(uport)) - console_stop(uport->cons); + console_suspend(uport->cons); uart_change_pm(state, UART_PM_STATE_OFF); diff --git a/include/linux/console.h b/include/linux/console.h index 0d48e0deb2139..74587eeea3c74 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -633,7 +633,7 @@ extern void console_conditional_schedule(void); extern void console_unblank(void); extern void console_flush_on_panic(enum con_flush_mode mode); extern struct tty_driver *console_device(int *); -extern void console_stop(struct console *); +extern void console_suspend(struct console *); extern void console_start(struct console *); extern int is_console_locked(void); extern int braille_register_console(struct console *, int index, diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 128d671e97a32..48e4fc51c88fb 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3497,10 +3497,10 @@ struct tty_driver *console_device(int *index) /* * Prevent further output on the passed console device so that (for example) - * serial drivers can disable console output before suspending a port, and can + * serial drivers can suspend console output before suspending a port, and can * re-enable output afterwards. */ -void console_stop(struct console *console) +void console_suspend(struct console *console) { __pr_flush(console, 1000, true); console_list_lock(); @@ -3515,7 +3515,7 @@ void console_stop(struct console *console) */ synchronize_srcu(&console_srcu); } -EXPORT_SYMBOL(console_stop); +EXPORT_SYMBOL(console_suspend); void console_start(struct console *console) { From 5395e09c803e20ea0713eaa3a44bc8dd36a009b7 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 26 Feb 2025 16:59:04 -0300 Subject: [PATCH 4/7] printk: Rename console_start to console_resume The intent of console_start was to resume a previously suspended console, so rename it accordingly. Signed-off-by: Marcos Paulo de Souza Reviewed-by: Petr Mladek Reviewed-by: John Ogness Link: https://lore.kernel.org/r/20250226-printk-renaming-v1-4-0b878577f2e6@suse.com [pmladek@suse.com: Fixed typo in the commit message. Updated also new drm_log.c.] Signed-off-by: Petr Mladek --- drivers/gpu/drm/clients/drm_log.c | 2 +- drivers/tty/serial/serial_core.c | 2 +- include/linux/console.h | 2 +- kernel/printk/printk.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/clients/drm_log.c b/drivers/gpu/drm/clients/drm_log.c index 755b41512d815..d239f1e3c4563 100644 --- a/drivers/gpu/drm/clients/drm_log.c +++ b/drivers/gpu/drm/clients/drm_log.c @@ -332,7 +332,7 @@ static int drm_log_client_resume(struct drm_client_dev *client, bool _console_lo { struct drm_log *dlog = client_to_drm_log(client); - console_start(&dlog->con); + console_resume(&dlog->con); return 0; } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index ff2499dbbb822..4e6bbbeeb2bf4 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2500,7 +2500,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) uart_port_unlock_irq(uport); } if (console_suspend_enabled) - console_start(uport->cons); + console_resume(uport->cons); } if (tty_port_suspended(port)) { diff --git a/include/linux/console.h b/include/linux/console.h index 74587eeea3c74..8f10d0a85bb45 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -634,7 +634,7 @@ extern void console_unblank(void); extern void console_flush_on_panic(enum con_flush_mode mode); extern struct tty_driver *console_device(int *); extern void console_suspend(struct console *); -extern void console_start(struct console *); +extern void console_resume(struct console *); extern int is_console_locked(void); extern int braille_register_console(struct console *, int index, char *console_options, char *braille_options); diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 48e4fc51c88fb..c9843946559c2 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3517,7 +3517,7 @@ void console_suspend(struct console *console) } EXPORT_SYMBOL(console_suspend); -void console_start(struct console *console) +void console_resume(struct console *console) { struct console_flush_type ft; bool is_nbcon; @@ -3542,7 +3542,7 @@ void console_start(struct console *console) __pr_flush(console, 1000, true); } -EXPORT_SYMBOL(console_start); +EXPORT_SYMBOL(console_resume); #ifdef CONFIG_PRINTK static int unregister_console_locked(struct console *console); From 72c96a2dacc0fb056d13a5f02b0845c4c910fe54 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 26 Feb 2025 16:59:05 -0300 Subject: [PATCH 5/7] printk: Check CON_SUSPEND when unblanking a console The commit 9e70a5e109a4 ("printk: Add per-console suspended state") introduced the CON_SUSPENDED flag for consoles. The suspended consoles will stop receiving messages, so don't unblank suspended consoles because it won't be showing anything either way. Signed-off-by: Marcos Paulo de Souza Reviewed-by: Petr Mladek Reviewed-by: John Ogness Link: https://lore.kernel.org/r/20250226-printk-renaming-v1-5-0b878577f2e6@suse.com Signed-off-by: Petr Mladek --- kernel/printk/printk.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index c9843946559c2..0e6db80d55132 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3342,7 +3342,12 @@ void console_unblank(void) */ cookie = console_srcu_read_lock(); for_each_console_srcu(c) { - if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank) { + short flags = console_srcu_read_flags(c); + + if (flags & CON_SUSPENDED) + continue; + + if ((flags & CON_ENABLED) && c->unblank) { found_unblank = true; break; } @@ -3379,7 +3384,12 @@ void console_unblank(void) cookie = console_srcu_read_lock(); for_each_console_srcu(c) { - if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank) + short flags = console_srcu_read_flags(c); + + if (flags & CON_SUSPENDED) + continue; + + if ((flags & CON_ENABLED) && c->unblank) c->unblank(); } console_srcu_read_unlock(cookie); From 2f1f7787b6b8648f3ceefc59192489052644c6c7 Mon Sep 17 00:00:00 2001 From: Adam Simonelli Date: Fri, 14 Mar 2025 12:07:49 -0400 Subject: [PATCH 6/7] printk: Add an option to allow ttynull to be a default console device The new option is CONFIG_NULL_TTY_DEFAULT_CONSOLE. if enabled, and CONFIG_VT is disabled, ttynull will become the default primary console device. ttynull will be the only console device usually with this option enabled. Some architectures do call add_preferred_console() which may add another console though. Motivation: Many distributions ship with CONFIG_VT enabled. On tested desktop hardware if CONFIG_VT is disabled, the default console device falls back to /dev/ttyS0 instead of /dev/tty. This could cause issues in user space, and hardware problems: 1. The user space issues include the case where /dev/ttyS0 is disconnected, and the TCGETS ioctl, which some user space libraries use as a probe to determine if a file is a tty, is called on /dev/console and fails. Programs that call isatty() on /dev/console and get an incorrect false value may skip expected logging to /dev/console. 2. The hardware issues include the case if a user has a science instrument or other device connected to the /dev/ttyS0 port, and they were to upgrade to a kernel that is disabling the CONFIG_VT option, kernel logs will then be sent to the device connected to /dev/ttyS0 unless they edit their kernel command line manually. The new CONFIG_NULL_TTY_DEFAULT_CONSOLE option will give users and distribution maintainers an option to avoid this. Disabling CONFIG_VT and enabling CONFIG_NULL_TTY_DEFAULT_CONSOLE will ensure the default kernel console behavior is not dependent on hardware configuration by default, and avoid unexpected new behavior on devices connected to the /dev/ttyS0 serial port. Reviewed-by: Petr Mladek Tested-by: Petr Mladek Signed-off-by: Adam Simonelli Link: https://lore.kernel.org/r/20250314160749.3286153-2-adamsimonelli@gmail.com [pmladek@suse.com: Fixed indentation of the commit message.] Signed-off-by: Petr Mladek --- Documentation/admin-guide/serial-console.rst | 4 +++- drivers/tty/Kconfig | 19 ++++++++++++++++++- kernel/printk/printk.c | 5 +++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/serial-console.rst b/Documentation/admin-guide/serial-console.rst index a3dfc2c66e019..1609e7479249f 100644 --- a/Documentation/admin-guide/serial-console.rst +++ b/Documentation/admin-guide/serial-console.rst @@ -78,7 +78,9 @@ If no console device is specified, the first device found capable of acting as a system console will be used. At this time, the system first looks for a VGA card and then for a serial port. So if you don't have a VGA card in your system the first serial port will automatically -become the console. +become the console, unless the kernel is configured with the +CONFIG_NULL_TTY_DEFAULT_CONSOLE option, then it will default to using the +ttynull device. You will need to create a new device to use ``/dev/console``. The official ``/dev/console`` is now character device 5,1. diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index 63a494d36a1fd..7fb81bbaee60b 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -383,7 +383,24 @@ config NULL_TTY available or desired. In order to use this driver, you should redirect the console to this - TTY, or boot the kernel with console=ttynull. + TTY, boot the kernel with console=ttynull, or enable + NULL_TTY_DEFAULT_CONSOLE. + + If unsure, say N. + +config NULL_TTY_DEFAULT_CONSOLE + bool "Support for console on ttynull" + depends on NULL_TTY=y && !VT_CONSOLE + help + Say Y here if you want the NULL TTY to be used as a /dev/console + device by default. + + For example, it might be useful to prevent a VT-less kernel from + writing the system log to a random device connected to the serial + port. + + Another console driver still might get preferred via the command + line, SPCR, or the device tree. If unsure, say N. diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 07668433644b8..2590498d8353a 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -4277,6 +4277,11 @@ void __init console_init(void) initcall_t call; initcall_entry_t *ce; +#ifdef CONFIG_NULL_TTY_DEFAULT_CONSOLE + if (!console_set_on_cmdline) + add_preferred_console("ttynull", 0, NULL); +#endif + /* Setup the default TTY line discipline. */ n_tty_init(); From c1aa3daa517292303d98ff61f0440c354669f948 Mon Sep 17 00:00:00 2001 From: Donghyeok Choe Date: Tue, 18 Mar 2025 11:23:20 +0900 Subject: [PATCH 7/7] printk/panic: Add option to allow non-panic CPUs to write to the ring buffer. Commit 779dbc2e78d7 ("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 bcc954c6caba ("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 Reviewed-by: Petr Mladek 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 Signed-off-by: Petr Mladek --- .../admin-guide/kernel-parameters.txt | 8 ++++++++ kernel/printk/internal.h | 1 + kernel/printk/printk.c | 20 ++++++++++++++++++- kernel/printk/printk_ringbuffer.c | 13 +++++++----- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 05f5935eeac8c..961bc82f05998 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -5013,6 +5013,14 @@ Format: 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: (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 diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h index a91bdf8029671..48a24e7b309db 100644 --- a/kernel/printk/internal.h +++ b/kernel/printk/internal.h @@ -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, diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 2590498d8353a..74b4734a87b91 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -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) @@ -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); diff --git a/kernel/printk/printk_ringbuffer.c b/kernel/printk/printk_ringbuffer.c index 88e8f3a619229..d9fb053cff67d 100644 --- a/kernel/printk/printk_ringbuffer.c +++ b/kernel/printk/printk_ringbuffer.c @@ -2133,9 +2133,9 @@ 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 @@ -2143,10 +2143,13 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq, * 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; + } } }