diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 22:16:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 22:16:58 -0400 |
commit | 6c536a17fa049d0fb690c1a947b97dbfd304a916 (patch) | |
tree | ed86fed39ac0952b2f21afee04d9d1494e9b904b | |
parent | ba8a3d6c7c1956c6ff54a96e23007beccaa95640 (diff) | |
parent | f2f0945e356daef87cdb01c0302801fb11cf382a (diff) |
Merge tag 'for_linus-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb
Pull KGDB/KDB fixes and cleanups from Jason Wessel:
"Cleanups
- Clean up compile warnings in kgdboc.c and x86/kernel/kgdb.c
- Add module event hooks for simplified debugging with gdb
Fixes
- Fix kdb to stop paging with 'q' on bta and dmesg
- Fix for data that scrolls off the vga console due to line wrapping
when using the kdb pager
New
- The debug core registers for kernel module events which allows a
kernel aware gdb to automatically load symbols and break on entry
to a kernel module
- Allow kgdboc=kdb to setup kdb on the vga console"
* tag 'for_linus-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb:
tty/console: fix warnings in drivers/tty/serial/kgdboc.c
kdb,vt_console: Fix missed data due to pager overruns
kdb: Fix dmesg/bta scroll to quit with 'q'
kgdboc: Accept either kbd or kdb to activate the vga + keyboard kdb shell
kgdb,x86: fix warning about unused variable
mips,kgdb: fix recursive page fault with CONFIG_KPROBES
kgdb: Add module event hooks
-rw-r--r-- | arch/mips/kernel/kgdb.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/kgdb.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/kgdboc.c | 3 | ||||
-rw-r--r-- | drivers/tty/vt/vt.c | 13 | ||||
-rw-r--r-- | include/linux/console.h | 10 | ||||
-rw-r--r-- | kernel/debug/debug_core.c | 18 | ||||
-rw-r--r-- | kernel/debug/kdb/kdb_bt.c | 2 | ||||
-rw-r--r-- | kernel/debug/kdb/kdb_io.c | 33 | ||||
-rw-r--r-- | kernel/debug/kdb/kdb_main.c | 2 |
9 files changed, 84 insertions, 8 deletions
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index f4546e97c60d..23817a6e32b6 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, | |||
283 | struct pt_regs *regs = args->regs; | 283 | struct pt_regs *regs = args->regs; |
284 | int trap = (regs->cp0_cause & 0x7c) >> 2; | 284 | int trap = (regs->cp0_cause & 0x7c) >> 2; |
285 | 285 | ||
286 | #ifdef CONFIG_KPROBES | ||
287 | /* | ||
288 | * Return immediately if the kprobes fault notifier has set | ||
289 | * DIE_PAGE_FAULT. | ||
290 | */ | ||
291 | if (cmd == DIE_PAGE_FAULT) | ||
292 | return NOTIFY_DONE; | ||
293 | #endif /* CONFIG_KPROBES */ | ||
294 | |||
286 | /* Userspace events, ignore. */ | 295 | /* Userspace events, ignore. */ |
287 | if (user_mode(regs)) | 296 | if (user_mode(regs)) |
288 | return NOTIFY_DONE; | 297 | return NOTIFY_DONE; |
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 3f61904365cf..836f8322960e 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) | |||
746 | int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) | 746 | int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) |
747 | { | 747 | { |
748 | int err; | 748 | int err; |
749 | #ifdef CONFIG_DEBUG_RODATA | ||
749 | char opc[BREAK_INSTR_SIZE]; | 750 | char opc[BREAK_INSTR_SIZE]; |
751 | #endif /* CONFIG_DEBUG_RODATA */ | ||
750 | 752 | ||
751 | bpt->type = BP_BREAKPOINT; | 753 | bpt->type = BP_BREAKPOINT; |
752 | err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, | 754 | err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, |
diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index c0b334327d93..10020547c60b 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c | |||
@@ -97,7 +97,8 @@ static void kgdboc_restore_input(void) | |||
97 | 97 | ||
98 | static int kgdboc_register_kbd(char **cptr) | 98 | static int kgdboc_register_kbd(char **cptr) |
99 | { | 99 | { |
100 | if (strncmp(*cptr, "kbd", 3) == 0) { | 100 | if (strncmp(*cptr, "kbd", 3) == 0 || |
101 | strncmp(*cptr, "kdb", 3) == 0) { | ||
101 | if (kdb_poll_idx < KDB_POLL_FUNC_MAX) { | 102 | if (kdb_poll_idx < KDB_POLL_FUNC_MAX) { |
102 | kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char; | 103 | kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char; |
103 | kdb_poll_idx++; | 104 | kdb_poll_idx++; |
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 999ca63afdef..f87d7e8964bf 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -3442,6 +3442,19 @@ int con_debug_enter(struct vc_data *vc) | |||
3442 | kdb_set(2, setargs); | 3442 | kdb_set(2, setargs); |
3443 | } | 3443 | } |
3444 | } | 3444 | } |
3445 | if (vc->vc_cols < 999) { | ||
3446 | int colcount; | ||
3447 | char cols[4]; | ||
3448 | const char *setargs[3] = { | ||
3449 | "set", | ||
3450 | "COLUMNS", | ||
3451 | cols, | ||
3452 | }; | ||
3453 | if (kdbgetintenv(setargs[0], &colcount)) { | ||
3454 | snprintf(cols, 4, "%i", vc->vc_cols); | ||
3455 | kdb_set(2, setargs); | ||
3456 | } | ||
3457 | } | ||
3445 | #endif /* CONFIG_KGDB_KDB */ | 3458 | #endif /* CONFIG_KGDB_KDB */ |
3446 | return ret; | 3459 | return ret; |
3447 | } | 3460 | } |
diff --git a/include/linux/console.h b/include/linux/console.h index 7201ce4280ca..dedb082fe50f 100644 --- a/include/linux/console.h +++ b/include/linux/console.h | |||
@@ -83,8 +83,14 @@ void give_up_console(const struct consw *sw); | |||
83 | int con_debug_enter(struct vc_data *vc); | 83 | int con_debug_enter(struct vc_data *vc); |
84 | int con_debug_leave(void); | 84 | int con_debug_leave(void); |
85 | #else | 85 | #else |
86 | #define con_debug_enter(vc) (0) | 86 | static inline int con_debug_enter(struct vc_data *vc) |
87 | #define con_debug_leave() (0) | 87 | { |
88 | return 0; | ||
89 | } | ||
90 | static inline int con_debug_leave(void) | ||
91 | { | ||
92 | return 0; | ||
93 | } | ||
88 | #endif | 94 | #endif |
89 | 95 | ||
90 | /* scroll */ | 96 | /* scroll */ |
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 17e073c309e6..9a61738cefc8 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
@@ -696,6 +696,22 @@ out: | |||
696 | return ret; | 696 | return ret; |
697 | } | 697 | } |
698 | 698 | ||
699 | /* | ||
700 | * GDB places a breakpoint at this function to know dynamically | ||
701 | * loaded objects. It's not defined static so that only one instance with this | ||
702 | * name exists in the kernel. | ||
703 | */ | ||
704 | |||
705 | static int module_event(struct notifier_block *self, unsigned long val, | ||
706 | void *data) | ||
707 | { | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static struct notifier_block dbg_module_load_nb = { | ||
712 | .notifier_call = module_event, | ||
713 | }; | ||
714 | |||
699 | int kgdb_nmicallback(int cpu, void *regs) | 715 | int kgdb_nmicallback(int cpu, void *regs) |
700 | { | 716 | { |
701 | #ifdef CONFIG_SMP | 717 | #ifdef CONFIG_SMP |
@@ -824,6 +840,7 @@ static void kgdb_register_callbacks(void) | |||
824 | kgdb_arch_init(); | 840 | kgdb_arch_init(); |
825 | if (!dbg_is_early) | 841 | if (!dbg_is_early) |
826 | kgdb_arch_late(); | 842 | kgdb_arch_late(); |
843 | register_module_notifier(&dbg_module_load_nb); | ||
827 | register_reboot_notifier(&dbg_reboot_notifier); | 844 | register_reboot_notifier(&dbg_reboot_notifier); |
828 | atomic_notifier_chain_register(&panic_notifier_list, | 845 | atomic_notifier_chain_register(&panic_notifier_list, |
829 | &kgdb_panic_event_nb); | 846 | &kgdb_panic_event_nb); |
@@ -847,6 +864,7 @@ static void kgdb_unregister_callbacks(void) | |||
847 | if (kgdb_io_module_registered) { | 864 | if (kgdb_io_module_registered) { |
848 | kgdb_io_module_registered = 0; | 865 | kgdb_io_module_registered = 0; |
849 | unregister_reboot_notifier(&dbg_reboot_notifier); | 866 | unregister_reboot_notifier(&dbg_reboot_notifier); |
867 | unregister_module_notifier(&dbg_module_load_nb); | ||
850 | atomic_notifier_chain_unregister(&panic_notifier_list, | 868 | atomic_notifier_chain_unregister(&panic_notifier_list, |
851 | &kgdb_panic_event_nb); | 869 | &kgdb_panic_event_nb); |
852 | kgdb_arch_exit(); | 870 | kgdb_arch_exit(); |
diff --git a/kernel/debug/kdb/kdb_bt.c b/kernel/debug/kdb/kdb_bt.c index 07c9bbb94a0b..b03e0e814e43 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) | |||
129 | } | 129 | } |
130 | /* Now the inactive tasks */ | 130 | /* Now the inactive tasks */ |
131 | kdb_do_each_thread(g, p) { | 131 | kdb_do_each_thread(g, p) { |
132 | if (KDB_FLAG(CMD_INTERRUPT)) | ||
133 | return 0; | ||
132 | if (task_curr(p)) | 134 | if (task_curr(p)) |
133 | continue; | 135 | continue; |
134 | if (kdb_bt1(p, mask, argcount, btaprompt)) | 136 | if (kdb_bt1(p, mask, argcount, btaprompt)) |
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 0a69d2adc4f3..14ff4849262c 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) | |||
552 | { | 552 | { |
553 | int diag; | 553 | int diag; |
554 | int linecount; | 554 | int linecount; |
555 | int colcount; | ||
555 | int logging, saved_loglevel = 0; | 556 | int logging, saved_loglevel = 0; |
556 | int saved_trap_printk; | 557 | int saved_trap_printk; |
557 | int got_printf_lock = 0; | 558 | int got_printf_lock = 0; |
@@ -584,6 +585,10 @@ int vkdb_printf(const char *fmt, va_list ap) | |||
584 | if (diag || linecount <= 1) | 585 | if (diag || linecount <= 1) |
585 | linecount = 24; | 586 | linecount = 24; |
586 | 587 | ||
588 | diag = kdbgetintenv("COLUMNS", &colcount); | ||
589 | if (diag || colcount <= 1) | ||
590 | colcount = 80; | ||
591 | |||
587 | diag = kdbgetintenv("LOGGING", &logging); | 592 | diag = kdbgetintenv("LOGGING", &logging); |
588 | if (diag) | 593 | if (diag) |
589 | logging = 0; | 594 | logging = 0; |
@@ -690,7 +695,7 @@ kdb_printit: | |||
690 | gdbstub_msg_write(kdb_buffer, retlen); | 695 | gdbstub_msg_write(kdb_buffer, retlen); |
691 | } else { | 696 | } else { |
692 | if (dbg_io_ops && !dbg_io_ops->is_console) { | 697 | if (dbg_io_ops && !dbg_io_ops->is_console) { |
693 | len = strlen(kdb_buffer); | 698 | len = retlen; |
694 | cp = kdb_buffer; | 699 | cp = kdb_buffer; |
695 | while (len--) { | 700 | while (len--) { |
696 | dbg_io_ops->write_char(*cp); | 701 | dbg_io_ops->write_char(*cp); |
@@ -709,11 +714,29 @@ kdb_printit: | |||
709 | printk(KERN_INFO "%s", kdb_buffer); | 714 | printk(KERN_INFO "%s", kdb_buffer); |
710 | } | 715 | } |
711 | 716 | ||
712 | if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n')) | 717 | if (KDB_STATE(PAGER)) { |
713 | kdb_nextline++; | 718 | /* |
719 | * Check printed string to decide how to bump the | ||
720 | * kdb_nextline to control when the more prompt should | ||
721 | * show up. | ||
722 | */ | ||
723 | int got = 0; | ||
724 | len = retlen; | ||
725 | while (len--) { | ||
726 | if (kdb_buffer[len] == '\n') { | ||
727 | kdb_nextline++; | ||
728 | got = 0; | ||
729 | } else if (kdb_buffer[len] == '\r') { | ||
730 | got = 0; | ||
731 | } else { | ||
732 | got++; | ||
733 | } | ||
734 | } | ||
735 | kdb_nextline += got / (colcount + 1); | ||
736 | } | ||
714 | 737 | ||
715 | /* check for having reached the LINES number of printed lines */ | 738 | /* check for having reached the LINES number of printed lines */ |
716 | if (kdb_nextline == linecount) { | 739 | if (kdb_nextline >= linecount) { |
717 | char buf1[16] = ""; | 740 | char buf1[16] = ""; |
718 | 741 | ||
719 | /* Watch out for recursion here. Any routine that calls | 742 | /* Watch out for recursion here. Any routine that calls |
@@ -765,7 +788,7 @@ kdb_printit: | |||
765 | kdb_grepping_flag = 0; | 788 | kdb_grepping_flag = 0; |
766 | kdb_printf("\n"); | 789 | kdb_printf("\n"); |
767 | } else if (buf1[0] == ' ') { | 790 | } else if (buf1[0] == ' ') { |
768 | kdb_printf("\n"); | 791 | kdb_printf("\r"); |
769 | suspend_grep = 1; /* for this recursion */ | 792 | suspend_grep = 1; /* for this recursion */ |
770 | } else if (buf1[0] == '\n') { | 793 | } else if (buf1[0] == '\n') { |
771 | kdb_nextline = linecount - 1; | 794 | kdb_nextline = linecount - 1; |
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 1261dc7eaeb9..4d5f8d5612f3 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c | |||
@@ -2101,6 +2101,8 @@ static int kdb_dmesg(int argc, const char **argv) | |||
2101 | } | 2101 | } |
2102 | if (!lines--) | 2102 | if (!lines--) |
2103 | break; | 2103 | break; |
2104 | if (KDB_FLAG(CMD_INTERRUPT)) | ||
2105 | return 0; | ||
2104 | 2106 | ||
2105 | kdb_printf("%.*s\n", (int)len - 1, buf); | 2107 | kdb_printf("%.*s\n", (int)len - 1, buf); |
2106 | } | 2108 | } |