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/kdb | |
| parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) | |
Patched in Tegra support.
Diffstat (limited to 'kernel/debug/kdb')
| -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 |
8 files changed, 117 insertions, 197 deletions
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) { |
