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 | cookie = console_srcu_read_lock(); | 590 | cookie = console_srcu_read_lock(); |
| 591 | for_each_console_srcu(c) { | 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 | continue; | 595 | continue; |
| 594 | if (c == dbg_io_ops->cons) | 596 | if (c == dbg_io_ops->cons) |
| 595 | continue; | 597 | continue; |
| 596 | if (!c->write) | 598 | |
| 597 | continue; | 599 | if (flags & CON_NBCON) { |
| 598 | /* | 600 | struct nbcon_write_context wctxt = { }; |
| 599 | * Set oops_in_progress to encourage the console drivers to | 601 | |
| 600 | * disregard their internal spin locks: in the current calling | 602 | /* |
| 601 | * context the risk of deadlock is a bigger problem than risks | 603 | * Do not continue if the console is NBCON and the context |
| 602 | * due to re-entering the console driver. We operate directly on | 604 | * can't be acquired. |
| 603 | * oops_in_progress rather than using bust_spinlocks() because | 605 | */ |
| 604 | * the calls bust_spinlocks() makes on exit are not appropriate | 606 | if (!nbcon_kdb_try_acquire(c, &wctxt)) |
| 605 | * for this calling context. | 607 | continue; |
| 606 | */ | 608 | |
| 607 | ++oops_in_progress; | 609 | nbcon_write_context_set_buf(&wctxt, (char *)msg, msg_len); |
| 608 | c->write(c, msg, msg_len); | 610 | |
| 609 | --oops_in_progress; | 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 | touch_nmi_watchdog(); | 627 | touch_nmi_watchdog(); |
| 611 | } | 628 | } |
| 612 | console_srcu_read_unlock(cookie); | 629 | console_srcu_read_unlock(cookie); |