Skip to content

Commit f503b5a

Browse files
committed
x86,kgdb: Add low level debug hook
The only way the debugger can handle a trap in inside rcu_lock, notify_die, or atomic_notifier_call_chain without a triple fault is to have a low level "first opportunity handler" in the int3 exception handler. Generally this will be something the vast majority of folks will not need, but for those who need it, it is added as a kernel .config option called KGDB_LOW_LEVEL_TRAP. CC: Ingo Molnar <[email protected]> CC: Thomas Gleixner <[email protected]> CC: H. Peter Anvin <[email protected]> CC: [email protected] Signed-off-by: Jason Wessel <[email protected]>
1 parent 98ec187 commit f503b5a

File tree

6 files changed

+41
-2
lines changed

6 files changed

+41
-2
lines changed

arch/x86/include/asm/kgdb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,7 @@ static inline void arch_kgdb_breakpoint(void)
7676
#define BREAK_INSTR_SIZE 1
7777
#define CACHE_FLUSH_IS_SAFE 1
7878

79+
extern int kgdb_ll_trap(int cmd, const char *str,
80+
struct pt_regs *regs, long err, int trap, int sig);
81+
7982
#endif /* _ASM_X86_KGDB_H */

arch/x86/kernel/kgdb.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,14 +538,34 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
538538
return NOTIFY_DONE;
539539
}
540540

541-
if (kgdb_handle_exception(args->trapnr, args->signr, args->err, regs))
541+
if (kgdb_handle_exception(args->trapnr, args->signr, cmd, regs))
542542
return NOTIFY_DONE;
543543

544544
/* Must touch watchdog before return to normal operation */
545545
touch_nmi_watchdog();
546546
return NOTIFY_STOP;
547547
}
548548

549+
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
550+
int kgdb_ll_trap(int cmd, const char *str,
551+
struct pt_regs *regs, long err, int trap, int sig)
552+
{
553+
struct die_args args = {
554+
.regs = regs,
555+
.str = str,
556+
.err = err,
557+
.trapnr = trap,
558+
.signr = sig,
559+
560+
};
561+
562+
if (!kgdb_io_module_registered)
563+
return NOTIFY_DONE;
564+
565+
return __kgdb_notify(&args, cmd);
566+
}
567+
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
568+
549569
static int
550570
kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
551571
{

arch/x86/kernel/traps.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/kprobes.h>
1616
#include <linux/uaccess.h>
1717
#include <linux/kdebug.h>
18+
#include <linux/kgdb.h>
1819
#include <linux/kernel.h>
1920
#include <linux/module.h>
2021
#include <linux/ptrace.h>
@@ -451,6 +452,11 @@ void restart_nmi(void)
451452
/* May run on IST stack. */
452453
dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
453454
{
455+
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
456+
if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
457+
== NOTIFY_STOP)
458+
return;
459+
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
454460
#ifdef CONFIG_KPROBES
455461
if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
456462
== NOTIFY_STOP)

include/linux/kgdb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct uart_port;
6060
void kgdb_breakpoint(void);
6161

6262
extern int kgdb_connected;
63+
extern int kgdb_io_module_registered;
6364

6465
extern atomic_t kgdb_setting_breakpoint;
6566
extern atomic_t kgdb_cpu_doing_single_step;

kernel/debug/debug_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ int kgdb_connected;
6666
EXPORT_SYMBOL_GPL(kgdb_connected);
6767

6868
/* All the KGDB handlers are installed */
69-
static int kgdb_io_module_registered;
69+
int kgdb_io_module_registered;
7070

7171
/* Guard for recursive entry */
7272
static int exception_level;

lib/Kconfig.kgdb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ config KGDB_TESTS_BOOT_STRING
5757
information about other strings you could use beyond the
5858
default of V1F100.
5959

60+
config KGDB_LOW_LEVEL_TRAP
61+
bool "KGDB: Allow debugging with traps in notifiers"
62+
depends on X86
63+
default n
64+
help
65+
This will add an extra call back to kgdb for the breakpoint
66+
exception handler on which will will allow kgdb to step
67+
through a notify handler.
68+
6069
config KGDB_KDB
6170
bool "KGDB_KDB: include kdb frontend for kgdb"
6271
default n

0 commit comments

Comments
 (0)