diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2012-03-16 15:20:41 -0400 |
---|---|---|
committer | Jason Wessel <jason.wessel@windriver.com> | 2012-03-22 16:07:15 -0400 |
commit | 2366e047840e33928803c0442176fb3991423da8 (patch) | |
tree | 6c1488ee97a24c85dd4f2ddb1a06a5694de6e2f2 /kernel/debug | |
parent | 9fbe465efc76044dd87afe764db5464ae61aeabc (diff) |
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...
Reported-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'kernel/debug')
-rw-r--r-- | kernel/debug/debug_core.c | 17 | ||||
-rw-r--r-- | kernel/debug/gdbstub.c | 7 |
2 files changed, 24 insertions, 0 deletions
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 0d7c08784efb..3c1ad4e03543 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/sched.h> | 42 | #include <linux/sched.h> |
43 | #include <linux/sysrq.h> | 43 | #include <linux/sysrq.h> |
44 | #include <linux/reboot.h> | ||
44 | #include <linux/init.h> | 45 | #include <linux/init.h> |
45 | #include <linux/kgdb.h> | 46 | #include <linux/kgdb.h> |
46 | #include <linux/kdb.h> | 47 | #include <linux/kdb.h> |
@@ -784,6 +785,20 @@ void __init dbg_late_init(void) | |||
784 | kdb_init(KDB_INIT_FULL); | 785 | kdb_init(KDB_INIT_FULL); |
785 | } | 786 | } |
786 | 787 | ||
788 | static int | ||
789 | dbg_notify_reboot(struct notifier_block *this, unsigned long code, void *x) | ||
790 | { | ||
791 | if (!dbg_kdb_mode) | ||
792 | gdbstub_exit(code); | ||
793 | return NOTIFY_DONE; | ||
794 | } | ||
795 | |||
796 | static struct notifier_block dbg_reboot_notifier = { | ||
797 | .notifier_call = dbg_notify_reboot, | ||
798 | .next = NULL, | ||
799 | .priority = INT_MAX, | ||
800 | }; | ||
801 | |||
787 | static void kgdb_register_callbacks(void) | 802 | static void kgdb_register_callbacks(void) |
788 | { | 803 | { |
789 | if (!kgdb_io_module_registered) { | 804 | if (!kgdb_io_module_registered) { |
@@ -791,6 +806,7 @@ static void kgdb_register_callbacks(void) | |||
791 | kgdb_arch_init(); | 806 | kgdb_arch_init(); |
792 | if (!dbg_is_early) | 807 | if (!dbg_is_early) |
793 | kgdb_arch_late(); | 808 | kgdb_arch_late(); |
809 | register_reboot_notifier(&dbg_reboot_notifier); | ||
794 | atomic_notifier_chain_register(&panic_notifier_list, | 810 | atomic_notifier_chain_register(&panic_notifier_list, |
795 | &kgdb_panic_event_nb); | 811 | &kgdb_panic_event_nb); |
796 | #ifdef CONFIG_MAGIC_SYSRQ | 812 | #ifdef CONFIG_MAGIC_SYSRQ |
@@ -812,6 +828,7 @@ static void kgdb_unregister_callbacks(void) | |||
812 | */ | 828 | */ |
813 | if (kgdb_io_module_registered) { | 829 | if (kgdb_io_module_registered) { |
814 | kgdb_io_module_registered = 0; | 830 | kgdb_io_module_registered = 0; |
831 | unregister_reboot_notifier(&dbg_reboot_notifier); | ||
815 | atomic_notifier_chain_unregister(&panic_notifier_list, | 832 | atomic_notifier_chain_unregister(&panic_notifier_list, |
816 | &kgdb_panic_event_nb); | 833 | &kgdb_panic_event_nb); |
817 | kgdb_arch_exit(); | 834 | kgdb_arch_exit(); |
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index 5a155742ae96..ce615e064482 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c | |||
@@ -1111,6 +1111,13 @@ void gdbstub_exit(int status) | |||
1111 | unsigned char checksum, ch, buffer[3]; | 1111 | unsigned char checksum, ch, buffer[3]; |
1112 | int loop; | 1112 | int loop; |
1113 | 1113 | ||
1114 | if (!kgdb_connected) | ||
1115 | return; | ||
1116 | kgdb_connected = 0; | ||
1117 | |||
1118 | if (!dbg_io_ops || dbg_kdb_mode) | ||
1119 | return; | ||
1120 | |||
1114 | buffer[0] = 'W'; | 1121 | buffer[0] = 'W'; |
1115 | buffer[1] = hex_asc_hi(status); | 1122 | buffer[1] = hex_asc_hi(status); |
1116 | buffer[2] = hex_asc_lo(status); | 1123 | buffer[2] = hex_asc_lo(status); |