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>
This commit is contained in:
@@ -41,6 +41,7 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/sysrq.h>
|
#include <linux/sysrq.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kgdb.h>
|
#include <linux/kgdb.h>
|
||||||
#include <linux/kdb.h>
|
#include <linux/kdb.h>
|
||||||
@@ -784,6 +785,20 @@ void __init dbg_late_init(void)
|
|||||||
kdb_init(KDB_INIT_FULL);
|
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)
|
static void kgdb_register_callbacks(void)
|
||||||
{
|
{
|
||||||
if (!kgdb_io_module_registered) {
|
if (!kgdb_io_module_registered) {
|
||||||
@@ -791,6 +806,7 @@ static void kgdb_register_callbacks(void)
|
|||||||
kgdb_arch_init();
|
kgdb_arch_init();
|
||||||
if (!dbg_is_early)
|
if (!dbg_is_early)
|
||||||
kgdb_arch_late();
|
kgdb_arch_late();
|
||||||
|
register_reboot_notifier(&dbg_reboot_notifier);
|
||||||
atomic_notifier_chain_register(&panic_notifier_list,
|
atomic_notifier_chain_register(&panic_notifier_list,
|
||||||
&kgdb_panic_event_nb);
|
&kgdb_panic_event_nb);
|
||||||
#ifdef CONFIG_MAGIC_SYSRQ
|
#ifdef CONFIG_MAGIC_SYSRQ
|
||||||
@@ -812,6 +828,7 @@ static void kgdb_unregister_callbacks(void)
|
|||||||
*/
|
*/
|
||||||
if (kgdb_io_module_registered) {
|
if (kgdb_io_module_registered) {
|
||||||
kgdb_io_module_registered = 0;
|
kgdb_io_module_registered = 0;
|
||||||
|
unregister_reboot_notifier(&dbg_reboot_notifier);
|
||||||
atomic_notifier_chain_unregister(&panic_notifier_list,
|
atomic_notifier_chain_unregister(&panic_notifier_list,
|
||||||
&kgdb_panic_event_nb);
|
&kgdb_panic_event_nb);
|
||||||
kgdb_arch_exit();
|
kgdb_arch_exit();
|
||||||
|
@@ -1111,6 +1111,13 @@ void gdbstub_exit(int status)
|
|||||||
unsigned char checksum, ch, buffer[3];
|
unsigned char checksum, ch, buffer[3];
|
||||||
int loop;
|
int loop;
|
||||||
|
|
||||||
|
if (!kgdb_connected)
|
||||||
|
return;
|
||||||
|
kgdb_connected = 0;
|
||||||
|
|
||||||
|
if (!dbg_io_ops || dbg_kdb_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
buffer[0] = 'W';
|
buffer[0] = 'W';
|
||||||
buffer[1] = hex_asc_hi(status);
|
buffer[1] = hex_asc_hi(status);
|
||||||
buffer[2] = hex_asc_lo(status);
|
buffer[2] = hex_asc_lo(status);
|
||||||
|
Reference in New Issue
Block a user