]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kdb,kgdb: Implement switch and pass buffer from kdb -> gdb
authorJason Wessel <jason.wessel@windriver.com>
Mon, 23 May 2011 18:17:41 +0000 (13:17 -0500)
committerJason Wessel <jason.wessel@windriver.com>
Fri, 29 Jul 2011 22:48:39 +0000 (17:48 -0500)
When switching from kdb mode to kgdb mode packets were getting lost
depending on the size of the fifo queue of the serial chip.  When gdb
initially connects if it is in kdb mode it should entirely send any
character buffer over to the gdbstub when switching connections.

Previously kdb was zero'ing out the character buffer and this could
lead to gdb failing to connect at all, or a lenthy pause could occur
on the initial connect.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
kernel/debug/gdbstub.c
kernel/debug/kdb/kdb_debugger.c
kernel/debug/kdb/kdb_io.c
kernel/debug/kdb/kdb_private.h

index a11db956dd62c4c5a5fa22699ccd3662a88f00bc..dd398d7aaa95617587b436c1c2b79121e6203e08 100644 (file)
@@ -53,11 +53,21 @@ static unsigned long                gdb_regs[(NUMREGBYTES +
  */
 
 #ifdef CONFIG_KGDB_KDB
+static int gdbstub_use_prev_in_buf;
+static int gdbstub_prev_in_buf_pos;
+
 static int gdbstub_read_wait(void)
 {
        int ret = -1;
        int i;
 
+       if (unlikely(gdbstub_use_prev_in_buf)) {
+               if (gdbstub_prev_in_buf_pos < gdbstub_use_prev_in_buf)
+                       return remcom_in_buffer[gdbstub_prev_in_buf_pos++];
+               else
+                       gdbstub_use_prev_in_buf = 0;
+       }
+
        /* poll any additional I/O interfaces that are defined */
        while (ret < 0)
                for (i = 0; kdb_poll_funcs[i] != NULL; i++) {
@@ -109,7 +119,6 @@ static void get_packet(char *buffer)
                        buffer[count] = ch;
                        count = count + 1;
                }
-               buffer[count] = 0;
 
                if (ch == '#') {
                        xmitcsum = hex_to_bin(gdbstub_read_wait()) << 4;
@@ -124,6 +133,8 @@ static void get_packet(char *buffer)
                        if (dbg_io_ops->flush)
                                dbg_io_ops->flush();
                }
+
+               buffer[count] = 0;
        } while (checksum != xmitcsum);
 }
 
@@ -1082,12 +1093,11 @@ int gdbstub_state(struct kgdb_state *ks, char *cmd)
        case 'c':
                strcpy(remcom_in_buffer, cmd);
                return 0;
-       case '?':
-               gdb_cmd_status(ks);
-               break;
-       case '\0':
-               strcpy(remcom_out_buffer, "");
-               break;
+       case '$':
+               strcpy(remcom_in_buffer, cmd);
+               gdbstub_use_prev_in_buf = strlen(remcom_in_buffer);
+               gdbstub_prev_in_buf_pos = 0;
+               return 0;
        }
        dbg_io_ops->write_char('+');
        put_packet(remcom_out_buffer);
index dd0b1b7dd02c9bb5d8d32b84c39f0a62a4db9c56..fe422d275782b6d6cfaca4cfca227832d352d357 100644 (file)
@@ -30,6 +30,8 @@ EXPORT_SYMBOL_GPL(kdb_poll_funcs);
 int kdb_poll_idx = 1;
 EXPORT_SYMBOL_GPL(kdb_poll_idx);
 
+static struct kgdb_state *kdb_ks;
+
 int kdb_stub(struct kgdb_state *ks)
 {
        int error = 0;
@@ -39,6 +41,7 @@ int kdb_stub(struct kgdb_state *ks)
        kdb_dbtrap_t db_result = KDB_DB_NOBPT;
        int i;
 
+       kdb_ks = ks;
        if (KDB_STATE(REENTRY)) {
                reason = KDB_REASON_SWITCH;
                KDB_STATE_CLEAR(REENTRY);
@@ -124,16 +127,6 @@ int kdb_stub(struct kgdb_state *ks)
        kdbnearsym_cleanup();
        if (error == KDB_CMD_KGDB) {
                if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) {
-       /*
-        * This inteface glue which allows kdb to transition in into
-        * the gdb stub.  In order to do this the '?' or '' gdb serial
-        * packet response is processed here.  And then control is
-        * passed to the gdbstub.
-        */
-                       if (KDB_STATE(DOING_KGDB))
-                               gdbstub_state(ks, "?");
-                       else
-                               gdbstub_state(ks, "");
                        KDB_STATE_CLEAR(DOING_KGDB);
                        KDB_STATE_CLEAR(DOING_KGDB2);
                }
@@ -166,3 +159,7 @@ int kdb_stub(struct kgdb_state *ks)
        return kgdb_info[ks->cpu].ret_state;
 }
 
+void kdb_gdb_state_pass(char *buf)
+{
+       gdbstub_state(kdb_ks, buf);
+}
index 96fdaac46a80b03c41e79b95a8c7e521ad437021..bd233264b29f8ebbf7cb3af6e9ebc9aa9dce3c92 100644 (file)
@@ -35,8 +35,8 @@ static void kgdb_transition_check(char *buffer)
 {
        int slen = strlen(buffer);
        if (strncmp(buffer, "$?#3f", slen) != 0 &&
-           strncmp(buffer, "$qSupported#37", slen) != 0 &&
-           strncmp(buffer, "+$qSupported#37", slen) != 0) {
+           strncmp(buffer, "$qSupported", slen) != 0 &&
+           strncmp(buffer, "+$qSupported", slen) != 0) {
                KDB_STATE_SET(KGDB_TRANS);
                kdb_printf("%s", buffer);
        }
@@ -390,12 +390,14 @@ poll_again:
                        /* Special escape to kgdb */
                        if (lastchar - buffer >= 5 &&
                            strcmp(lastchar - 5, "$?#3f") == 0) {
+                               kdb_gdb_state_pass(lastchar - 5);
                                strcpy(buffer, "kgdb");
                                KDB_STATE_SET(DOING_KGDB);
                                return buffer;
                        }
-                       if (lastchar - buffer >= 14 &&
-                           strcmp(lastchar - 14, "$qSupported#37") == 0) {
+                       if (lastchar - buffer >= 11 &&
+                           strcmp(lastchar - 11, "$qSupported") == 0) {
+                               kdb_gdb_state_pass(lastchar - 11);
                                strcpy(buffer, "kgdb");
                                KDB_STATE_SET(DOING_KGDB2);
                                return buffer;
index 35d69ed1dfb58e388dcd8717776631aa4473802d..03d332e63442803883fb77978311f6730f7b8db3 100644 (file)
@@ -218,6 +218,7 @@ 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 void kdb_gdb_state_pass(char *buf);
 
 /* Defines for kdb_symbol_print */
 #define KDB_SP_SPACEB  0x0001          /* Space before string */