Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kdb: Adapt kdb_msg_write to work with NBCON consoles

Function kdb_msg_write was calling con->write for any found console,
but it won't work on NBCON consoles. In this case we should acquire the
ownership of the console using NBCON_PRIO_EMERGENCY, since printing
kdb messages should only be interrupted by a panic.

At this point, the console is required to use the atomic callback. The
console is skipped if the write_atomic callback is not set or if the
context could not be acquired. The validation of NBCON is done by the
console_is_usable helper. The context is released right after
write_atomic finishes.

The oops_in_progress handling is only needed in the legacy consoles,
so it was moved around the con->write callback.

Suggested-by: Petr Mladek <pmladek@suse.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Reviewed-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
Link: https://patch.msgid.link/20251016-nbcon-kgdboc-v6-5-866aac60a80e@suse.com
[pmladek@suse.com: Fixed compilation with !CONFIG_PRINTK.]
Signed-off-by: Petr Mladek <pmladek@suse.com>

authored by

Marcos Paulo de Souza and committed by
Petr Mladek
62627bf0 4349cf0d

+33 -16
+1 -1
include/linux/console.h
··· 664 664 static inline void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt) { } 665 665 static inline bool nbcon_kdb_try_acquire(struct console *con, 666 666 struct nbcon_write_context *wctxt) { return false; } 667 - static inline void nbcon_kdb_release(struct console *con) { } 667 + static inline void nbcon_kdb_release(struct nbcon_write_context *wctxt) { } 668 668 static inline bool console_is_usable(struct console *con, short flags, 669 669 bool use_atomic) { return false; } 670 670 #endif
+32 -15
kernel/debug/kdb/kdb_io.c
··· 589 589 */ 590 590 cookie = console_srcu_read_lock(); 591 591 for_each_console_srcu(c) { 592 - if (!(console_srcu_read_flags(c) & CON_ENABLED)) 592 + short flags = console_srcu_read_flags(c); 593 + 594 + if (!console_is_usable(c, flags, true)) 593 595 continue; 594 596 if (c == dbg_io_ops->cons) 595 597 continue; 596 - if (!c->write) 597 - continue; 598 - /* 599 - * Set oops_in_progress to encourage the console drivers to 600 - * disregard their internal spin locks: in the current calling 601 - * context the risk of deadlock is a bigger problem than risks 602 - * due to re-entering the console driver. We operate directly on 603 - * oops_in_progress rather than using bust_spinlocks() because 604 - * the calls bust_spinlocks() makes on exit are not appropriate 605 - * for this calling context. 606 - */ 607 - ++oops_in_progress; 608 - c->write(c, msg, msg_len); 609 - --oops_in_progress; 598 + 599 + if (flags & CON_NBCON) { 600 + struct nbcon_write_context wctxt = { }; 601 + 602 + /* 603 + * Do not continue if the console is NBCON and the context 604 + * can't be acquired. 605 + */ 606 + if (!nbcon_kdb_try_acquire(c, &wctxt)) 607 + continue; 608 + 609 + nbcon_write_context_set_buf(&wctxt, (char *)msg, msg_len); 610 + 611 + c->write_atomic(c, &wctxt); 612 + nbcon_kdb_release(&wctxt); 613 + } else { 614 + /* 615 + * Set oops_in_progress to encourage the console drivers to 616 + * disregard their internal spin locks: in the current calling 617 + * context the risk of deadlock is a bigger problem than risks 618 + * due to re-entering the console driver. We operate directly on 619 + * oops_in_progress rather than using bust_spinlocks() because 620 + * the calls bust_spinlocks() makes on exit are not appropriate 621 + * for this calling context. 622 + */ 623 + ++oops_in_progress; 624 + c->write(c, msg, msg_len); 625 + --oops_in_progress; 626 + } 610 627 touch_nmi_watchdog(); 611 628 } 612 629 console_srcu_read_unlock(cookie);