From f30fed10c440a25937e509860fa207399b26efe5 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 12 Oct 2012 06:37:33 -0500 Subject: kgdb: Add module event hooks Allow gdb to auto load kernel modules when it is attached, which makes it trivially easy to debug module init functions or pre-set breakpoints in a kernel module that has not loaded yet. Signed-off-by: Jason Wessel --- kernel/debug/debug_core.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 0557f24c6bc..8bfa373cd5f 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -688,6 +688,22 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) return kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER); } +/* + * GDB places a breakpoint at this function to know dynamically + * loaded objects. It's not defined static so that only one instance with this + * name exists in the kernel. + */ + +static int module_event(struct notifier_block *self, unsigned long val, + void *data) +{ + return 0; +} + +static struct notifier_block dbg_module_load_nb = { + .notifier_call = module_event, +}; + int kgdb_nmicallback(int cpu, void *regs) { #ifdef CONFIG_SMP @@ -816,6 +832,7 @@ static void kgdb_register_callbacks(void) kgdb_arch_init(); if (!dbg_is_early) kgdb_arch_late(); + register_module_notifier(&dbg_module_load_nb); register_reboot_notifier(&dbg_reboot_notifier); atomic_notifier_chain_register(&panic_notifier_list, &kgdb_panic_event_nb); @@ -839,6 +856,7 @@ static void kgdb_unregister_callbacks(void) if (kgdb_io_module_registered) { kgdb_io_module_registered = 0; unregister_reboot_notifier(&dbg_reboot_notifier); + unregister_module_notifier(&dbg_module_load_nb); atomic_notifier_chain_unregister(&panic_notifier_list, &kgdb_panic_event_nb); kgdb_arch_exit(); -- cgit v1.2.3 From f0a996eeeda214f4293e234df33b29bec003b536 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 10 Aug 2012 12:21:15 -0500 Subject: mips,kgdb: fix recursive page fault with CONFIG_KPROBES This fault was detected using the kgdb test suite on boot and it crashes recursively due to the fact that CONFIG_KPROBES on mips adds an extra die notifier in the page fault handler. The crash signature looks like this: kgdbts:RUN bad memory access test KGDB: re-enter exception: ALL breakpoints killed Call Trace: [<807b7548>] dump_stack+0x20/0x54 [<807b7548>] dump_stack+0x20/0x54 The fix for now is to have kgdb return immediately if the fault type is DIE_PAGE_FAULT and allow the kprobe code to decide what is supposed to happen. Cc: Masami Hiramatsu Cc: David S. Miller Cc: Signed-off-by: Jason Wessel --- arch/mips/kernel/kgdb.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index f4546e97c60..23817a6e32b 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -283,6 +283,15 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, struct pt_regs *regs = args->regs; int trap = (regs->cp0_cause & 0x7c) >> 2; +#ifdef CONFIG_KPROBES + /* + * Return immediately if the kprobes fault notifier has set + * DIE_PAGE_FAULT. + */ + if (cmd == DIE_PAGE_FAULT) + return NOTIFY_DONE; +#endif /* CONFIG_KPROBES */ + /* Userspace events, ignore. */ if (user_mode(regs)) return NOTIFY_DONE; -- cgit v1.2.3 From 42c12213141d7c88e8f649b4bacd19ba14577658 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Wed, 8 Aug 2012 21:12:19 -0500 Subject: kgdb,x86: fix warning about unused variable When compiling without CONFIG_DEBUG_RODATA the following compiler warning is generated: arch/x86/kernel/kgdb.c: In function 'kgdb_arch_set_breakpoint': arch/x86/kernel/kgdb.c:749: warning: unused variable 'opc' The variable instantiation needs to be inside the #ifdef to make the warning go away. Reported-by: Thiago Rafael Becker Signed-off-by: Jason Wessel --- arch/x86/kernel/kgdb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 3f61904365c..836f8322960 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -746,7 +746,9 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) { int err; +#ifdef CONFIG_DEBUG_RODATA char opc[BREAK_INSTR_SIZE]; +#endif /* CONFIG_DEBUG_RODATA */ bpt->type = BP_BREAKPOINT; err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, -- cgit v1.2.3 From 24b8592ec021c433e73e6d8000e71f5c341fdde0 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 10 Aug 2012 12:12:23 -0500 Subject: kgdboc: Accept either kbd or kdb to activate the vga + keyboard kdb shell It is a common enough mistake for people to specify "kdb" when they meant to type "kbd" that the kgdboc can just accept both since they both mean the same thing anyway. Specifically it is for the case where you want kdb to be active on your graphics console + keyboard (where kbd was the original abbreviation for keyboard). With this change kgdboc will now accept either to mean the same thing: kgdboc=kbd kgdboc=kdb Signed-off-by: Jason Wessel --- drivers/tty/serial/kgdboc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index 2b42a01a81c..509e71456d1 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -97,7 +97,8 @@ static void kgdboc_restore_input(void) static int kgdboc_register_kbd(char **cptr) { - if (strncmp(*cptr, "kbd", 3) == 0) { + if (strncmp(*cptr, "kbd", 3) == 0 || + strncmp(*cptr, "kdb", 3) == 0) { if (kdb_poll_idx < KDB_POLL_FUNC_MAX) { kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char; kdb_poll_idx++; -- cgit v1.2.3 From d1871b38fccdc4b6575b0cabdea9e06bc70167eb Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Sun, 26 Aug 2012 21:43:12 -0500 Subject: kdb: Fix dmesg/bta scroll to quit with 'q' If you press 'q' the pager should exit instead of printing everything from dmesg which can really bog down a 9600 baud serial link. The same is true for the bta command. Signed-off-by: Jason Wessel --- kernel/debug/kdb/kdb_bt.c | 2 ++ kernel/debug/kdb/kdb_main.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/kernel/debug/kdb/kdb_bt.c b/kernel/debug/kdb/kdb_bt.c index 07c9bbb94a0..b03e0e814e4 100644 --- a/kernel/debug/kdb/kdb_bt.c +++ b/kernel/debug/kdb/kdb_bt.c @@ -129,6 +129,8 @@ kdb_bt(int argc, const char **argv) } /* Now the inactive tasks */ kdb_do_each_thread(g, p) { + if (KDB_FLAG(CMD_INTERRUPT)) + return 0; if (task_curr(p)) continue; if (kdb_bt1(p, mask, argcount, btaprompt)) diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 31df1706b9a..1afeb5c1e5a 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -2100,6 +2100,8 @@ static int kdb_dmesg(int argc, const char **argv) } if (!lines--) break; + if (KDB_FLAG(CMD_INTERRUPT)) + return 0; kdb_printf("%.*s\n", (int)len - 1, buf); } -- cgit v1.2.3 From 17b572e82032bc246324ce136696656b66d4e3f1 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Sun, 26 Aug 2012 22:37:03 -0500 Subject: kdb,vt_console: Fix missed data due to pager overruns It is possible to miss data when using the kdb pager. The kdb pager does not pay attention to the maximum column constraint of the screen or serial terminal. This result is not incrementing the shown lines correctly and the pager will print more lines that fit on the screen. Obviously that is less than useful when using a VGA console where you cannot scroll back. The pager will now look at the kdb_buffer string to see how many characters are printed. It might not be perfect considering you can output ASCII that might move the cursor position, but it is a substantially better approximation for viewing dmesg and trace logs. This also means that the vt screen needs to set the kdb COLUMNS variable. Cc: Signed-off-by: Jason Wessel --- drivers/tty/vt/vt.c | 13 +++++++++++++ kernel/debug/kdb/kdb_io.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 84cbf298c09..a13f7e158c5 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -3475,6 +3475,19 @@ int con_debug_enter(struct vc_data *vc) kdb_set(2, setargs); } } + if (vc->vc_cols < 999) { + int colcount; + char cols[4]; + const char *setargs[3] = { + "set", + "COLUMNS", + cols, + }; + if (kdbgetintenv(setargs[0], &colcount)) { + snprintf(cols, 4, "%i", vc->vc_cols); + kdb_set(2, setargs); + } + } #endif /* CONFIG_KGDB_KDB */ return ret; } diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 0a69d2adc4f..14ff4849262 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -552,6 +552,7 @@ int vkdb_printf(const char *fmt, va_list ap) { int diag; int linecount; + int colcount; int logging, saved_loglevel = 0; int saved_trap_printk; int got_printf_lock = 0; @@ -584,6 +585,10 @@ int vkdb_printf(const char *fmt, va_list ap) if (diag || linecount <= 1) linecount = 24; + diag = kdbgetintenv("COLUMNS", &colcount); + if (diag || colcount <= 1) + colcount = 80; + diag = kdbgetintenv("LOGGING", &logging); if (diag) logging = 0; @@ -690,7 +695,7 @@ kdb_printit: gdbstub_msg_write(kdb_buffer, retlen); } else { if (dbg_io_ops && !dbg_io_ops->is_console) { - len = strlen(kdb_buffer); + len = retlen; cp = kdb_buffer; while (len--) { dbg_io_ops->write_char(*cp); @@ -709,11 +714,29 @@ kdb_printit: printk(KERN_INFO "%s", kdb_buffer); } - if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n')) - kdb_nextline++; + if (KDB_STATE(PAGER)) { + /* + * Check printed string to decide how to bump the + * kdb_nextline to control when the more prompt should + * show up. + */ + int got = 0; + len = retlen; + while (len--) { + if (kdb_buffer[len] == '\n') { + kdb_nextline++; + got = 0; + } else if (kdb_buffer[len] == '\r') { + got = 0; + } else { + got++; + } + } + kdb_nextline += got / (colcount + 1); + } /* check for having reached the LINES number of printed lines */ - if (kdb_nextline == linecount) { + if (kdb_nextline >= linecount) { char buf1[16] = ""; /* Watch out for recursion here. Any routine that calls @@ -765,7 +788,7 @@ kdb_printit: kdb_grepping_flag = 0; kdb_printf("\n"); } else if (buf1[0] == ' ') { - kdb_printf("\n"); + kdb_printf("\r"); suspend_grep = 1; /* for this recursion */ } else if (buf1[0] == '\n') { kdb_nextline = linecount - 1; -- cgit v1.2.3 From f2f0945e356daef87cdb01c0302801fb11cf382a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 28 Sep 2012 23:36:14 +0200 Subject: tty/console: fix warnings in drivers/tty/serial/kgdboc.c The con_debug_leave/con_debug_enter functions are stubbed out by defining them to (0), which causes harmless build warnings. Using proper inline functions is the normal way to deal with this. Without this patch, building the ARM bcm2835_defconfig results in: drivers/tty/serial/kgdboc.c: In function 'kgdboc_pre_exp_handler': drivers/tty/serial/kgdboc.c:279:3: warning: statement with no effect [-Wunused-value] drivers/tty/serial/kgdboc.c: In function 'kgdboc_post_exp_handler': drivers/tty/serial/kgdboc.c:293:3: warning: statement with no effect [-Wunused-value] Signed-off-by: Arnd Bergmann Cc: Anton Vorontsov Cc: Greg Kroah-Hartman Signed-off-by: Jason Wessel --- include/linux/console.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/console.h b/include/linux/console.h index 7201ce4280c..dedb082fe50 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -83,8 +83,14 @@ void give_up_console(const struct consw *sw); int con_debug_enter(struct vc_data *vc); int con_debug_leave(void); #else -#define con_debug_enter(vc) (0) -#define con_debug_leave() (0) +static inline int con_debug_enter(struct vc_data *vc) +{ + return 0; +} +static inline int con_debug_leave(void) +{ + return 0; +} #endif /* scroll */ -- cgit v1.2.3