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.
You can only make use of <constant>kgdbwait</constant> and early
debugging if you build kgdboc into the kernel as a built-in.
</para>
<para>Optionally you can elect to activate kms (Kernel Mode
Setting) integration. When you use kms with kgdboc and you have a
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
full graphics console applications to run.
</para>
</para>
<sect2 id="kgdbocArgs">
<title>kgdboc arguments</title>
<para>Usage: <constant>kgdboc=[kms][[,]kbd][[,]serial_device][,baud]</constant></para>
@ -284,7 +284,6 @@
</listitem>
</orderedlist>
</para>
</sect3>
<para>NOTE: Kgdboc does not support interrupting the target via the
gdb remote protocol. You must manually send a sysrq-g unless you
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
allows an unmodified gdb to do the debugging.
</para>
</sect3>
</sect2>
</sect1>
<sect1 id="kgdbwait">
@ -350,12 +350,12 @@
</para>
</listitem>
</orderedlist>
</para>
<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>
</para>
<para>It is possible to use this option with kgdboc on a tty that is not a system console.
</para>
</para>
</sect1>
<sect1 id="kgdbreboot">
<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_t;
enum kdb_msgsrc {
KDB_MSGSRC_INTERNAL, /* direct call to kdb_printf() */
KDB_MSGSRC_PRINTK, /* trapped from 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 *, ...);
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)
cpu_relax();
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
@ -696,6 +696,14 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
if (arch_kgdb_ops.enable_nmi)
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));
ks->cpu = raw_smp_processor_id();
@ -828,6 +836,15 @@ static int kgdb_panic_event(struct notifier_block *self,
unsigned long val,
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)
kdb_printf("PANIC: %s\n", (char *)data);
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.
*/
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)
strncpy(kdb_prompt_str, prompt, CMD_BUFLEN);
@ -548,7 +548,7 @@ static int kdb_search_string(char *searched, char *searchfor)
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 linecount;
@ -680,6 +680,12 @@ int vkdb_printf(const char *fmt, va_list ap)
size_avail = sizeof(kdb_buffer) - len;
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
* should be printed, up to the null.
@ -691,19 +697,20 @@ int vkdb_printf(const char *fmt, va_list ap)
* Write to all consoles.
*/
retlen = strlen(kdb_buffer);
cp = (char *) printk_skip_level(kdb_buffer);
if (!dbg_kdb_mode && kgdb_connected) {
gdbstub_msg_write(kdb_buffer, retlen);
gdbstub_msg_write(cp, retlen - (cp - kdb_buffer));
} else {
if (dbg_io_ops && !dbg_io_ops->is_console) {
len = retlen;
cp = kdb_buffer;
len = retlen - (cp - kdb_buffer);
cp2 = cp;
while (len--) {
dbg_io_ops->write_char(*cp);
cp++;
dbg_io_ops->write_char(*cp2);
cp2++;
}
}
while (c) {
c->write(c, kdb_buffer, retlen);
c->write(c, cp, retlen - (cp - kdb_buffer));
touch_nmi_watchdog();
c = c->next;
}
@ -711,7 +718,10 @@ int vkdb_printf(const char *fmt, va_list ap)
if (logging) {
saved_loglevel = console_loglevel;
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)) {
@ -794,11 +804,23 @@ int vkdb_printf(const char *fmt, va_list ap)
kdb_nextline = linecount - 1;
kdb_printf("\r");
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') {
/* user hit something other than enter */
suspend_grep = 1; /* for this recursion */
kdb_printf("\nOnly 'q' or 'Q' are processed at more "
"prompt, input ignored\n");
if (buf1[0] != '/')
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) {
/* user hit enter */
suspend_grep = 1; /* for this recursion */
@ -844,7 +866,7 @@ int kdb_printf(const char *fmt, ...)
int r;
va_start(ap, fmt);
r = vkdb_printf(fmt, ap);
r = vkdb_printf(KDB_MSGSRC_INTERNAL, fmt, ap);
va_end(ap);
return r;

View File

@ -50,8 +50,7 @@
static int kdb_cmd_enabled = CONFIG_KDB_DEFAULT_ENABLE;
module_param_named(cmd_enable, kdb_cmd_enabled, int, 0600);
#define GREP_LEN 256
char kdb_grep_string[GREP_LEN];
char kdb_grep_string[KDB_GREP_STRLEN];
int kdb_grepping_flag;
EXPORT_SYMBOL(kdb_grepping_flag);
int kdb_grep_leading;
@ -870,7 +869,7 @@ static void parse_grep(const char *str)
len = strlen(cp);
if (!len)
return;
if (len >= GREP_LEN) {
if (len >= KDB_GREP_STRLEN) {
kdb_printf("search string too long\n");
return;
}
@ -915,13 +914,12 @@ int kdb_parse(const char *cmdstr)
char *cp;
char *cpp, quoted;
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.
*/
cp = (char *)cmdstr;
kdb_grepping_flag = check_grep = 0;
if (KDB_FLAG(CMD_INTERRUPT)) {
/* 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_machreg_fmt "\n",
instruction_pointer(regs));
kdb_dumpregs(regs);
break;
case KDB_REASON_SSTEP:
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_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 = '\0';
@ -2256,7 +2256,7 @@ static int kdb_cpu(int argc, const char **argv)
/*
* Validate cpunum
*/
if ((cpunum > NR_CPUS) || !kgdb_info[cpunum].enter_kgdb)
if ((cpunum >= CONFIG_NR_CPUS) || !kgdb_info[cpunum].enter_kgdb)
return KDB_BADCPUNUM;
dbg_switch_cpu = cpunum;
@ -2583,7 +2583,7 @@ static int kdb_summary(int argc, const char **argv)
#define K(x) ((x) << (PAGE_SHIFT - 10))
kdb_printf("\nMemTotal: %8lu kB\nMemFree: %8lu kB\n"
"Buffers: %8lu kB\n",
val.totalram, val.freeram, val.bufferram);
K(val.totalram), K(val.freeram), K(val.bufferram));
return 0;
}

View File

@ -196,7 +196,9 @@ extern int kdb_main_loop(kdb_reason_t, kdb_reason_t,
/* Miscellaneous functions and data areas */
extern int kdb_grepping_flag;
#define KDB_GREPPING_FLAG_SEARCH 0x8000
extern char kdb_grep_string[];
#define KDB_GREP_STRLEN 256
extern int kdb_grep_leading;
extern int kdb_grep_trailing;
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_send_sig_info(struct task_struct *p, struct siginfo *info);
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);
/* Defines for kdb_symbol_print */

View File

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