Re: [PATCH 4/4] kgdb: x86: Detach gdb if machine shuts down or reboots

From: Jason Wessel
Date: Fri Mar 16 2012 - 11:38:24 EST


On 03/16/2012 07:17 AM, Jan Kiszka wrote:
> Hook into machine restart/power-off/halt handlers and call gdbstub_exit
> so that a attached gdb frontend is properly informed. If kgdb is
> disabled or no frontend attached, gdbstub_exit will do nothing.
>


We have long had an out of tree patch which hooked the reboot notifier, vs adding call backs to the actual reboot functions. It seems at first glance that all of cases that Jan probably cares about are actually caught by the reboot notifier.

I attached the patch I am referencing, and perhaps Jan can try it out. It applies on top of Jan's series at the moment.

A few more comments first.

> static void __machine_emergency_restart(int emergency)
> {
> reboot_emergency = emergency;
> + gdbstub_exit(1);


If we do have to add callbacks at the arch level, my preference is to pass the stop code like you would have received in the reboot notifier. Specifically something like: gdbstub_exit(SYS_RESTART).

> machine_ops.emergency_restart();
> }
>
> @@ -730,6 +732,7 @@ struct machine_ops machine_ops = {
>
> void machine_power_off(void)
> {
> + gdbstub_exit(0);


Similarly gdbstub_exit(SYS_HALT) and so on.

Jan, what do you think about trying the reboot notifier version?

Thanks,
Jason.
From: Jason Wessel <jason.wessel@xxxxxxxxxxxxx>
Subject: [PATCH] kgdb,debug-core,gdbstub: Hook the reboot notifier for debugger detach

The gdbstub and kdb should get detached if the system is rebooting.
Calling gdbstub_exit() will set the proper debug core state and send a
message to any debugger that is connected to correctly detach.

An attached debugger will receive the exit code from
include/linux/reboot.h based on SYS_HALT, SYS_REBOOT, etc...

Signed-off-by: Jason Wessel <jason.wessel@xxxxxxxxxxxxx>
---
kernel/debug/debug_core.c | 17 +++++++++++++++++
kernel/debug/gdbstub.c | 5 ++++-
2 files changed, 21 insertions(+), 1 deletion(-)

--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -41,6 +41,7 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/sysrq.h>
+#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/kgdb.h>
#include <linux/kdb.h>
@@ -784,6 +785,20 @@ void __init dbg_late_init(void)
kdb_init(KDB_INIT_FULL);
}

+static int
+dbg_notify_reboot(struct notifier_block *this, unsigned long code, void *x)
+{
+ if (!dbg_kdb_mode)
+ gdbstub_exit(code);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block dbg_reboot_notifier = {
+ .notifier_call = dbg_notify_reboot,
+ .next = NULL,
+ .priority = INT_MAX,
+};
+
static void kgdb_register_callbacks(void)
{
if (!kgdb_io_module_registered) {
@@ -791,6 +806,7 @@ static void kgdb_register_callbacks(void
kgdb_arch_init();
if (!dbg_is_early)
kgdb_arch_late();
+ register_reboot_notifier(&dbg_reboot_notifier);
atomic_notifier_chain_register(&panic_notifier_list,
&kgdb_panic_event_nb);
#ifdef CONFIG_MAGIC_SYSRQ
@@ -812,6 +828,7 @@ static void kgdb_unregister_callbacks(vo
*/
if (kgdb_io_module_registered) {
kgdb_io_module_registered = 0;
+ unregister_reboot_notifier(&dbg_reboot_notifier);
atomic_notifier_chain_unregister(&panic_notifier_list,
&kgdb_panic_event_nb);
kgdb_arch_exit();
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -1110,8 +1110,11 @@ void gdbstub_exit(int status)
{
unsigned char checksum, ch, buffer[3];
int loop;
+ if (!kgdb_connected)
+ return;
+ kgdb_connected = 0;

- if (!dbg_io_ops || !kgdb_connected)
+ if (!dbg_io_ops || dbg_kdb_mode)
return;

buffer[0] = 'W';