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.
Showing the changes to kernel/debug (1 of 2 files). Show all
Unified · Split
| @@ -589,24 +589,41 @@ static void kdb_msg_write(const char *msg, int msg_len) · 588 unmodified lines | ||
| 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); |