Merge tag 'for_linux-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jwess...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 Feb 2015 23:13:29 +0000 (15:13 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 Feb 2015 23:13:29 +0000 (15:13 -0800)
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

Documentation/DocBook/kgdb.tmpl
include/linux/kdb.h
kernel/debug/debug_core.c
kernel/debug/kdb/kdb_io.c
kernel/debug/kdb/kdb_main.c
kernel/debug/kdb/kdb_private.h
kernel/printk/printk.c

index 2428cc04dbc84b5f7243558296f6f36fa9621fb4..f3abca7ec53d62e4bd416da9f53395aef9269855 100644 (file)
    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
    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>
    </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.
     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">
    </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>
index 75ae2e2631fceaa27915f3d100b1f03244b17500..a19bcf9e762e1d4886e8bd5ed202e4485ba8cf3e 100644 (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 *, ...);
 
index 07ce18ca71e0cd46b70155269a77b04af23f6526..0874e2edd2756bcbe5542a496fb6b131b092b3ea 100644 (file)
@@ -604,7 +604,7 @@ return_normal:
                   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();
index 7c70812caea5b3223fe1a9b7d9252980f90a02fe..fc1ef736253c79954686d018a2deca4c86300fa6 100644 (file)
@@ -439,7 +439,7 @@ poll_again:
  *     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 @@ kdb_printit:
         * 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 @@ kdb_printit:
        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 @@ kdb_printit:
                        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;
index 7b40c5f07dce8d09e1ebaba547e401b5655befbb..4121345498e0e48f10b414a4b12e0b5f15daeabd 100644 (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;
 }
 
index eaacd1693954b13aa55c59028c597b6ed91488f3..75014d7f45681b1a75643fd06dbc119e8ea16cb7 100644 (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 */
index c06df7de0963a3c82889c274dd2d707507d31d50..01cfd69c54c6772ad49a1d81120258f765f435a1 100644 (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