Prechádzať zdrojové kódy

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
Linus Torvalds 10 rokov pred
rodič
commit
4fbd0a81a0

+ 3 - 3
Documentation/DocBook/kgdb.tmpl

@@ -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>

+ 7 - 1
include/linux/kdb.h

@@ -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 *, ...);
 
 

+ 18 - 1
kernel/debug/debug_core.c

@@ -604,7 +604,7 @@ return_normal:
 		   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();

+ 34 - 12
kernel/debug/kdb/kdb_io.c

@@ -439,7 +439,7 @@ poll_again:
  *	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 @@ kdb_printit:
 	 * 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;
-			cp = kdb_buffer;
+			len = retlen - (cp - kdb_buffer);
+			cp2 = cp;
 			while (len--) {
 			while (len--) {
-				dbg_io_ops->write_char(*cp);
-				cp++;
+				dbg_io_ops->write_char(*cp2);
+				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 @@ kdb_printit:
 	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 @@ kdb_printit:
 			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 "
-				   "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) {
 		} 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;

+ 8 - 8
kernel/debug/kdb/kdb_main.c

@@ -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[GREP_LEN];
+char kdb_grep_string[KDB_GREP_STRLEN];
 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;
 }
 }
 
 

+ 3 - 1
kernel/debug/kdb/kdb_private.h

@@ -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 */

+ 1 - 1
kernel/printk/printk.c

@@ -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