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>
Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
---
kernel/debug/kdb/kdb_io.c | 47 ++++++++++++++++++++++++++++++++---------------
1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index 9b11b10b120cf07e451a7a4d92ce50f9a6c066b2..7f41ce5d1b4b2b9970f7c84d8df40d13c9e9a084 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -589,24 +589,41 @@ static void kdb_msg_write(const char *msg, int msg_len)
*/
cookie = console_srcu_read_lock();
for_each_console_srcu(c) {
- if (!(console_srcu_read_flags(c) & CON_ENABLED))
+ short flags = console_srcu_read_flags(c);
+
+ if (!console_is_usable(c, flags, true))
continue;
if (c == dbg_io_ops->cons)
continue;
- if (!c->write)
- continue;
- /*
- * Set oops_in_progress to encourage the console drivers to
- * disregard their internal spin locks: in the current calling
- * context the risk of deadlock is a bigger problem than risks
- * due to re-entering the console driver. We operate directly on
- * oops_in_progress rather than using bust_spinlocks() because
- * the calls bust_spinlocks() makes on exit are not appropriate
- * for this calling context.
- */
- ++oops_in_progress;
- c->write(c, msg, msg_len);
- --oops_in_progress;
+
+ if (flags & CON_NBCON) {
+ struct nbcon_write_context wctxt = { };
+
+ /*
+ * Do not continue if the console is NBCON and the context
+ * can't be acquired.
+ */
+ if (!nbcon_kdb_try_acquire(c, &wctxt))
+ continue;
+
+ nbcon_write_context_set_buf(&wctxt, (char *)msg, msg_len);
+
+ c->write_atomic(c, &wctxt);
+ nbcon_kdb_release(&wctxt);
+ } else {
+ /*
+ * Set oops_in_progress to encourage the console drivers to
+ * disregard their internal spin locks: in the current calling
+ * context the risk of deadlock is a bigger problem than risks
+ * due to re-entering the console driver. We operate directly on
+ * oops_in_progress rather than using bust_spinlocks() because
+ * the calls bust_spinlocks() makes on exit are not appropriate
+ * for this calling context.
+ */
+ ++oops_in_progress;
+ c->write(c, msg, msg_len);
+ --oops_in_progress;
+ }
touch_nmi_watchdog();
}
console_srcu_read_unlock(cookie);
--
2.51.0
On Mon 2025-09-15 08:20:34, Marcos Paulo de Souza wrote: > 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> > Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com> It looks good to me: Reviewed-by: Petr Mladek <pmladek@suse.com> See one note below. > --- a/kernel/debug/kdb/kdb_io.c > +++ b/kernel/debug/kdb/kdb_io.c > @@ -589,24 +589,41 @@ static void kdb_msg_write(const char *msg, int msg_len) > */ > cookie = console_srcu_read_lock(); > for_each_console_srcu(c) { > - if (!(console_srcu_read_flags(c) & CON_ENABLED)) > + short flags = console_srcu_read_flags(c); > + > + if (!console_is_usable(c, flags, true)) > continue; > if (c == dbg_io_ops->cons) > continue; > - if (!c->write) > - continue; > - /* > - * Set oops_in_progress to encourage the console drivers to > - * disregard their internal spin locks: in the current calling > - * context the risk of deadlock is a bigger problem than risks > - * due to re-entering the console driver. We operate directly on > - * oops_in_progress rather than using bust_spinlocks() because > - * the calls bust_spinlocks() makes on exit are not appropriate > - * for this calling context. > - */ > - ++oops_in_progress; > - c->write(c, msg, msg_len); > - --oops_in_progress; > + > + if (flags & CON_NBCON) { > + struct nbcon_write_context wctxt = { }; > + > + /* > + * Do not continue if the console is NBCON and the context > + * can't be acquired. > + */ > + if (!nbcon_kdb_try_acquire(c, &wctxt)) > + continue; > + > + nbcon_write_context_set_buf(&wctxt, (char *)msg, msg_len); I have overlooked the (char *) cast in the earlier versions of the patchset. It would be nice to fix the nbcon API so that the parameter could be passed as (const char *). It looks that the API using struct nbcon_write_context never modifies the given buffer so it would be the right thing. But it is beyond the scope of this patchset. It would be material for a separate code clean up ;-) Best Regards, Petr
© 2016 - 2025 Red Hat, Inc.