KGDB/KDB New:

* KDB: improved searching
    * No longer enter debug core on panic if panic timeout is set
 
 KGDB/KDB regressions / cleanups
    * fix pdf doc build errors
    * prevent junk characters on kdb console from printk levels
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJU5qxHAAoJEIciOldedpOjliYP/izuoNZ/EtjjeihOL44ic0o0
 cmvdSc/ovR/mO4fbDpftMB0nhzclgRyAvr+VTPd3Bp5Poh+wJ0ZKu1R7f+ioSN73
 Y4ek9PJqPSBQr+JdfPK80N56Choeni48bsC6up12i3BTfXobj81zlu4Sj0SMOoHq
 IkFkB7soRuiFoc5IkKMvf3N3T9j1PnEULmHteNDRr0hTmGipEzkD3zocc/bRFV/l
 JTZRzIMGBNGnF01DPLDcuvbu0wGBh6ADMBLtx5v1UrhV32ypfJq2bgxFvgM/AXn2
 3VG4HcRbVsGmlBOahFR6X0DE/WAplw01yu1EabR2EWUePyz41cnSkxl4nR/NNhwz
 qMbr3uzu1iWUTTz5ySRcWxSuRRCihVQqNk6p+y21N/jY/5cr2jI03qJm0zZ/ObqL
 VUcPE7CfdcriCDXoepgXZE4XfX65Jf5tUiyiCj+1ds05ab5qHELIwKOZdjU2ON1b
 pb2ElPngGSEEoU/eSDgP2RVJ9Mk/k5s2TxaPXVJNkeWGNxPU5HtCytZpVI5hckbP
 /NZWTtyUDZ85is8cWUkHEdjnQ+CdzaA/FwJEqnB0or2is91mo8uBxP5BvdqPnPL0
 QdPPnVgD72dumXfJpH2HY3DdUs24LaP0vgSO8ELKgfA67nprS+5xztNSd8ekNnhF
 4wMhZbuAhB68E6bA0X7G
 =TH0R
 -----END PGP SIGNATURE-----

Merge tag 'for_linux-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb

Pull kgdb/kdb updates from Jason Wessel:
 "KGDB/KDB New:
   - KDB: improved searching
   - No longer enter debug core on panic if panic timeout is set

  KGDB/KDB regressions / cleanups
   - fix pdf doc build errors
   - prevent junk characters on kdb console from printk levels"

* tag 'for_linux-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb:
  kgdb, docs: Fix <para> pdfdocs build errors
  debug: prevent entering debug mode on panic/exception.
  kdb: Const qualifier for kdb_getstr's prompt argument
  kdb: Provide forward search at more prompt
  kdb: Fix a prompt management bug when using | grep
  kdb: Remove stack dump when entering kgdb due to NMI
  kdb: Avoid printing KERN_ levels to consoles
  kdb: Fix off by one error in kdb_cpu()
  kdb: fix incorrect counts in KDB summary command output
This commit is contained in:
Linus Torvalds 2015-02-20 15:13:29 -08:00
commit 4fbd0a81a0
7 changed files with 74 additions and 27 deletions

View File

@ -197,6 +197,7 @@
may be configured as a kernel built-in or a kernel loadable module. may be configured as a kernel built-in or a kernel loadable module.
You can only make use of <constant>kgdbwait</constant> and early You can only make use of <constant>kgdbwait</constant> and early
debugging if you build kgdboc into the kernel as a built-in. debugging if you build kgdboc into the kernel as a built-in.
</para>
<para>Optionally you can elect to activate kms (Kernel Mode <para>Optionally you can elect to activate kms (Kernel Mode
Setting) integration. When you use kms with kgdboc and you have a Setting) integration. When you use kms with kgdboc and you have a
video driver that has atomic mode setting hooks, it is possible to video driver that has atomic mode setting hooks, it is possible to
@ -206,7 +207,6 @@
crashes or doing analysis of memory with kdb while allowing the crashes or doing analysis of memory with kdb while allowing the
full graphics console applications to run. full graphics console applications to run.
</para> </para>
</para>
<sect2 id="kgdbocArgs"> <sect2 id="kgdbocArgs">
<title>kgdboc arguments</title> <title>kgdboc arguments</title>
<para>Usage: <constant>kgdboc=[kms][[,]kbd][[,]serial_device][,baud]</constant></para> <para>Usage: <constant>kgdboc=[kms][[,]kbd][[,]serial_device][,baud]</constant></para>
@ -284,7 +284,6 @@
</listitem> </listitem>
</orderedlist> </orderedlist>
</para> </para>
</sect3>
<para>NOTE: Kgdboc does not support interrupting the target via the <para>NOTE: Kgdboc does not support interrupting the target via the
gdb remote protocol. You must manually send a sysrq-g unless you gdb remote protocol. You must manually send a sysrq-g unless you
have a proxy that splits console output to a terminal program. have a proxy that splits console output to a terminal program.
@ -305,6 +304,7 @@
as well as on the initial connect, or to use a debugger proxy that as well as on the initial connect, or to use a debugger proxy that
allows an unmodified gdb to do the debugging. allows an unmodified gdb to do the debugging.
</para> </para>
</sect3>
</sect2> </sect2>
</sect1> </sect1>
<sect1 id="kgdbwait"> <sect1 id="kgdbwait">
@ -350,12 +350,12 @@
</para> </para>
</listitem> </listitem>
</orderedlist> </orderedlist>
</para>
<para>IMPORTANT NOTE: You cannot use kgdboc + kgdbcon on a tty that is an <para>IMPORTANT NOTE: You cannot use kgdboc + kgdbcon on a tty that is an
active system console. An example of incorrect usage is <constant>console=ttyS0,115200 kgdboc=ttyS0 kgdbcon</constant> active system console. An example of incorrect usage is <constant>console=ttyS0,115200 kgdboc=ttyS0 kgdbcon</constant>
</para> </para>
<para>It is possible to use this option with kgdboc on a tty that is not a system console. <para>It is possible to use this option with kgdboc on a tty that is not a system console.
</para> </para>
</para>
</sect1> </sect1>
<sect1 id="kgdbreboot"> <sect1 id="kgdbreboot">
<title>Run time parameter: kgdbreboot</title> <title>Run time parameter: kgdbreboot</title>

View File

@ -156,8 +156,14 @@ typedef enum {
KDB_REASON_SYSTEM_NMI, /* In NMI due to SYSTEM cmd; regs valid */ KDB_REASON_SYSTEM_NMI, /* In NMI due to SYSTEM cmd; regs valid */
} kdb_reason_t; } kdb_reason_t;
enum kdb_msgsrc {
KDB_MSGSRC_INTERNAL, /* direct call to kdb_printf() */
KDB_MSGSRC_PRINTK, /* trapped from printk() */
};
extern int kdb_trap_printk; extern int kdb_trap_printk;
extern __printf(1, 0) int vkdb_printf(const char *fmt, va_list args); extern __printf(2, 0) int vkdb_printf(enum kdb_msgsrc src, const char *fmt,
va_list args);
extern __printf(1, 2) int kdb_printf(const char *, ...); extern __printf(1, 2) int kdb_printf(const char *, ...);
typedef __printf(1, 2) int (*kdb_printf_t)(const char *, ...); typedef __printf(1, 2) int (*kdb_printf_t)(const char *, ...);

View File

@ -604,7 +604,7 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
online_cpus) online_cpus)
cpu_relax(); cpu_relax();
if (!time_left) if (!time_left)
pr_crit("KGDB: Timed out waiting for secondary CPUs.\n"); pr_crit("Timed out waiting for secondary CPUs.\n");
/* /*
* At this point the primary processor is completely * At this point the primary processor is completely
@ -696,6 +696,14 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
if (arch_kgdb_ops.enable_nmi) if (arch_kgdb_ops.enable_nmi)
arch_kgdb_ops.enable_nmi(0); arch_kgdb_ops.enable_nmi(0);
/*
* Avoid entering the debugger if we were triggered due to an oops
* but panic_timeout indicates the system should automatically
* reboot on panic. We don't want to get stuck waiting for input
* on such systems, especially if its "just" an oops.
*/
if (signo != SIGTRAP && panic_timeout)
return 1;
memset(ks, 0, sizeof(struct kgdb_state)); memset(ks, 0, sizeof(struct kgdb_state));
ks->cpu = raw_smp_processor_id(); ks->cpu = raw_smp_processor_id();
@ -828,6 +836,15 @@ static int kgdb_panic_event(struct notifier_block *self,
unsigned long val, unsigned long val,
void *data) void *data)
{ {
/*
* Avoid entering the debugger if we were triggered due to a panic
* We don't want to get stuck waiting for input from user in such case.
* panic_timeout indicates the system should automatically
* reboot on panic.
*/
if (panic_timeout)
return NOTIFY_DONE;
if (dbg_kdb_mode) if (dbg_kdb_mode)
kdb_printf("PANIC: %s\n", (char *)data); kdb_printf("PANIC: %s\n", (char *)data);
kgdb_breakpoint(); kgdb_breakpoint();

View File

@ -439,7 +439,7 @@ static char *kdb_read(char *buffer, size_t bufsize)
* substituted for %d, %x or %o in the prompt. * substituted for %d, %x or %o in the prompt.
*/ */
char *kdb_getstr(char *buffer, size_t bufsize, char *prompt) char *kdb_getstr(char *buffer, size_t bufsize, const char *prompt)
{ {
if (prompt && kdb_prompt_str != prompt) if (prompt && kdb_prompt_str != prompt)
strncpy(kdb_prompt_str, prompt, CMD_BUFLEN); strncpy(kdb_prompt_str, prompt, CMD_BUFLEN);
@ -548,7 +548,7 @@ static int kdb_search_string(char *searched, char *searchfor)
return 0; return 0;
} }
int vkdb_printf(const char *fmt, va_list ap) int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap)
{ {
int diag; int diag;
int linecount; int linecount;
@ -680,6 +680,12 @@ int vkdb_printf(const char *fmt, va_list ap)
size_avail = sizeof(kdb_buffer) - len; size_avail = sizeof(kdb_buffer) - len;
goto kdb_print_out; goto kdb_print_out;
} }
if (kdb_grepping_flag >= KDB_GREPPING_FLAG_SEARCH)
/*
* This was a interactive search (using '/' at more
* prompt) and it has completed. Clear the flag.
*/
kdb_grepping_flag = 0;
/* /*
* at this point the string is a full line and * at this point the string is a full line and
* should be printed, up to the null. * should be printed, up to the null.
@ -691,19 +697,20 @@ int vkdb_printf(const char *fmt, va_list ap)
* Write to all consoles. * Write to all consoles.
*/ */
retlen = strlen(kdb_buffer); retlen = strlen(kdb_buffer);
cp = (char *) printk_skip_level(kdb_buffer);
if (!dbg_kdb_mode && kgdb_connected) { if (!dbg_kdb_mode && kgdb_connected) {
gdbstub_msg_write(kdb_buffer, retlen); gdbstub_msg_write(cp, retlen - (cp - kdb_buffer));
} else { } else {
if (dbg_io_ops && !dbg_io_ops->is_console) { if (dbg_io_ops && !dbg_io_ops->is_console) {
len = retlen; len = retlen - (cp - kdb_buffer);
cp = kdb_buffer; cp2 = cp;
while (len--) { while (len--) {
dbg_io_ops->write_char(*cp); dbg_io_ops->write_char(*cp2);
cp++; cp2++;
} }
} }
while (c) { while (c) {
c->write(c, kdb_buffer, retlen); c->write(c, cp, retlen - (cp - kdb_buffer));
touch_nmi_watchdog(); touch_nmi_watchdog();
c = c->next; c = c->next;
} }
@ -711,7 +718,10 @@ int vkdb_printf(const char *fmt, va_list ap)
if (logging) { if (logging) {
saved_loglevel = console_loglevel; saved_loglevel = console_loglevel;
console_loglevel = CONSOLE_LOGLEVEL_SILENT; console_loglevel = CONSOLE_LOGLEVEL_SILENT;
printk(KERN_INFO "%s", kdb_buffer); if (printk_get_level(kdb_buffer) || src == KDB_MSGSRC_PRINTK)
printk("%s", kdb_buffer);
else
pr_info("%s", kdb_buffer);
} }
if (KDB_STATE(PAGER)) { if (KDB_STATE(PAGER)) {
@ -794,11 +804,23 @@ int vkdb_printf(const char *fmt, va_list ap)
kdb_nextline = linecount - 1; kdb_nextline = linecount - 1;
kdb_printf("\r"); kdb_printf("\r");
suspend_grep = 1; /* for this recursion */ suspend_grep = 1; /* for this recursion */
} else if (buf1[0] == '/' && !kdb_grepping_flag) {
kdb_printf("\r");
kdb_getstr(kdb_grep_string, KDB_GREP_STRLEN,
kdbgetenv("SEARCHPROMPT") ?: "search> ");
*strchrnul(kdb_grep_string, '\n') = '\0';
kdb_grepping_flag += KDB_GREPPING_FLAG_SEARCH;
suspend_grep = 1; /* for this recursion */
} else if (buf1[0] && buf1[0] != '\n') { } else if (buf1[0] && buf1[0] != '\n') {
/* user hit something other than enter */ /* user hit something other than enter */
suspend_grep = 1; /* for this recursion */ suspend_grep = 1; /* for this recursion */
kdb_printf("\nOnly 'q' or 'Q' are processed at more " if (buf1[0] != '/')
"prompt, input ignored\n"); kdb_printf(
"\nOnly 'q', 'Q' or '/' are processed at "
"more prompt, input ignored\n");
else
kdb_printf("\n'/' cannot be used during | "
"grep filtering, input ignored\n");
} else if (kdb_grepping_flag) { } else if (kdb_grepping_flag) {
/* user hit enter */ /* user hit enter */
suspend_grep = 1; /* for this recursion */ suspend_grep = 1; /* for this recursion */
@ -844,7 +866,7 @@ int kdb_printf(const char *fmt, ...)
int r; int r;
va_start(ap, fmt); va_start(ap, fmt);
r = vkdb_printf(fmt, ap); r = vkdb_printf(KDB_MSGSRC_INTERNAL, fmt, ap);
va_end(ap); va_end(ap);
return r; return r;

View File

@ -50,8 +50,7 @@
static int kdb_cmd_enabled = CONFIG_KDB_DEFAULT_ENABLE; static int kdb_cmd_enabled = CONFIG_KDB_DEFAULT_ENABLE;
module_param_named(cmd_enable, kdb_cmd_enabled, int, 0600); module_param_named(cmd_enable, kdb_cmd_enabled, int, 0600);
#define GREP_LEN 256 char kdb_grep_string[KDB_GREP_STRLEN];
char kdb_grep_string[GREP_LEN];
int kdb_grepping_flag; int kdb_grepping_flag;
EXPORT_SYMBOL(kdb_grepping_flag); EXPORT_SYMBOL(kdb_grepping_flag);
int kdb_grep_leading; int kdb_grep_leading;
@ -870,7 +869,7 @@ static void parse_grep(const char *str)
len = strlen(cp); len = strlen(cp);
if (!len) if (!len)
return; return;
if (len >= GREP_LEN) { if (len >= KDB_GREP_STRLEN) {
kdb_printf("search string too long\n"); kdb_printf("search string too long\n");
return; return;
} }
@ -915,13 +914,12 @@ int kdb_parse(const char *cmdstr)
char *cp; char *cp;
char *cpp, quoted; char *cpp, quoted;
kdbtab_t *tp; kdbtab_t *tp;
int i, escaped, ignore_errors = 0, check_grep; int i, escaped, ignore_errors = 0, check_grep = 0;
/* /*
* First tokenize the command string. * First tokenize the command string.
*/ */
cp = (char *)cmdstr; cp = (char *)cmdstr;
kdb_grepping_flag = check_grep = 0;
if (KDB_FLAG(CMD_INTERRUPT)) { if (KDB_FLAG(CMD_INTERRUPT)) {
/* Previous command was interrupted, newline must not /* Previous command was interrupted, newline must not
@ -1247,7 +1245,6 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
kdb_printf("due to NonMaskable Interrupt @ " kdb_printf("due to NonMaskable Interrupt @ "
kdb_machreg_fmt "\n", kdb_machreg_fmt "\n",
instruction_pointer(regs)); instruction_pointer(regs));
kdb_dumpregs(regs);
break; break;
case KDB_REASON_SSTEP: case KDB_REASON_SSTEP:
case KDB_REASON_BREAK: case KDB_REASON_BREAK:
@ -1281,6 +1278,9 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
*/ */
kdb_nextline = 1; kdb_nextline = 1;
KDB_STATE_CLEAR(SUPPRESS); KDB_STATE_CLEAR(SUPPRESS);
kdb_grepping_flag = 0;
/* ensure the old search does not leak into '/' commands */
kdb_grep_string[0] = '\0';
cmdbuf = cmd_cur; cmdbuf = cmd_cur;
*cmdbuf = '\0'; *cmdbuf = '\0';
@ -2256,7 +2256,7 @@ static int kdb_cpu(int argc, const char **argv)
/* /*
* Validate cpunum * Validate cpunum
*/ */
if ((cpunum > NR_CPUS) || !kgdb_info[cpunum].enter_kgdb) if ((cpunum >= CONFIG_NR_CPUS) || !kgdb_info[cpunum].enter_kgdb)
return KDB_BADCPUNUM; return KDB_BADCPUNUM;
dbg_switch_cpu = cpunum; dbg_switch_cpu = cpunum;
@ -2583,7 +2583,7 @@ static int kdb_summary(int argc, const char **argv)
#define K(x) ((x) << (PAGE_SHIFT - 10)) #define K(x) ((x) << (PAGE_SHIFT - 10))
kdb_printf("\nMemTotal: %8lu kB\nMemFree: %8lu kB\n" kdb_printf("\nMemTotal: %8lu kB\nMemFree: %8lu kB\n"
"Buffers: %8lu kB\n", "Buffers: %8lu kB\n",
val.totalram, val.freeram, val.bufferram); K(val.totalram), K(val.freeram), K(val.bufferram));
return 0; return 0;
} }

View File

@ -196,7 +196,9 @@ extern int kdb_main_loop(kdb_reason_t, kdb_reason_t,
/* Miscellaneous functions and data areas */ /* Miscellaneous functions and data areas */
extern int kdb_grepping_flag; extern int kdb_grepping_flag;
#define KDB_GREPPING_FLAG_SEARCH 0x8000
extern char kdb_grep_string[]; extern char kdb_grep_string[];
#define KDB_GREP_STRLEN 256
extern int kdb_grep_leading; extern int kdb_grep_leading;
extern int kdb_grep_trailing; extern int kdb_grep_trailing;
extern char *kdb_cmds[]; extern char *kdb_cmds[];
@ -209,7 +211,7 @@ extern void kdb_ps1(const struct task_struct *p);
extern void kdb_print_nameval(const char *name, unsigned long val); extern void kdb_print_nameval(const char *name, unsigned long val);
extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info); extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
extern void kdb_meminfo_proc_show(void); extern void kdb_meminfo_proc_show(void);
extern char *kdb_getstr(char *, size_t, char *); extern char *kdb_getstr(char *, size_t, const char *);
extern void kdb_gdb_state_pass(char *buf); extern void kdb_gdb_state_pass(char *buf);
/* Defines for kdb_symbol_print */ /* Defines for kdb_symbol_print */

View File

@ -1811,7 +1811,7 @@ int vprintk_default(const char *fmt, va_list args)
#ifdef CONFIG_KGDB_KDB #ifdef CONFIG_KGDB_KDB
if (unlikely(kdb_trap_printk)) { if (unlikely(kdb_trap_printk)) {
r = vkdb_printf(fmt, args); r = vkdb_printf(KDB_MSGSRC_PRINTK, fmt, args);
return r; return r;
} }
#endif #endif