Skip to content

Commit f679c49

Browse files
committed
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>
1 parent 3bdb65e commit f679c49

4 files changed

Lines changed: 29 additions & 21 deletions

File tree

kernel/debug/gdbstub.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
/* Our I/O buffers. */
4343
static char remcom_in_buffer[BUFMAX];
4444
static char remcom_out_buffer[BUFMAX];
45+
static int gdbstub_use_prev_in_buf;
46+
static int gdbstub_prev_in_buf_pos;
4547

4648
/* Storage for the registers, in GDB format. */
4749
static unsigned long gdb_regs[(NUMREGBYTES +
@@ -58,6 +60,13 @@ static int gdbstub_read_wait(void)
5860
int ret = -1;
5961
int i;
6062

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+
6170
/* poll any additional I/O interfaces that are defined */
6271
while (ret < 0)
6372
for (i = 0; kdb_poll_funcs[i] != NULL; i++) {
@@ -109,7 +118,6 @@ static void get_packet(char *buffer)
109118
buffer[count] = ch;
110119
count = count + 1;
111120
}
112-
buffer[count] = 0;
113121

114122
if (ch == '#') {
115123
xmitcsum = hex_to_bin(gdbstub_read_wait()) << 4;
@@ -124,6 +132,7 @@ static void get_packet(char *buffer)
124132
if (dbg_io_ops->flush)
125133
dbg_io_ops->flush();
126134
}
135+
buffer[count] = 0;
127136
} while (checksum != xmitcsum);
128137
}
129138

@@ -1082,12 +1091,11 @@ int gdbstub_state(struct kgdb_state *ks, char *cmd)
10821091
case 'c':
10831092
strcpy(remcom_in_buffer, cmd);
10841093
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;
10911099
}
10921100
dbg_io_ops->write_char('+');
10931101
put_packet(remcom_out_buffer);

kernel/debug/kdb/kdb_debugger.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ EXPORT_SYMBOL_GPL(kdb_poll_funcs);
3030
int kdb_poll_idx = 1;
3131
EXPORT_SYMBOL_GPL(kdb_poll_idx);
3232

33+
static struct kgdb_state *kdb_ks;
34+
3335
int kdb_stub(struct kgdb_state *ks)
3436
{
3537
int error = 0;
@@ -39,6 +41,7 @@ int kdb_stub(struct kgdb_state *ks)
3941
kdb_dbtrap_t db_result = KDB_DB_NOBPT;
4042
int i;
4143

44+
kdb_ks = ks;
4245
if (KDB_STATE(REENTRY)) {
4346
reason = KDB_REASON_SWITCH;
4447
KDB_STATE_CLEAR(REENTRY);
@@ -124,16 +127,6 @@ int kdb_stub(struct kgdb_state *ks)
124127
kdbnearsym_cleanup();
125128
if (error == KDB_CMD_KGDB) {
126129
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, "");
137130
KDB_STATE_CLEAR(DOING_KGDB);
138131
KDB_STATE_CLEAR(DOING_KGDB2);
139132
}
@@ -166,3 +159,7 @@ int kdb_stub(struct kgdb_state *ks)
166159
return kgdb_info[ks->cpu].ret_state;
167160
}
168161

162+
void kdb_gdb_state_pass(char *buf)
163+
{
164+
gdbstub_state(kdb_ks, buf);
165+
}

kernel/debug/kdb/kdb_io.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ static void kgdb_transition_check(char *buffer)
3535
{
3636
int slen = strlen(buffer);
3737
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) {
4040
KDB_STATE_SET(KGDB_TRANS);
4141
kdb_printf("%s", buffer);
4242
}
@@ -390,12 +390,14 @@ static char *kdb_read(char *buffer, size_t bufsize)
390390
/* Special escape to kgdb */
391391
if (lastchar - buffer >= 5 &&
392392
strcmp(lastchar - 5, "$?#3f") == 0) {
393+
kdb_gdb_state_pass(lastchar - 5);
393394
strcpy(buffer, "kgdb");
394395
KDB_STATE_SET(DOING_KGDB);
395396
return buffer;
396397
}
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);
399401
strcpy(buffer, "kgdb");
400402
KDB_STATE_SET(DOING_KGDB2);
401403
return buffer;

kernel/debug/kdb/kdb_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ extern void kdb_print_nameval(const char *name, unsigned long val);
218218
extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
219219
extern void kdb_meminfo_proc_show(void);
220220
extern char *kdb_getstr(char *, size_t, char *);
221+
extern void kdb_gdb_state_pass(char *buf);
221222

222223
/* Defines for kdb_symbol_print */
223224
#define KDB_SP_SPACEB 0x0001 /* Space before string */

0 commit comments

Comments
 (0)