Commit f679c4985bb2e7de9d39a5d40b6031361c4ad861

Authored by Jason Wessel
1 parent 3bdb65ec95

kdb,kgdb: Implement switch and pass buffer from kdb -> gdb

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 lengthy pause could occur
on the initial connect.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>

Showing 4 changed files with 29 additions and 21 deletions Side-by-side Diff

kernel/debug/gdbstub.c
... ... @@ -42,6 +42,8 @@
42 42 /* Our I/O buffers. */
43 43 static char remcom_in_buffer[BUFMAX];
44 44 static char remcom_out_buffer[BUFMAX];
  45 +static int gdbstub_use_prev_in_buf;
  46 +static int gdbstub_prev_in_buf_pos;
45 47  
46 48 /* Storage for the registers, in GDB format. */
47 49 static unsigned long gdb_regs[(NUMREGBYTES +
... ... @@ -58,6 +60,13 @@
58 60 int ret = -1;
59 61 int i;
60 62  
  63 + if (unlikely(gdbstub_use_prev_in_buf)) {
  64 + if (gdbstub_prev_in_buf_pos < gdbstub_use_prev_in_buf)
  65 + return remcom_in_buffer[gdbstub_prev_in_buf_pos++];
  66 + else
  67 + gdbstub_use_prev_in_buf = 0;
  68 + }
  69 +
61 70 /* poll any additional I/O interfaces that are defined */
62 71 while (ret < 0)
63 72 for (i = 0; kdb_poll_funcs[i] != NULL; i++) {
... ... @@ -109,7 +118,6 @@
109 118 buffer[count] = ch;
110 119 count = count + 1;
111 120 }
112   - buffer[count] = 0;
113 121  
114 122 if (ch == '#') {
115 123 xmitcsum = hex_to_bin(gdbstub_read_wait()) << 4;
... ... @@ -124,6 +132,7 @@
124 132 if (dbg_io_ops->flush)
125 133 dbg_io_ops->flush();
126 134 }
  135 + buffer[count] = 0;
127 136 } while (checksum != xmitcsum);
128 137 }
129 138  
... ... @@ -1082,12 +1091,11 @@
1082 1091 case 'c':
1083 1092 strcpy(remcom_in_buffer, cmd);
1084 1093 return 0;
1085   - case '?':
1086   - gdb_cmd_status(ks);
1087   - break;
1088   - case '\0':
1089   - strcpy(remcom_out_buffer, "");
1090   - break;
  1094 + case '$':
  1095 + strcpy(remcom_in_buffer, cmd);
  1096 + gdbstub_use_prev_in_buf = strlen(remcom_in_buffer);
  1097 + gdbstub_prev_in_buf_pos = 0;
  1098 + return 0;
1091 1099 }
1092 1100 dbg_io_ops->write_char('+');
1093 1101 put_packet(remcom_out_buffer);
kernel/debug/kdb/kdb_debugger.c
... ... @@ -30,6 +30,8 @@
30 30 int kdb_poll_idx = 1;
31 31 EXPORT_SYMBOL_GPL(kdb_poll_idx);
32 32  
  33 +static struct kgdb_state *kdb_ks;
  34 +
33 35 int kdb_stub(struct kgdb_state *ks)
34 36 {
35 37 int error = 0;
... ... @@ -39,6 +41,7 @@
39 41 kdb_dbtrap_t db_result = KDB_DB_NOBPT;
40 42 int i;
41 43  
  44 + kdb_ks = ks;
42 45 if (KDB_STATE(REENTRY)) {
43 46 reason = KDB_REASON_SWITCH;
44 47 KDB_STATE_CLEAR(REENTRY);
... ... @@ -124,16 +127,6 @@
124 127 kdbnearsym_cleanup();
125 128 if (error == KDB_CMD_KGDB) {
126 129 if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) {
127   - /*
128   - * This inteface glue which allows kdb to transition in into
129   - * the gdb stub. In order to do this the '?' or '' gdb serial
130   - * packet response is processed here. And then control is
131   - * passed to the gdbstub.
132   - */
133   - if (KDB_STATE(DOING_KGDB))
134   - gdbstub_state(ks, "?");
135   - else
136   - gdbstub_state(ks, "");
137 130 KDB_STATE_CLEAR(DOING_KGDB);
138 131 KDB_STATE_CLEAR(DOING_KGDB2);
139 132 }
... ... @@ -164,5 +157,10 @@
164 157 return DBG_SWITCH_CPU_EVENT;
165 158 }
166 159 return kgdb_info[ks->cpu].ret_state;
  160 +}
  161 +
  162 +void kdb_gdb_state_pass(char *buf)
  163 +{
  164 + gdbstub_state(kdb_ks, buf);
167 165 }
kernel/debug/kdb/kdb_io.c
... ... @@ -35,8 +35,8 @@
35 35 {
36 36 int slen = strlen(buffer);
37 37 if (strncmp(buffer, "$?#3f", slen) != 0 &&
38   - strncmp(buffer, "$qSupported#37", slen) != 0 &&
39   - strncmp(buffer, "+$qSupported#37", slen) != 0) {
  38 + strncmp(buffer, "$qSupported", slen) != 0 &&
  39 + strncmp(buffer, "+$qSupported", slen) != 0) {
40 40 KDB_STATE_SET(KGDB_TRANS);
41 41 kdb_printf("%s", buffer);
42 42 }
43 43  
... ... @@ -390,12 +390,14 @@
390 390 /* Special escape to kgdb */
391 391 if (lastchar - buffer >= 5 &&
392 392 strcmp(lastchar - 5, "$?#3f") == 0) {
  393 + kdb_gdb_state_pass(lastchar - 5);
393 394 strcpy(buffer, "kgdb");
394 395 KDB_STATE_SET(DOING_KGDB);
395 396 return buffer;
396 397 }
397   - if (lastchar - buffer >= 14 &&
398   - strcmp(lastchar - 14, "$qSupported#37") == 0) {
  398 + if (lastchar - buffer >= 11 &&
  399 + strcmp(lastchar - 11, "$qSupported") == 0) {
  400 + kdb_gdb_state_pass(lastchar - 11);
399 401 strcpy(buffer, "kgdb");
400 402 KDB_STATE_SET(DOING_KGDB2);
401 403 return buffer;
kernel/debug/kdb/kdb_private.h
... ... @@ -218,6 +218,7 @@
218 218 extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
219 219 extern void kdb_meminfo_proc_show(void);
220 220 extern char *kdb_getstr(char *, size_t, char *);
  221 +extern void kdb_gdb_state_pass(char *buf);
221 222  
222 223 /* Defines for kdb_symbol_print */
223 224 #define KDB_SP_SPACEB 0x0001 /* Space before string */