Re: [PATCH] kgdb: Flush console before entering kgdb on panic

From: Daniel Thompson
Date: Fri Aug 25 2023 - 06:09:47 EST


On Tue, Aug 22, 2023 at 01:19:46PM -0700, Douglas Anderson wrote:
> When entering kdb/kgdb on a kernel panic, it was be observed that the
> console isn't flushed before the `kdb` prompt came up. Specifically,
> when using the buddy lockup detector on arm64 and running:
> echo HARDLOCKUP > /sys/kernel/debug/provoke-crash/DIRECT
>
> I could see:
> [ 26.161099] lkdtm: Performing direct entry HARDLOCKUP
> [ 32.499881] watchdog: Watchdog detected hard LOCKUP on cpu 6
> [ 32.552865] Sending NMI from CPU 5 to CPUs 6:
> [ 32.557359] NMI backtrace for cpu 6
> ... [backtrace for cpu 6] ...
> [ 32.558353] NMI backtrace for cpu 5
> ... [backtrace for cpu 5] ...
> [ 32.867471] Sending NMI from CPU 5 to CPUs 0-4,7:
> [ 32.872321] NMI backtrace forP cpuANC: Hard LOCKUP
>
> Entering kdb (current=..., pid 0) on processor 5 due to Keyboard Entry
> [5]kdb>
>
> As you can see, backtraces for the other CPUs start printing and get
> interleaved with the kdb PANIC print.
>
> Let's replicate the commands to flush the console in the kdb panic
> entry point to avoid this.
>
> Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx>
> ---
>
> kernel/debug/debug_core.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
> index d5e9ccde3ab8..3a904d8697c8 100644
> --- a/kernel/debug/debug_core.c
> +++ b/kernel/debug/debug_core.c
> @@ -1006,6 +1006,9 @@ void kgdb_panic(const char *msg)
> if (panic_timeout)
> return;
>
> + debug_locks_off();
> + console_flush_on_panic(CONSOLE_FLUSH_PENDING);
> +
> if (dbg_kdb_mode)
> kdb_printf("PANIC: %s\n", msg);

I'm somewhat included to say *this* (calling kdb_printf() when not
actually in the debugger) is the cause of the problem. kdb_printf()
does some pretty horid things to the console and isn't intended to
run while the system is active.

I'd therefore be more tempted to defer the print to the b.p. trap
handler itself and make this part of kgdb_panic() look more like:

kgdb_panic_msg = msg;
kgdb_breakpoint();
kgdb_panic_msg = NULL;


Daniel.