diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
| commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
| tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /kernel/debug | |
| parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) | |
Patched in Tegra support.
Diffstat (limited to 'kernel/debug')
| -rw-r--r-- | kernel/debug/debug_core.c | 119 | ||||
| -rw-r--r-- | kernel/debug/gdbstub.c | 22 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_bp.c | 7 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_bt.c | 3 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_debugger.c | 5 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_io.c | 48 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_keyboard.c | 95 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_main.c | 142 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_private.h | 8 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_support.c | 6 |
10 files changed, 157 insertions, 298 deletions
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 9a61738cefc..0d7c08784ef 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
| @@ -41,7 +41,6 @@ | |||
| 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> | ||
| 45 | #include <linux/init.h> | 44 | #include <linux/init.h> |
| 46 | #include <linux/kgdb.h> | 45 | #include <linux/kgdb.h> |
| 47 | #include <linux/kdb.h> | 46 | #include <linux/kdb.h> |
| @@ -53,6 +52,7 @@ | |||
| 53 | #include <asm/cacheflush.h> | 52 | #include <asm/cacheflush.h> |
| 54 | #include <asm/byteorder.h> | 53 | #include <asm/byteorder.h> |
| 55 | #include <linux/atomic.h> | 54 | #include <linux/atomic.h> |
| 55 | #include <asm/system.h> | ||
| 56 | 56 | ||
| 57 | #include "debug_core.h" | 57 | #include "debug_core.h" |
| 58 | 58 | ||
| @@ -75,8 +75,6 @@ static int exception_level; | |||
| 75 | struct kgdb_io *dbg_io_ops; | 75 | struct kgdb_io *dbg_io_ops; |
| 76 | static DEFINE_SPINLOCK(kgdb_registration_lock); | 76 | static DEFINE_SPINLOCK(kgdb_registration_lock); |
| 77 | 77 | ||
| 78 | /* Action for the reboot notifiter, a global allow kdb to change it */ | ||
| 79 | static int kgdbreboot; | ||
| 80 | /* kgdb console driver is loaded */ | 78 | /* kgdb console driver is loaded */ |
| 81 | static int kgdb_con_registered; | 79 | static int kgdb_con_registered; |
| 82 | /* determine if kgdb console output should be used */ | 80 | /* determine if kgdb console output should be used */ |
| @@ -98,7 +96,6 @@ static int __init opt_kgdb_con(char *str) | |||
| 98 | early_param("kgdbcon", opt_kgdb_con); | 96 | early_param("kgdbcon", opt_kgdb_con); |
| 99 | 97 | ||
| 100 | module_param(kgdb_use_con, int, 0644); | 98 | module_param(kgdb_use_con, int, 0644); |
| 101 | module_param(kgdbreboot, int, 0644); | ||
| 102 | 99 | ||
| 103 | /* | 100 | /* |
| 104 | * Holds information about breakpoints in a kernel. These breakpoints are | 101 | * Holds information about breakpoints in a kernel. These breakpoints are |
| @@ -160,39 +157,37 @@ early_param("nokgdbroundup", opt_nokgdbroundup); | |||
| 160 | * Weak aliases for breakpoint management, | 157 | * Weak aliases for breakpoint management, |
| 161 | * can be overriden by architectures when needed: | 158 | * can be overriden by architectures when needed: |
| 162 | */ | 159 | */ |
| 163 | int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) | 160 | int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) |
| 164 | { | 161 | { |
| 165 | int err; | 162 | int err; |
| 166 | 163 | ||
| 167 | err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, | 164 | err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE); |
| 168 | BREAK_INSTR_SIZE); | ||
| 169 | if (err) | 165 | if (err) |
| 170 | return err; | 166 | return err; |
| 171 | err = probe_kernel_write((char *)bpt->bpt_addr, | 167 | |
| 172 | arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); | 168 | return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr, |
| 173 | return err; | 169 | BREAK_INSTR_SIZE); |
| 174 | } | 170 | } |
| 175 | 171 | ||
| 176 | int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) | 172 | int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) |
| 177 | { | 173 | { |
| 178 | return probe_kernel_write((char *)bpt->bpt_addr, | 174 | return probe_kernel_write((char *)addr, |
| 179 | (char *)bpt->saved_instr, BREAK_INSTR_SIZE); | 175 | (char *)bundle, BREAK_INSTR_SIZE); |
| 180 | } | 176 | } |
| 181 | 177 | ||
| 182 | int __weak kgdb_validate_break_address(unsigned long addr) | 178 | int __weak kgdb_validate_break_address(unsigned long addr) |
| 183 | { | 179 | { |
| 184 | struct kgdb_bkpt tmp; | 180 | char tmp_variable[BREAK_INSTR_SIZE]; |
| 185 | int err; | 181 | int err; |
| 186 | /* Validate setting the breakpoint and then removing it. If the | 182 | /* Validate setting the breakpoint and then removing it. In the |
| 187 | * remove fails, the kernel needs to emit a bad message because we | 183 | * remove fails, the kernel needs to emit a bad message because we |
| 188 | * are deep trouble not being able to put things back the way we | 184 | * are deep trouble not being able to put things back the way we |
| 189 | * found them. | 185 | * found them. |
| 190 | */ | 186 | */ |
| 191 | tmp.bpt_addr = addr; | 187 | err = kgdb_arch_set_breakpoint(addr, tmp_variable); |
| 192 | err = kgdb_arch_set_breakpoint(&tmp); | ||
| 193 | if (err) | 188 | if (err) |
| 194 | return err; | 189 | return err; |
| 195 | err = kgdb_arch_remove_breakpoint(&tmp); | 190 | err = kgdb_arch_remove_breakpoint(addr, tmp_variable); |
| 196 | if (err) | 191 | if (err) |
| 197 | printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " | 192 | printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " |
| 198 | "memory destroyed at: %lx", addr); | 193 | "memory destroyed at: %lx", addr); |
| @@ -236,6 +231,7 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) | |||
| 236 | */ | 231 | */ |
| 237 | int dbg_activate_sw_breakpoints(void) | 232 | int dbg_activate_sw_breakpoints(void) |
| 238 | { | 233 | { |
| 234 | unsigned long addr; | ||
| 239 | int error; | 235 | int error; |
| 240 | int ret = 0; | 236 | int ret = 0; |
| 241 | int i; | 237 | int i; |
| @@ -244,15 +240,16 @@ int dbg_activate_sw_breakpoints(void) | |||
| 244 | if (kgdb_break[i].state != BP_SET) | 240 | if (kgdb_break[i].state != BP_SET) |
| 245 | continue; | 241 | continue; |
| 246 | 242 | ||
| 247 | error = kgdb_arch_set_breakpoint(&kgdb_break[i]); | 243 | addr = kgdb_break[i].bpt_addr; |
| 244 | error = kgdb_arch_set_breakpoint(addr, | ||
| 245 | kgdb_break[i].saved_instr); | ||
| 248 | if (error) { | 246 | if (error) { |
| 249 | ret = error; | 247 | ret = error; |
| 250 | printk(KERN_INFO "KGDB: BP install failed: %lx", | 248 | printk(KERN_INFO "KGDB: BP install failed: %lx", addr); |
| 251 | kgdb_break[i].bpt_addr); | ||
| 252 | continue; | 249 | continue; |
| 253 | } | 250 | } |
| 254 | 251 | ||
| 255 | kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); | 252 | kgdb_flush_swbreak_addr(addr); |
| 256 | kgdb_break[i].state = BP_ACTIVE; | 253 | kgdb_break[i].state = BP_ACTIVE; |
| 257 | } | 254 | } |
| 258 | return ret; | 255 | return ret; |
| @@ -301,6 +298,7 @@ int dbg_set_sw_break(unsigned long addr) | |||
| 301 | 298 | ||
| 302 | int dbg_deactivate_sw_breakpoints(void) | 299 | int dbg_deactivate_sw_breakpoints(void) |
| 303 | { | 300 | { |
| 301 | unsigned long addr; | ||
| 304 | int error; | 302 | int error; |
| 305 | int ret = 0; | 303 | int ret = 0; |
| 306 | int i; | 304 | int i; |
| @@ -308,14 +306,15 @@ int dbg_deactivate_sw_breakpoints(void) | |||
| 308 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { | 306 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
| 309 | if (kgdb_break[i].state != BP_ACTIVE) | 307 | if (kgdb_break[i].state != BP_ACTIVE) |
| 310 | continue; | 308 | continue; |
| 311 | error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); | 309 | addr = kgdb_break[i].bpt_addr; |
| 310 | error = kgdb_arch_remove_breakpoint(addr, | ||
| 311 | kgdb_break[i].saved_instr); | ||
| 312 | if (error) { | 312 | if (error) { |
| 313 | printk(KERN_INFO "KGDB: BP remove failed: %lx\n", | 313 | printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); |
| 314 | kgdb_break[i].bpt_addr); | ||
| 315 | ret = error; | 314 | ret = error; |
| 316 | } | 315 | } |
| 317 | 316 | ||
| 318 | kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); | 317 | kgdb_flush_swbreak_addr(addr); |
| 319 | kgdb_break[i].state = BP_SET; | 318 | kgdb_break[i].state = BP_SET; |
| 320 | } | 319 | } |
| 321 | return ret; | 320 | return ret; |
| @@ -349,6 +348,7 @@ int kgdb_isremovedbreak(unsigned long addr) | |||
| 349 | 348 | ||
| 350 | int dbg_remove_all_break(void) | 349 | int dbg_remove_all_break(void) |
| 351 | { | 350 | { |
| 351 | unsigned long addr; | ||
| 352 | int error; | 352 | int error; |
| 353 | int i; | 353 | int i; |
| 354 | 354 | ||
| @@ -356,10 +356,12 @@ int dbg_remove_all_break(void) | |||
| 356 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { | 356 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
| 357 | if (kgdb_break[i].state != BP_ACTIVE) | 357 | if (kgdb_break[i].state != BP_ACTIVE) |
| 358 | goto setundefined; | 358 | goto setundefined; |
| 359 | error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); | 359 | addr = kgdb_break[i].bpt_addr; |
| 360 | error = kgdb_arch_remove_breakpoint(addr, | ||
| 361 | kgdb_break[i].saved_instr); | ||
| 360 | if (error) | 362 | if (error) |
| 361 | printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", | 363 | printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", |
| 362 | kgdb_break[i].bpt_addr); | 364 | addr); |
| 363 | setundefined: | 365 | setundefined: |
| 364 | kgdb_break[i].state = BP_UNDEFINED; | 366 | kgdb_break[i].state = BP_UNDEFINED; |
| 365 | } | 367 | } |
| @@ -672,10 +674,6 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) | |||
| 672 | { | 674 | { |
| 673 | struct kgdb_state kgdb_var; | 675 | struct kgdb_state kgdb_var; |
| 674 | struct kgdb_state *ks = &kgdb_var; | 676 | struct kgdb_state *ks = &kgdb_var; |
| 675 | int ret = 0; | ||
| 676 | |||
| 677 | if (arch_kgdb_ops.enable_nmi) | ||
| 678 | arch_kgdb_ops.enable_nmi(0); | ||
| 679 | 677 | ||
| 680 | ks->cpu = raw_smp_processor_id(); | 678 | ks->cpu = raw_smp_processor_id(); |
| 681 | ks->ex_vector = evector; | 679 | ks->ex_vector = evector; |
| @@ -685,33 +683,13 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) | |||
| 685 | ks->linux_regs = regs; | 683 | ks->linux_regs = regs; |
| 686 | 684 | ||
| 687 | if (kgdb_reenter_check(ks)) | 685 | if (kgdb_reenter_check(ks)) |
| 688 | goto out; /* Ouch, double exception ! */ | 686 | return 0; /* Ouch, double exception ! */ |
| 689 | if (kgdb_info[ks->cpu].enter_kgdb != 0) | 687 | if (kgdb_info[ks->cpu].enter_kgdb != 0) |
| 690 | goto out; | 688 | return 0; |
| 691 | |||
| 692 | ret = kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER); | ||
| 693 | out: | ||
| 694 | if (arch_kgdb_ops.enable_nmi) | ||
| 695 | arch_kgdb_ops.enable_nmi(1); | ||
| 696 | return ret; | ||
| 697 | } | ||
| 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 | 689 | ||
| 705 | static int module_event(struct notifier_block *self, unsigned long val, | 690 | return kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER); |
| 706 | void *data) | ||
| 707 | { | ||
| 708 | return 0; | ||
| 709 | } | 691 | } |
| 710 | 692 | ||
| 711 | static struct notifier_block dbg_module_load_nb = { | ||
| 712 | .notifier_call = module_event, | ||
| 713 | }; | ||
| 714 | |||
| 715 | int kgdb_nmicallback(int cpu, void *regs) | 693 | int kgdb_nmicallback(int cpu, void *regs) |
| 716 | { | 694 | { |
| 717 | #ifdef CONFIG_SMP | 695 | #ifdef CONFIG_SMP |
| @@ -806,33 +784,6 @@ void __init dbg_late_init(void) | |||
| 806 | kdb_init(KDB_INIT_FULL); | 784 | kdb_init(KDB_INIT_FULL); |
| 807 | } | 785 | } |
| 808 | 786 | ||
| 809 | static int | ||
| 810 | dbg_notify_reboot(struct notifier_block *this, unsigned long code, void *x) | ||
| 811 | { | ||
| 812 | /* | ||
| 813 | * Take the following action on reboot notify depending on value: | ||
| 814 | * 1 == Enter debugger | ||
| 815 | * 0 == [the default] detatch debug client | ||
| 816 | * -1 == Do nothing... and use this until the board resets | ||
| 817 | */ | ||
| 818 | switch (kgdbreboot) { | ||
| 819 | case 1: | ||
| 820 | kgdb_breakpoint(); | ||
| 821 | case -1: | ||
| 822 | goto done; | ||
| 823 | } | ||
| 824 | if (!dbg_kdb_mode) | ||
| 825 | gdbstub_exit(code); | ||
| 826 | done: | ||
| 827 | return NOTIFY_DONE; | ||
| 828 | } | ||
| 829 | |||
| 830 | static struct notifier_block dbg_reboot_notifier = { | ||
| 831 | .notifier_call = dbg_notify_reboot, | ||
| 832 | .next = NULL, | ||
| 833 | .priority = INT_MAX, | ||
| 834 | }; | ||
| 835 | |||
| 836 | static void kgdb_register_callbacks(void) | 787 | static void kgdb_register_callbacks(void) |
| 837 | { | 788 | { |
| 838 | if (!kgdb_io_module_registered) { | 789 | if (!kgdb_io_module_registered) { |
| @@ -840,8 +791,6 @@ static void kgdb_register_callbacks(void) | |||
| 840 | kgdb_arch_init(); | 791 | kgdb_arch_init(); |
| 841 | if (!dbg_is_early) | 792 | if (!dbg_is_early) |
| 842 | kgdb_arch_late(); | 793 | kgdb_arch_late(); |
| 843 | register_module_notifier(&dbg_module_load_nb); | ||
| 844 | register_reboot_notifier(&dbg_reboot_notifier); | ||
| 845 | atomic_notifier_chain_register(&panic_notifier_list, | 794 | atomic_notifier_chain_register(&panic_notifier_list, |
| 846 | &kgdb_panic_event_nb); | 795 | &kgdb_panic_event_nb); |
| 847 | #ifdef CONFIG_MAGIC_SYSRQ | 796 | #ifdef CONFIG_MAGIC_SYSRQ |
| @@ -863,8 +812,6 @@ static void kgdb_unregister_callbacks(void) | |||
| 863 | */ | 812 | */ |
| 864 | if (kgdb_io_module_registered) { | 813 | if (kgdb_io_module_registered) { |
| 865 | kgdb_io_module_registered = 0; | 814 | kgdb_io_module_registered = 0; |
| 866 | unregister_reboot_notifier(&dbg_reboot_notifier); | ||
| 867 | unregister_module_notifier(&dbg_module_load_nb); | ||
| 868 | atomic_notifier_chain_unregister(&panic_notifier_list, | 815 | atomic_notifier_chain_unregister(&panic_notifier_list, |
| 869 | &kgdb_panic_event_nb); | 816 | &kgdb_panic_event_nb); |
| 870 | kgdb_arch_exit(); | 817 | kgdb_arch_exit(); |
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index ce615e06448..34872482315 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c | |||
| @@ -217,7 +217,7 @@ void gdbstub_msg_write(const char *s, int len) | |||
| 217 | 217 | ||
| 218 | /* Pack in hex chars */ | 218 | /* Pack in hex chars */ |
| 219 | for (i = 0; i < wcount; i++) | 219 | for (i = 0; i < wcount; i++) |
| 220 | bufptr = hex_byte_pack(bufptr, s[i]); | 220 | bufptr = pack_hex_byte(bufptr, s[i]); |
| 221 | *bufptr = '\0'; | 221 | *bufptr = '\0'; |
| 222 | 222 | ||
| 223 | /* Move up */ | 223 | /* Move up */ |
| @@ -249,7 +249,7 @@ char *kgdb_mem2hex(char *mem, char *buf, int count) | |||
| 249 | if (err) | 249 | if (err) |
| 250 | return NULL; | 250 | return NULL; |
| 251 | while (count > 0) { | 251 | while (count > 0) { |
| 252 | buf = hex_byte_pack(buf, *tmp); | 252 | buf = pack_hex_byte(buf, *tmp); |
| 253 | tmp++; | 253 | tmp++; |
| 254 | count--; | 254 | count--; |
| 255 | } | 255 | } |
| @@ -411,14 +411,14 @@ static char *pack_threadid(char *pkt, unsigned char *id) | |||
| 411 | limit = id + (BUF_THREAD_ID_SIZE / 2); | 411 | limit = id + (BUF_THREAD_ID_SIZE / 2); |
| 412 | while (id < limit) { | 412 | while (id < limit) { |
| 413 | if (!lzero || *id != 0) { | 413 | if (!lzero || *id != 0) { |
| 414 | pkt = hex_byte_pack(pkt, *id); | 414 | pkt = pack_hex_byte(pkt, *id); |
| 415 | lzero = 0; | 415 | lzero = 0; |
| 416 | } | 416 | } |
| 417 | id++; | 417 | id++; |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | if (lzero) | 420 | if (lzero) |
| 421 | pkt = hex_byte_pack(pkt, 0); | 421 | pkt = pack_hex_byte(pkt, 0); |
| 422 | 422 | ||
| 423 | return pkt; | 423 | return pkt; |
| 424 | } | 424 | } |
| @@ -486,7 +486,7 @@ static void gdb_cmd_status(struct kgdb_state *ks) | |||
| 486 | dbg_remove_all_break(); | 486 | dbg_remove_all_break(); |
| 487 | 487 | ||
| 488 | remcom_out_buffer[0] = 'S'; | 488 | remcom_out_buffer[0] = 'S'; |
| 489 | hex_byte_pack(&remcom_out_buffer[1], ks->signo); | 489 | pack_hex_byte(&remcom_out_buffer[1], ks->signo); |
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | static void gdb_get_regs_helper(struct kgdb_state *ks) | 492 | static void gdb_get_regs_helper(struct kgdb_state *ks) |
| @@ -954,7 +954,7 @@ int gdb_serial_stub(struct kgdb_state *ks) | |||
| 954 | /* Reply to host that an exception has occurred */ | 954 | /* Reply to host that an exception has occurred */ |
| 955 | ptr = remcom_out_buffer; | 955 | ptr = remcom_out_buffer; |
| 956 | *ptr++ = 'T'; | 956 | *ptr++ = 'T'; |
| 957 | ptr = hex_byte_pack(ptr, ks->signo); | 957 | ptr = pack_hex_byte(ptr, ks->signo); |
| 958 | ptr += strlen(strcpy(ptr, "thread:")); | 958 | ptr += strlen(strcpy(ptr, "thread:")); |
| 959 | int_to_threadref(thref, shadow_pid(current->pid)); | 959 | int_to_threadref(thref, shadow_pid(current->pid)); |
| 960 | ptr = pack_threadid(ptr, thref); | 960 | ptr = pack_threadid(ptr, thref); |
| @@ -1111,13 +1111,6 @@ 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 | |||
| 1121 | buffer[0] = 'W'; | 1114 | buffer[0] = 'W'; |
| 1122 | buffer[1] = hex_asc_hi(status); | 1115 | buffer[1] = hex_asc_hi(status); |
| 1123 | buffer[2] = hex_asc_lo(status); | 1116 | buffer[2] = hex_asc_lo(status); |
| @@ -1136,6 +1129,5 @@ void gdbstub_exit(int status) | |||
| 1136 | dbg_io_ops->write_char(hex_asc_lo(checksum)); | 1129 | dbg_io_ops->write_char(hex_asc_lo(checksum)); |
| 1137 | 1130 | ||
| 1138 | /* make sure the output is flushed, lest the bootloader clobber it */ | 1131 | /* make sure the output is flushed, lest the bootloader clobber it */ |
| 1139 | if (dbg_io_ops->flush) | 1132 | dbg_io_ops->flush(); |
| 1140 | dbg_io_ops->flush(); | ||
| 1141 | } | 1133 | } |
diff --git a/kernel/debug/kdb/kdb_bp.c b/kernel/debug/kdb/kdb_bp.c index 8418c2f8ec5..20059ef4459 100644 --- a/kernel/debug/kdb/kdb_bp.c +++ b/kernel/debug/kdb/kdb_bp.c | |||
| @@ -153,13 +153,6 @@ static int _kdb_bp_install(struct pt_regs *regs, kdb_bp_t *bp) | |||
| 153 | } else { | 153 | } else { |
| 154 | kdb_printf("%s: failed to set breakpoint at 0x%lx\n", | 154 | kdb_printf("%s: failed to set breakpoint at 0x%lx\n", |
| 155 | __func__, bp->bp_addr); | 155 | __func__, bp->bp_addr); |
| 156 | #ifdef CONFIG_DEBUG_RODATA | ||
| 157 | if (!bp->bp_type) { | ||
| 158 | kdb_printf("Software breakpoints are unavailable.\n" | ||
| 159 | " Change the kernel CONFIG_DEBUG_RODATA=n\n" | ||
| 160 | " OR use hw breaks: help bph\n"); | ||
| 161 | } | ||
| 162 | #endif | ||
| 163 | return 1; | 156 | return 1; |
| 164 | } | 157 | } |
| 165 | return 0; | 158 | return 0; |
diff --git a/kernel/debug/kdb/kdb_bt.c b/kernel/debug/kdb/kdb_bt.c index b03e0e814e4..7179eac7b41 100644 --- a/kernel/debug/kdb/kdb_bt.c +++ b/kernel/debug/kdb/kdb_bt.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
| 16 | #include <linux/kdb.h> | 16 | #include <linux/kdb.h> |
| 17 | #include <linux/nmi.h> | 17 | #include <linux/nmi.h> |
| 18 | #include <asm/system.h> | ||
| 18 | #include "kdb_private.h" | 19 | #include "kdb_private.h" |
| 19 | 20 | ||
| 20 | 21 | ||
| @@ -129,8 +130,6 @@ kdb_bt(int argc, const char **argv) | |||
| 129 | } | 130 | } |
| 130 | /* Now the inactive tasks */ | 131 | /* Now the inactive tasks */ |
| 131 | kdb_do_each_thread(g, p) { | 132 | kdb_do_each_thread(g, p) { |
| 132 | if (KDB_FLAG(CMD_INTERRUPT)) | ||
| 133 | return 0; | ||
| 134 | if (task_curr(p)) | 133 | if (task_curr(p)) |
| 135 | continue; | 134 | continue; |
| 136 | if (kdb_bt1(p, mask, argcount, btaprompt)) | 135 | if (kdb_bt1(p, mask, argcount, btaprompt)) |
diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c index be7b33b73d3..d9ca9aa481e 100644 --- a/kernel/debug/kdb/kdb_debugger.c +++ b/kernel/debug/kdb/kdb_debugger.c | |||
| @@ -11,8 +11,6 @@ | |||
| 11 | #include <linux/kgdb.h> | 11 | #include <linux/kgdb.h> |
| 12 | #include <linux/kdb.h> | 12 | #include <linux/kdb.h> |
| 13 | #include <linux/kdebug.h> | 13 | #include <linux/kdebug.h> |
| 14 | #include <linux/export.h> | ||
| 15 | #include <linux/hardirq.h> | ||
| 16 | #include "kdb_private.h" | 14 | #include "kdb_private.h" |
| 17 | #include "../debug_core.h" | 15 | #include "../debug_core.h" |
| 18 | 16 | ||
| @@ -53,9 +51,6 @@ int kdb_stub(struct kgdb_state *ks) | |||
| 53 | if (atomic_read(&kgdb_setting_breakpoint)) | 51 | if (atomic_read(&kgdb_setting_breakpoint)) |
| 54 | reason = KDB_REASON_KEYBOARD; | 52 | reason = KDB_REASON_KEYBOARD; |
| 55 | 53 | ||
| 56 | if (in_nmi()) | ||
| 57 | reason = KDB_REASON_NMI; | ||
| 58 | |||
| 59 | for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { | 54 | for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { |
| 60 | if ((bp->bp_enabled) && (bp->bp_addr == addr)) { | 55 | if ((bp->bp_enabled) && (bp->bp_addr == addr)) { |
| 61 | reason = KDB_REASON_BREAK; | 56 | reason = KDB_REASON_BREAK; |
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 14ff4849262..4802eb5840e 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c | |||
| @@ -552,7 +552,6 @@ 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; | ||
| 556 | int logging, saved_loglevel = 0; | 555 | int logging, saved_loglevel = 0; |
| 557 | int saved_trap_printk; | 556 | int saved_trap_printk; |
| 558 | int got_printf_lock = 0; | 557 | int got_printf_lock = 0; |
| @@ -585,10 +584,6 @@ int vkdb_printf(const char *fmt, va_list ap) | |||
| 585 | if (diag || linecount <= 1) | 584 | if (diag || linecount <= 1) |
| 586 | linecount = 24; | 585 | linecount = 24; |
| 587 | 586 | ||
| 588 | diag = kdbgetintenv("COLUMNS", &colcount); | ||
| 589 | if (diag || colcount <= 1) | ||
| 590 | colcount = 80; | ||
| 591 | |||
| 592 | diag = kdbgetintenv("LOGGING", &logging); | 587 | diag = kdbgetintenv("LOGGING", &logging); |
| 593 | if (diag) | 588 | if (diag) |
| 594 | logging = 0; | 589 | logging = 0; |
| @@ -694,8 +689,8 @@ kdb_printit: | |||
| 694 | if (!dbg_kdb_mode && kgdb_connected) { | 689 | if (!dbg_kdb_mode && kgdb_connected) { |
| 695 | gdbstub_msg_write(kdb_buffer, retlen); | 690 | gdbstub_msg_write(kdb_buffer, retlen); |
| 696 | } else { | 691 | } else { |
| 697 | if (dbg_io_ops && !dbg_io_ops->is_console) { | 692 | if (!dbg_io_ops->is_console) { |
| 698 | len = retlen; | 693 | len = strlen(kdb_buffer); |
| 699 | cp = kdb_buffer; | 694 | cp = kdb_buffer; |
| 700 | while (len--) { | 695 | while (len--) { |
| 701 | dbg_io_ops->write_char(*cp); | 696 | dbg_io_ops->write_char(*cp); |
| @@ -714,30 +709,15 @@ kdb_printit: | |||
| 714 | printk(KERN_INFO "%s", kdb_buffer); | 709 | printk(KERN_INFO "%s", kdb_buffer); |
| 715 | } | 710 | } |
| 716 | 711 | ||
| 717 | if (KDB_STATE(PAGER)) { | 712 | if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n')) |
| 718 | /* | 713 | kdb_nextline++; |
| 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 | } | ||
| 737 | 714 | ||
| 738 | /* check for having reached the LINES number of printed lines */ | 715 | /* check for having reached the LINES number of printed lines */ |
| 739 | if (kdb_nextline >= linecount) { | 716 | if (kdb_nextline == linecount) { |
| 740 | char buf1[16] = ""; | 717 | char buf1[16] = ""; |
| 718 | #if defined(CONFIG_SMP) | ||
| 719 | char buf2[32]; | ||
| 720 | #endif | ||
| 741 | 721 | ||
| 742 | /* Watch out for recursion here. Any routine that calls | 722 | /* Watch out for recursion here. Any routine that calls |
| 743 | * kdb_printf will come back through here. And kdb_read | 723 | * kdb_printf will come back through here. And kdb_read |
| @@ -752,10 +732,18 @@ kdb_printit: | |||
| 752 | if (moreprompt == NULL) | 732 | if (moreprompt == NULL) |
| 753 | moreprompt = "more> "; | 733 | moreprompt = "more> "; |
| 754 | 734 | ||
| 735 | #if defined(CONFIG_SMP) | ||
| 736 | if (strchr(moreprompt, '%')) { | ||
| 737 | sprintf(buf2, moreprompt, get_cpu()); | ||
| 738 | put_cpu(); | ||
| 739 | moreprompt = buf2; | ||
| 740 | } | ||
| 741 | #endif | ||
| 742 | |||
| 755 | kdb_input_flush(); | 743 | kdb_input_flush(); |
| 756 | c = console_drivers; | 744 | c = console_drivers; |
| 757 | 745 | ||
| 758 | if (dbg_io_ops && !dbg_io_ops->is_console) { | 746 | if (!dbg_io_ops->is_console) { |
| 759 | len = strlen(moreprompt); | 747 | len = strlen(moreprompt); |
| 760 | cp = moreprompt; | 748 | cp = moreprompt; |
| 761 | while (len--) { | 749 | while (len--) { |
| @@ -788,7 +776,7 @@ kdb_printit: | |||
| 788 | kdb_grepping_flag = 0; | 776 | kdb_grepping_flag = 0; |
| 789 | kdb_printf("\n"); | 777 | kdb_printf("\n"); |
| 790 | } else if (buf1[0] == ' ') { | 778 | } else if (buf1[0] == ' ') { |
| 791 | kdb_printf("\r"); | 779 | kdb_printf("\n"); |
| 792 | suspend_grep = 1; /* for this recursion */ | 780 | suspend_grep = 1; /* for this recursion */ |
| 793 | } else if (buf1[0] == '\n') { | 781 | } else if (buf1[0] == '\n') { |
| 794 | kdb_nextline = linecount - 1; | 782 | kdb_nextline = linecount - 1; |
diff --git a/kernel/debug/kdb/kdb_keyboard.c b/kernel/debug/kdb/kdb_keyboard.c index 118527aa60e..4bca634975c 100644 --- a/kernel/debug/kdb/kdb_keyboard.c +++ b/kernel/debug/kdb/kdb_keyboard.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ | 25 | #define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ |
| 26 | 26 | ||
| 27 | static int kbd_exists; | 27 | static int kbd_exists; |
| 28 | static int kbd_last_ret; | ||
| 29 | 28 | ||
| 30 | /* | 29 | /* |
| 31 | * Check if the keyboard controller has a keypress for us. | 30 | * Check if the keyboard controller has a keypress for us. |
| @@ -91,11 +90,8 @@ int kdb_get_kbd_char(void) | |||
| 91 | return -1; | 90 | return -1; |
| 92 | } | 91 | } |
| 93 | 92 | ||
| 94 | if ((scancode & 0x80) != 0) { | 93 | if ((scancode & 0x80) != 0) |
| 95 | if (scancode == 0x9c) | ||
| 96 | kbd_last_ret = 0; | ||
| 97 | return -1; | 94 | return -1; |
| 98 | } | ||
| 99 | 95 | ||
| 100 | scancode &= 0x7f; | 96 | scancode &= 0x7f; |
| 101 | 97 | ||
| @@ -182,82 +178,35 @@ int kdb_get_kbd_char(void) | |||
| 182 | return -1; /* ignore unprintables */ | 178 | return -1; /* ignore unprintables */ |
| 183 | } | 179 | } |
| 184 | 180 | ||
| 185 | if (scancode == 0x1c) { | 181 | if ((scancode & 0x7f) == 0x1c) { |
| 186 | kbd_last_ret = 1; | 182 | /* |
| 187 | return 13; | 183 | * enter key. All done. Absorb the release scancode. |
| 188 | } | 184 | */ |
| 189 | |||
| 190 | return keychar & 0xff; | ||
| 191 | } | ||
| 192 | EXPORT_SYMBOL_GPL(kdb_get_kbd_char); | ||
| 193 | |||
| 194 | /* | ||
| 195 | * Best effort cleanup of ENTER break codes on leaving KDB. Called on | ||
| 196 | * exiting KDB, when we know we processed an ENTER or KP ENTER scan | ||
| 197 | * code. | ||
| 198 | */ | ||
| 199 | void kdb_kbd_cleanup_state(void) | ||
| 200 | { | ||
| 201 | int scancode, scanstatus; | ||
| 202 | |||
| 203 | /* | ||
| 204 | * Nothing to clean up, since either | ||
| 205 | * ENTER was never pressed, or has already | ||
| 206 | * gotten cleaned up. | ||
| 207 | */ | ||
| 208 | if (!kbd_last_ret) | ||
| 209 | return; | ||
| 210 | |||
| 211 | kbd_last_ret = 0; | ||
| 212 | /* | ||
| 213 | * Enter key. Need to absorb the break code here, lest it gets | ||
| 214 | * leaked out if we exit KDB as the result of processing 'g'. | ||
| 215 | * | ||
| 216 | * This has several interesting implications: | ||
| 217 | * + Need to handle KP ENTER, which has break code 0xe0 0x9c. | ||
| 218 | * + Need to handle repeat ENTER and repeat KP ENTER. Repeats | ||
| 219 | * only get a break code at the end of the repeated | ||
| 220 | * sequence. This means we can't propagate the repeated key | ||
| 221 | * press, and must swallow it away. | ||
| 222 | * + Need to handle possible PS/2 mouse input. | ||
| 223 | * + Need to handle mashed keys. | ||
| 224 | */ | ||
| 225 | |||
| 226 | while (1) { | ||
| 227 | while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) | 185 | while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) |
| 228 | cpu_relax(); | 186 | ; |
| 229 | 187 | ||
| 230 | /* | 188 | /* |
| 231 | * Fetch the scancode. | 189 | * Fetch the scancode |
| 232 | */ | 190 | */ |
| 233 | scancode = inb(KBD_DATA_REG); | 191 | scancode = inb(KBD_DATA_REG); |
| 234 | scanstatus = inb(KBD_STATUS_REG); | 192 | scanstatus = inb(KBD_STATUS_REG); |
| 235 | 193 | ||
| 236 | /* | 194 | while (scanstatus & KBD_STAT_MOUSE_OBF) { |
| 237 | * Skip mouse input. | 195 | scancode = inb(KBD_DATA_REG); |
| 238 | */ | 196 | scanstatus = inb(KBD_STATUS_REG); |
| 239 | if (scanstatus & KBD_STAT_MOUSE_OBF) | 197 | } |
| 240 | continue; | ||
| 241 | 198 | ||
| 242 | /* | 199 | if (scancode != 0x9c) { |
| 243 | * If we see 0xe0, this is either a break code for KP | 200 | /* |
| 244 | * ENTER, or a repeat make for KP ENTER. Either way, | 201 | * Wasn't an enter-release, why not? |
| 245 | * since the second byte is equivalent to an ENTER, | 202 | */ |
| 246 | * skip the 0xe0 and try again. | 203 | kdb_printf("kdb: expected enter got 0x%x status 0x%x\n", |
| 247 | * | 204 | scancode, scanstatus); |
| 248 | * If we see 0x1c, this must be a repeat ENTER or KP | 205 | } |
| 249 | * ENTER (and we swallowed 0xe0 before). Try again. | ||
| 250 | * | ||
| 251 | * We can also see make and break codes for other keys | ||
| 252 | * mashed before or after pressing ENTER. Thus, if we | ||
| 253 | * see anything other than 0x9c, we have to try again. | ||
| 254 | * | ||
| 255 | * Note, if you held some key as ENTER was depressed, | ||
| 256 | * that break code would get leaked out. | ||
| 257 | */ | ||
| 258 | if (scancode != 0x9c) | ||
| 259 | continue; | ||
| 260 | 206 | ||
| 261 | return; | 207 | return 13; |
| 262 | } | 208 | } |
| 209 | |||
| 210 | return keychar & 0xff; | ||
| 263 | } | 211 | } |
| 212 | EXPORT_SYMBOL_GPL(kdb_get_kbd_char); | ||
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 4d5f8d5612f..63786e71a3c 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c | |||
| @@ -14,14 +14,12 @@ | |||
| 14 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
| 15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/kmsg_dump.h> | ||
| 18 | #include <linux/reboot.h> | 17 | #include <linux/reboot.h> |
| 19 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
| 20 | #include <linux/sysrq.h> | 19 | #include <linux/sysrq.h> |
| 21 | #include <linux/smp.h> | 20 | #include <linux/smp.h> |
| 22 | #include <linux/utsname.h> | 21 | #include <linux/utsname.h> |
| 23 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
| 24 | #include <linux/atomic.h> | ||
| 25 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 26 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
| 27 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| @@ -140,10 +138,11 @@ static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t); | |||
| 140 | static char *__env[] = { | 138 | static char *__env[] = { |
| 141 | #if defined(CONFIG_SMP) | 139 | #if defined(CONFIG_SMP) |
| 142 | "PROMPT=[%d]kdb> ", | 140 | "PROMPT=[%d]kdb> ", |
| 141 | "MOREPROMPT=[%d]more> ", | ||
| 143 | #else | 142 | #else |
| 144 | "PROMPT=kdb> ", | 143 | "PROMPT=kdb> ", |
| 145 | #endif | ||
| 146 | "MOREPROMPT=more> ", | 144 | "MOREPROMPT=more> ", |
| 145 | #endif | ||
| 147 | "RADIX=16", | 146 | "RADIX=16", |
| 148 | "MDCOUNT=8", /* lines of md output */ | 147 | "MDCOUNT=8", /* lines of md output */ |
| 149 | KDB_PLATFORM_ENV, | 148 | KDB_PLATFORM_ENV, |
| @@ -1236,6 +1235,18 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, | |||
| 1236 | *cmdbuf = '\0'; | 1235 | *cmdbuf = '\0'; |
| 1237 | *(cmd_hist[cmd_head]) = '\0'; | 1236 | *(cmd_hist[cmd_head]) = '\0'; |
| 1238 | 1237 | ||
| 1238 | if (KDB_FLAG(ONLY_DO_DUMP)) { | ||
| 1239 | /* kdb is off but a catastrophic error requires a dump. | ||
| 1240 | * Take the dump and reboot. | ||
| 1241 | * Turn on logging so the kdb output appears in the log | ||
| 1242 | * buffer in the dump. | ||
| 1243 | */ | ||
| 1244 | const char *setargs[] = { "set", "LOGGING", "1" }; | ||
| 1245 | kdb_set(2, setargs); | ||
| 1246 | kdb_reboot(0, NULL); | ||
| 1247 | /*NOTREACHED*/ | ||
| 1248 | } | ||
| 1249 | |||
| 1239 | do_full_getstr: | 1250 | do_full_getstr: |
| 1240 | #if defined(CONFIG_SMP) | 1251 | #if defined(CONFIG_SMP) |
| 1241 | snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), | 1252 | snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), |
| @@ -1389,9 +1400,6 @@ int kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error, | |||
| 1389 | if (KDB_STATE(DOING_SS)) | 1400 | if (KDB_STATE(DOING_SS)) |
| 1390 | KDB_STATE_CLEAR(SSBPT); | 1401 | KDB_STATE_CLEAR(SSBPT); |
| 1391 | 1402 | ||
| 1392 | /* Clean up any keyboard devices before leaving */ | ||
| 1393 | kdb_kbd_cleanup_state(); | ||
| 1394 | |||
| 1395 | return result; | 1403 | return result; |
| 1396 | } | 1404 | } |
| 1397 | 1405 | ||
| @@ -1974,7 +1982,7 @@ static int kdb_lsmod(int argc, const char **argv) | |||
| 1974 | kdb_printf("%-20s%8u 0x%p ", mod->name, | 1982 | kdb_printf("%-20s%8u 0x%p ", mod->name, |
| 1975 | mod->core_size, (void *)mod); | 1983 | mod->core_size, (void *)mod); |
| 1976 | #ifdef CONFIG_MODULE_UNLOAD | 1984 | #ifdef CONFIG_MODULE_UNLOAD |
| 1977 | kdb_printf("%4ld ", module_refcount(mod)); | 1985 | kdb_printf("%4d ", module_refcount(mod)); |
| 1978 | #endif | 1986 | #endif |
| 1979 | if (mod->state == MODULE_STATE_GOING) | 1987 | if (mod->state == MODULE_STATE_GOING) |
| 1980 | kdb_printf(" (Unloading)"); | 1988 | kdb_printf(" (Unloading)"); |
| @@ -2029,15 +2037,8 @@ static int kdb_env(int argc, const char **argv) | |||
| 2029 | */ | 2037 | */ |
| 2030 | static int kdb_dmesg(int argc, const char **argv) | 2038 | static int kdb_dmesg(int argc, const char **argv) |
| 2031 | { | 2039 | { |
| 2032 | int diag; | 2040 | char *syslog_data[4], *start, *end, c = '\0', *p; |
| 2033 | int logging; | 2041 | int diag, logging, logsize, lines = 0, adjust = 0, n; |
| 2034 | int lines = 0; | ||
| 2035 | int adjust = 0; | ||
| 2036 | int n = 0; | ||
| 2037 | int skip = 0; | ||
| 2038 | struct kmsg_dumper dumper = { .active = 1 }; | ||
| 2039 | size_t len; | ||
| 2040 | char buf[201]; | ||
| 2041 | 2042 | ||
| 2042 | if (argc > 2) | 2043 | if (argc > 2) |
| 2043 | return KDB_ARGCOUNT; | 2044 | return KDB_ARGCOUNT; |
| @@ -2060,10 +2061,22 @@ static int kdb_dmesg(int argc, const char **argv) | |||
| 2060 | kdb_set(2, setargs); | 2061 | kdb_set(2, setargs); |
| 2061 | } | 2062 | } |
| 2062 | 2063 | ||
| 2063 | kmsg_dump_rewind_nolock(&dumper); | 2064 | /* syslog_data[0,1] physical start, end+1. syslog_data[2,3] |
| 2064 | while (kmsg_dump_get_line_nolock(&dumper, 1, NULL, 0, NULL)) | 2065 | * logical start, end+1. */ |
| 2065 | n++; | 2066 | kdb_syslog_data(syslog_data); |
| 2066 | 2067 | if (syslog_data[2] == syslog_data[3]) | |
| 2068 | return 0; | ||
| 2069 | logsize = syslog_data[1] - syslog_data[0]; | ||
| 2070 | start = syslog_data[2]; | ||
| 2071 | end = syslog_data[3]; | ||
| 2072 | #define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0]) | ||
| 2073 | for (n = 0, p = start; p < end; ++p) { | ||
| 2074 | c = *KDB_WRAP(p); | ||
| 2075 | if (c == '\n') | ||
| 2076 | ++n; | ||
| 2077 | } | ||
| 2078 | if (c != '\n') | ||
| 2079 | ++n; | ||
| 2067 | if (lines < 0) { | 2080 | if (lines < 0) { |
| 2068 | if (adjust >= n) | 2081 | if (adjust >= n) |
| 2069 | kdb_printf("buffer only contains %d lines, nothing " | 2082 | kdb_printf("buffer only contains %d lines, nothing " |
| @@ -2071,11 +2084,21 @@ static int kdb_dmesg(int argc, const char **argv) | |||
| 2071 | else if (adjust - lines >= n) | 2084 | else if (adjust - lines >= n) |
| 2072 | kdb_printf("buffer only contains %d lines, last %d " | 2085 | kdb_printf("buffer only contains %d lines, last %d " |
| 2073 | "lines printed\n", n, n - adjust); | 2086 | "lines printed\n", n, n - adjust); |
| 2074 | skip = adjust; | 2087 | if (adjust) { |
| 2075 | lines = abs(lines); | 2088 | for (; start < end && adjust; ++start) { |
| 2089 | if (*KDB_WRAP(start) == '\n') | ||
| 2090 | --adjust; | ||
| 2091 | } | ||
| 2092 | if (start < end) | ||
| 2093 | ++start; | ||
| 2094 | } | ||
| 2095 | for (p = start; p < end && lines; ++p) { | ||
| 2096 | if (*KDB_WRAP(p) == '\n') | ||
| 2097 | ++lines; | ||
| 2098 | } | ||
| 2099 | end = p; | ||
| 2076 | } else if (lines > 0) { | 2100 | } else if (lines > 0) { |
| 2077 | skip = n - lines - adjust; | 2101 | int skip = n - (adjust + lines); |
| 2078 | lines = abs(lines); | ||
| 2079 | if (adjust >= n) { | 2102 | if (adjust >= n) { |
| 2080 | kdb_printf("buffer only contains %d lines, " | 2103 | kdb_printf("buffer only contains %d lines, " |
| 2081 | "nothing printed\n", n); | 2104 | "nothing printed\n", n); |
| @@ -2086,56 +2109,39 @@ static int kdb_dmesg(int argc, const char **argv) | |||
| 2086 | kdb_printf("buffer only contains %d lines, first " | 2109 | kdb_printf("buffer only contains %d lines, first " |
| 2087 | "%d lines printed\n", n, lines); | 2110 | "%d lines printed\n", n, lines); |
| 2088 | } | 2111 | } |
| 2089 | } else { | 2112 | for (; start < end && skip; ++start) { |
| 2090 | lines = n; | 2113 | if (*KDB_WRAP(start) == '\n') |
| 2091 | } | 2114 | --skip; |
| 2092 | |||
| 2093 | if (skip >= n || skip < 0) | ||
| 2094 | return 0; | ||
| 2095 | |||
| 2096 | kmsg_dump_rewind_nolock(&dumper); | ||
| 2097 | while (kmsg_dump_get_line_nolock(&dumper, 1, buf, sizeof(buf), &len)) { | ||
| 2098 | if (skip) { | ||
| 2099 | skip--; | ||
| 2100 | continue; | ||
| 2101 | } | 2115 | } |
| 2102 | if (!lines--) | 2116 | for (p = start; p < end && lines; ++p) { |
| 2103 | break; | 2117 | if (*KDB_WRAP(p) == '\n') |
| 2118 | --lines; | ||
| 2119 | } | ||
| 2120 | end = p; | ||
| 2121 | } | ||
| 2122 | /* Do a line at a time (max 200 chars) to reduce protocol overhead */ | ||
| 2123 | c = '\n'; | ||
| 2124 | while (start != end) { | ||
| 2125 | char buf[201]; | ||
| 2126 | p = buf; | ||
| 2104 | if (KDB_FLAG(CMD_INTERRUPT)) | 2127 | if (KDB_FLAG(CMD_INTERRUPT)) |
| 2105 | return 0; | 2128 | return 0; |
| 2106 | 2129 | while (start < end && (c = *KDB_WRAP(start)) && | |
| 2107 | kdb_printf("%.*s\n", (int)len - 1, buf); | 2130 | (p - buf) < sizeof(buf)-1) { |
| 2131 | ++start; | ||
| 2132 | *p++ = c; | ||
| 2133 | if (c == '\n') | ||
| 2134 | break; | ||
| 2135 | } | ||
| 2136 | *p = '\0'; | ||
| 2137 | kdb_printf("%s", buf); | ||
| 2108 | } | 2138 | } |
| 2139 | if (c != '\n') | ||
| 2140 | kdb_printf("\n"); | ||
| 2109 | 2141 | ||
| 2110 | return 0; | 2142 | return 0; |
| 2111 | } | 2143 | } |
| 2112 | #endif /* CONFIG_PRINTK */ | 2144 | #endif /* CONFIG_PRINTK */ |
| 2113 | |||
| 2114 | /* Make sure we balance enable/disable calls, must disable first. */ | ||
| 2115 | static atomic_t kdb_nmi_disabled; | ||
| 2116 | |||
| 2117 | static int kdb_disable_nmi(int argc, const char *argv[]) | ||
| 2118 | { | ||
| 2119 | if (atomic_read(&kdb_nmi_disabled)) | ||
| 2120 | return 0; | ||
| 2121 | atomic_set(&kdb_nmi_disabled, 1); | ||
| 2122 | arch_kgdb_ops.enable_nmi(0); | ||
| 2123 | return 0; | ||
| 2124 | } | ||
| 2125 | |||
| 2126 | static int kdb_param_enable_nmi(const char *val, const struct kernel_param *kp) | ||
| 2127 | { | ||
| 2128 | if (!atomic_add_unless(&kdb_nmi_disabled, -1, 0)) | ||
| 2129 | return -EINVAL; | ||
| 2130 | arch_kgdb_ops.enable_nmi(1); | ||
| 2131 | return 0; | ||
| 2132 | } | ||
| 2133 | |||
| 2134 | static const struct kernel_param_ops kdb_param_ops_enable_nmi = { | ||
| 2135 | .set = kdb_param_enable_nmi, | ||
| 2136 | }; | ||
| 2137 | module_param_cb(enable_nmi, &kdb_param_ops_enable_nmi, NULL, 0600); | ||
| 2138 | |||
| 2139 | /* | 2145 | /* |
| 2140 | * kdb_cpu - This function implements the 'cpu' command. | 2146 | * kdb_cpu - This function implements the 'cpu' command. |
| 2141 | * cpu [<cpunum>] | 2147 | * cpu [<cpunum>] |
| @@ -2880,10 +2886,6 @@ static void __init kdb_inittab(void) | |||
| 2880 | kdb_register_repeat("dmesg", kdb_dmesg, "[lines]", | 2886 | kdb_register_repeat("dmesg", kdb_dmesg, "[lines]", |
| 2881 | "Display syslog buffer", 0, KDB_REPEAT_NONE); | 2887 | "Display syslog buffer", 0, KDB_REPEAT_NONE); |
| 2882 | #endif | 2888 | #endif |
| 2883 | if (arch_kgdb_ops.enable_nmi) { | ||
| 2884 | kdb_register_repeat("disable_nmi", kdb_disable_nmi, "", | ||
| 2885 | "Disable NMI entry to KDB", 0, KDB_REPEAT_NONE); | ||
| 2886 | } | ||
| 2887 | kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"", | 2889 | kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"", |
| 2888 | "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE); | 2890 | "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE); |
| 2889 | kdb_register_repeat("kill", kdb_kill, "<-signal> <pid>", | 2891 | kdb_register_repeat("kill", kdb_kill, "<-signal> <pid>", |
diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h index 392ec6a2584..e381d105b40 100644 --- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h | |||
| @@ -205,6 +205,7 @@ extern char kdb_grep_string[]; | |||
| 205 | extern int kdb_grep_leading; | 205 | extern int kdb_grep_leading; |
| 206 | extern int kdb_grep_trailing; | 206 | extern int kdb_grep_trailing; |
| 207 | extern char *kdb_cmds[]; | 207 | extern char *kdb_cmds[]; |
| 208 | extern void kdb_syslog_data(char *syslog_data[]); | ||
| 208 | extern unsigned long kdb_task_state_string(const char *); | 209 | extern unsigned long kdb_task_state_string(const char *); |
| 209 | extern char kdb_task_state_char (const struct task_struct *); | 210 | extern char kdb_task_state_char (const struct task_struct *); |
| 210 | extern unsigned long kdb_task_state(const struct task_struct *p, | 211 | extern unsigned long kdb_task_state(const struct task_struct *p, |
| @@ -245,13 +246,6 @@ extern void debug_kusage(void); | |||
| 245 | 246 | ||
| 246 | extern void kdb_set_current_task(struct task_struct *); | 247 | extern void kdb_set_current_task(struct task_struct *); |
| 247 | extern struct task_struct *kdb_current_task; | 248 | extern struct task_struct *kdb_current_task; |
| 248 | |||
| 249 | #ifdef CONFIG_KDB_KEYBOARD | ||
| 250 | extern void kdb_kbd_cleanup_state(void); | ||
| 251 | #else /* ! CONFIG_KDB_KEYBOARD */ | ||
| 252 | #define kdb_kbd_cleanup_state() | ||
| 253 | #endif /* ! CONFIG_KDB_KEYBOARD */ | ||
| 254 | |||
| 255 | #ifdef CONFIG_MODULES | 249 | #ifdef CONFIG_MODULES |
| 256 | extern struct list_head *kdb_modules; | 250 | extern struct list_head *kdb_modules; |
| 257 | #endif /* CONFIG_MODULES */ | 251 | #endif /* CONFIG_MODULES */ |
diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c index d35cc2d3a4c..5532dd37aa8 100644 --- a/kernel/debug/kdb/kdb_support.c +++ b/kernel/debug/kdb/kdb_support.c | |||
| @@ -384,9 +384,9 @@ static int kdb_getphys(void *res, unsigned long addr, size_t size) | |||
| 384 | if (!pfn_valid(pfn)) | 384 | if (!pfn_valid(pfn)) |
| 385 | return 1; | 385 | return 1; |
| 386 | page = pfn_to_page(pfn); | 386 | page = pfn_to_page(pfn); |
| 387 | vaddr = kmap_atomic(page); | 387 | vaddr = kmap_atomic(page, KM_KDB); |
| 388 | memcpy(res, vaddr + (addr & (PAGE_SIZE - 1)), size); | 388 | memcpy(res, vaddr + (addr & (PAGE_SIZE - 1)), size); |
| 389 | kunmap_atomic(vaddr); | 389 | kunmap_atomic(vaddr, KM_KDB); |
| 390 | 390 | ||
| 391 | return 0; | 391 | return 0; |
| 392 | } | 392 | } |
| @@ -636,7 +636,7 @@ char kdb_task_state_char (const struct task_struct *p) | |||
| 636 | (p->exit_state & EXIT_ZOMBIE) ? 'Z' : | 636 | (p->exit_state & EXIT_ZOMBIE) ? 'Z' : |
| 637 | (p->exit_state & EXIT_DEAD) ? 'E' : | 637 | (p->exit_state & EXIT_DEAD) ? 'E' : |
| 638 | (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?'; | 638 | (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?'; |
| 639 | if (is_idle_task(p)) { | 639 | if (p->pid == 0) { |
| 640 | /* Idle task. Is it really idle, apart from the kdb | 640 | /* Idle task. Is it really idle, apart from the kdb |
| 641 | * interrupt? */ | 641 | * interrupt? */ |
| 642 | if (!kdb_task_has_cpu(p) || kgdb_info[cpu].irq_depth == 1) { | 642 | if (!kdb_task_has_cpu(p) || kgdb_info[cpu].irq_depth == 1) { |
