printk,kdb: capture printk() when in kdb shell
[linux-3.10.git] / kernel / debug / kdb / kdb_io.c
index 9e3cec7..c9b7f4f 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/smp.h>
 #include <linux/nmi.h>
 #include <linux/delay.h>
+#include <linux/kgdb.h>
 #include <linux/kdb.h>
 #include <linux/kallsyms.h>
 #include "kdb_private.h"
@@ -28,6 +29,7 @@
 #define CMD_BUFLEN 256
 char kdb_prompt_str[CMD_BUFLEN];
 
+int kdb_trap_printk;
 
 static void kgdb_transition_check(char *buffer)
 {
@@ -532,12 +534,12 @@ static int kdb_search_string(char *searched, char *searchfor)
        return 0;
 }
 
-int kdb_printf(const char *fmt, ...)
+int vkdb_printf(const char *fmt, va_list ap)
 {
-       va_list ap;
        int diag;
        int linecount;
        int logging, saved_loglevel = 0;
+       int saved_trap_printk;
        int got_printf_lock = 0;
        int retlen = 0;
        int fnd, len;
@@ -548,6 +550,9 @@ int kdb_printf(const char *fmt, ...)
        unsigned long uninitialized_var(flags);
 
        preempt_disable();
+       saved_trap_printk = kdb_trap_printk;
+       kdb_trap_printk = 0;
+
        /* Serialize kdb_printf if multiple cpus try to write at once.
         * But if any cpu goes recursive in kdb, just print the output,
         * even if it is interleaved with any other text.
@@ -574,9 +579,7 @@ int kdb_printf(const char *fmt, ...)
                next_avail = kdb_buffer;
                size_avail = sizeof(kdb_buffer);
        }
-       va_start(ap, fmt);
        vsnprintf(next_avail, size_avail, fmt, ap);
-       va_end(ap);
 
        /*
         * If kdb_parse() found that the command was cmd xxx | grep yyy
@@ -669,10 +672,22 @@ kdb_printit:
         * Write to all consoles.
         */
        retlen = strlen(kdb_buffer);
-       while (c) {
-               c->write(c, kdb_buffer, retlen);
-               touch_nmi_watchdog();
-               c = c->next;
+       if (!dbg_kdb_mode && kgdb_connected) {
+               gdbstub_msg_write(kdb_buffer, retlen);
+       } else {
+               if (!dbg_io_ops->is_console) {
+                       len = strlen(kdb_buffer);
+                       cp = kdb_buffer;
+                       while (len--) {
+                               dbg_io_ops->write_char(*cp);
+                               cp++;
+                       }
+               }
+               while (c) {
+                       c->write(c, kdb_buffer, retlen);
+                       touch_nmi_watchdog();
+                       c = c->next;
+               }
        }
        if (logging) {
                saved_loglevel = console_loglevel;
@@ -714,6 +729,14 @@ kdb_printit:
                kdb_input_flush();
                c = console_drivers;
 
+               if (!dbg_io_ops->is_console) {
+                       len = strlen(moreprompt);
+                       cp = moreprompt;
+                       while (len--) {
+                               dbg_io_ops->write_char(*cp);
+                               cp++;
+                       }
+               }
                while (c) {
                        c->write(c, moreprompt, strlen(moreprompt));
                        touch_nmi_watchdog();
@@ -784,6 +807,20 @@ kdb_print_out:
        } else {
                __release(kdb_printf_lock);
        }
+       kdb_trap_printk = saved_trap_printk;
        preempt_enable();
        return retlen;
 }
+
+int kdb_printf(const char *fmt, ...)
+{
+       va_list ap;
+       int r;
+
+       va_start(ap, fmt);
+       r = vkdb_printf(fmt, ap);
+       va_end(ap);
+
+       return r;
+}
+