Skip to content

Commit

Permalink
Merge tag 'for_linux-3.20-rc1' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
torvalds committed Feb 20, 2015
2 parents 7bad222 + dd8f30c commit 4fbd0a8
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 27 deletions.
6 changes: 3 additions & 3 deletions Documentation/DocBook/kgdb.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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>
Expand Down Expand Up @@ -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.
Expand All @@ -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">
Expand Down Expand Up @@ -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>
Expand Down
8 changes: 7 additions & 1 deletion include/linux/kdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *, ...);

Expand Down
19 changes: 18 additions & 1 deletion kernel/debug/debug_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
46 changes: 34 additions & 12 deletions kernel/debug/kdb/kdb_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -691,27 +697,31 @@ 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;
}
}
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)) {
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 8 additions & 8 deletions kernel/debug/kdb/kdb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 3 additions & 1 deletion kernel/debug/kdb/kdb_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand All @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion kernel/printk/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 4fbd0a8

Please sign in to comment.