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); |
