xref: /openbmc/linux/kernel/debug/gdbstub.c (revision 53197fc49549240f6c6a963b2713a4cd9517964b)
1*53197fc4SJason Wessel /*
2*53197fc4SJason Wessel  * Kernel Debug Core
3*53197fc4SJason Wessel  *
4*53197fc4SJason Wessel  * Maintainer: Jason Wessel <jason.wessel@windriver.com>
5*53197fc4SJason Wessel  *
6*53197fc4SJason Wessel  * Copyright (C) 2000-2001 VERITAS Software Corporation.
7*53197fc4SJason Wessel  * Copyright (C) 2002-2004 Timesys Corporation
8*53197fc4SJason Wessel  * Copyright (C) 2003-2004 Amit S. Kale <amitkale@linsyssoft.com>
9*53197fc4SJason Wessel  * Copyright (C) 2004 Pavel Machek <pavel@suse.cz>
10*53197fc4SJason Wessel  * Copyright (C) 2004-2006 Tom Rini <trini@kernel.crashing.org>
11*53197fc4SJason Wessel  * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd.
12*53197fc4SJason Wessel  * Copyright (C) 2005-2009 Wind River Systems, Inc.
13*53197fc4SJason Wessel  * Copyright (C) 2007 MontaVista Software, Inc.
14*53197fc4SJason Wessel  * Copyright (C) 2008 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
15*53197fc4SJason Wessel  *
16*53197fc4SJason Wessel  * Contributors at various stages not listed above:
17*53197fc4SJason Wessel  *  Jason Wessel ( jason.wessel@windriver.com )
18*53197fc4SJason Wessel  *  George Anzinger <george@mvista.com>
19*53197fc4SJason Wessel  *  Anurekh Saxena (anurekh.saxena@timesys.com)
20*53197fc4SJason Wessel  *  Lake Stevens Instrument Division (Glenn Engel)
21*53197fc4SJason Wessel  *  Jim Kingdon, Cygnus Support.
22*53197fc4SJason Wessel  *
23*53197fc4SJason Wessel  * Original KGDB stub: David Grothe <dave@gcom.com>,
24*53197fc4SJason Wessel  * Tigran Aivazian <tigran@sco.com>
25*53197fc4SJason Wessel  *
26*53197fc4SJason Wessel  * This file is licensed under the terms of the GNU General Public License
27*53197fc4SJason Wessel  * version 2. This program is licensed "as is" without any warranty of any
28*53197fc4SJason Wessel  * kind, whether express or implied.
29*53197fc4SJason Wessel  */
30*53197fc4SJason Wessel 
31*53197fc4SJason Wessel #include <linux/kernel.h>
32*53197fc4SJason Wessel #include <linux/kgdb.h>
33*53197fc4SJason Wessel #include <linux/reboot.h>
34*53197fc4SJason Wessel #include <linux/uaccess.h>
35*53197fc4SJason Wessel #include <asm/cacheflush.h>
36*53197fc4SJason Wessel #include <asm/unaligned.h>
37*53197fc4SJason Wessel #include "debug_core.h"
38*53197fc4SJason Wessel 
39*53197fc4SJason Wessel #define KGDB_MAX_THREAD_QUERY 17
40*53197fc4SJason Wessel 
41*53197fc4SJason Wessel /* Our I/O buffers. */
42*53197fc4SJason Wessel static char			remcom_in_buffer[BUFMAX];
43*53197fc4SJason Wessel static char			remcom_out_buffer[BUFMAX];
44*53197fc4SJason Wessel 
45*53197fc4SJason Wessel /* Storage for the registers, in GDB format. */
46*53197fc4SJason Wessel static unsigned long		gdb_regs[(NUMREGBYTES +
47*53197fc4SJason Wessel 					sizeof(unsigned long) - 1) /
48*53197fc4SJason Wessel 					sizeof(unsigned long)];
49*53197fc4SJason Wessel 
50*53197fc4SJason Wessel /*
51*53197fc4SJason Wessel  * GDB remote protocol parser:
52*53197fc4SJason Wessel  */
53*53197fc4SJason Wessel 
54*53197fc4SJason Wessel static int hex(char ch)
55*53197fc4SJason Wessel {
56*53197fc4SJason Wessel 	if ((ch >= 'a') && (ch <= 'f'))
57*53197fc4SJason Wessel 		return ch - 'a' + 10;
58*53197fc4SJason Wessel 	if ((ch >= '0') && (ch <= '9'))
59*53197fc4SJason Wessel 		return ch - '0';
60*53197fc4SJason Wessel 	if ((ch >= 'A') && (ch <= 'F'))
61*53197fc4SJason Wessel 		return ch - 'A' + 10;
62*53197fc4SJason Wessel 	return -1;
63*53197fc4SJason Wessel }
64*53197fc4SJason Wessel 
65*53197fc4SJason Wessel /* scan for the sequence $<data>#<checksum> */
66*53197fc4SJason Wessel static void get_packet(char *buffer)
67*53197fc4SJason Wessel {
68*53197fc4SJason Wessel 	unsigned char checksum;
69*53197fc4SJason Wessel 	unsigned char xmitcsum;
70*53197fc4SJason Wessel 	int count;
71*53197fc4SJason Wessel 	char ch;
72*53197fc4SJason Wessel 
73*53197fc4SJason Wessel 	do {
74*53197fc4SJason Wessel 		/*
75*53197fc4SJason Wessel 		 * Spin and wait around for the start character, ignore all
76*53197fc4SJason Wessel 		 * other characters:
77*53197fc4SJason Wessel 		 */
78*53197fc4SJason Wessel 		while ((ch = (dbg_io_ops->read_char())) != '$')
79*53197fc4SJason Wessel 			/* nothing */;
80*53197fc4SJason Wessel 
81*53197fc4SJason Wessel 		kgdb_connected = 1;
82*53197fc4SJason Wessel 		checksum = 0;
83*53197fc4SJason Wessel 		xmitcsum = -1;
84*53197fc4SJason Wessel 
85*53197fc4SJason Wessel 		count = 0;
86*53197fc4SJason Wessel 
87*53197fc4SJason Wessel 		/*
88*53197fc4SJason Wessel 		 * now, read until a # or end of buffer is found:
89*53197fc4SJason Wessel 		 */
90*53197fc4SJason Wessel 		while (count < (BUFMAX - 1)) {
91*53197fc4SJason Wessel 			ch = dbg_io_ops->read_char();
92*53197fc4SJason Wessel 			if (ch == '#')
93*53197fc4SJason Wessel 				break;
94*53197fc4SJason Wessel 			checksum = checksum + ch;
95*53197fc4SJason Wessel 			buffer[count] = ch;
96*53197fc4SJason Wessel 			count = count + 1;
97*53197fc4SJason Wessel 		}
98*53197fc4SJason Wessel 		buffer[count] = 0;
99*53197fc4SJason Wessel 
100*53197fc4SJason Wessel 		if (ch == '#') {
101*53197fc4SJason Wessel 			xmitcsum = hex(dbg_io_ops->read_char()) << 4;
102*53197fc4SJason Wessel 			xmitcsum += hex(dbg_io_ops->read_char());
103*53197fc4SJason Wessel 
104*53197fc4SJason Wessel 			if (checksum != xmitcsum)
105*53197fc4SJason Wessel 				/* failed checksum */
106*53197fc4SJason Wessel 				dbg_io_ops->write_char('-');
107*53197fc4SJason Wessel 			else
108*53197fc4SJason Wessel 				/* successful transfer */
109*53197fc4SJason Wessel 				dbg_io_ops->write_char('+');
110*53197fc4SJason Wessel 			if (dbg_io_ops->flush)
111*53197fc4SJason Wessel 				dbg_io_ops->flush();
112*53197fc4SJason Wessel 		}
113*53197fc4SJason Wessel 	} while (checksum != xmitcsum);
114*53197fc4SJason Wessel }
115*53197fc4SJason Wessel 
116*53197fc4SJason Wessel /*
117*53197fc4SJason Wessel  * Send the packet in buffer.
118*53197fc4SJason Wessel  * Check for gdb connection if asked for.
119*53197fc4SJason Wessel  */
120*53197fc4SJason Wessel static void put_packet(char *buffer)
121*53197fc4SJason Wessel {
122*53197fc4SJason Wessel 	unsigned char checksum;
123*53197fc4SJason Wessel 	int count;
124*53197fc4SJason Wessel 	char ch;
125*53197fc4SJason Wessel 
126*53197fc4SJason Wessel 	/*
127*53197fc4SJason Wessel 	 * $<packet info>#<checksum>.
128*53197fc4SJason Wessel 	 */
129*53197fc4SJason Wessel 	while (1) {
130*53197fc4SJason Wessel 		dbg_io_ops->write_char('$');
131*53197fc4SJason Wessel 		checksum = 0;
132*53197fc4SJason Wessel 		count = 0;
133*53197fc4SJason Wessel 
134*53197fc4SJason Wessel 		while ((ch = buffer[count])) {
135*53197fc4SJason Wessel 			dbg_io_ops->write_char(ch);
136*53197fc4SJason Wessel 			checksum += ch;
137*53197fc4SJason Wessel 			count++;
138*53197fc4SJason Wessel 		}
139*53197fc4SJason Wessel 
140*53197fc4SJason Wessel 		dbg_io_ops->write_char('#');
141*53197fc4SJason Wessel 		dbg_io_ops->write_char(hex_asc_hi(checksum));
142*53197fc4SJason Wessel 		dbg_io_ops->write_char(hex_asc_lo(checksum));
143*53197fc4SJason Wessel 		if (dbg_io_ops->flush)
144*53197fc4SJason Wessel 			dbg_io_ops->flush();
145*53197fc4SJason Wessel 
146*53197fc4SJason Wessel 		/* Now see what we get in reply. */
147*53197fc4SJason Wessel 		ch = dbg_io_ops->read_char();
148*53197fc4SJason Wessel 
149*53197fc4SJason Wessel 		if (ch == 3)
150*53197fc4SJason Wessel 			ch = dbg_io_ops->read_char();
151*53197fc4SJason Wessel 
152*53197fc4SJason Wessel 		/* If we get an ACK, we are done. */
153*53197fc4SJason Wessel 		if (ch == '+')
154*53197fc4SJason Wessel 			return;
155*53197fc4SJason Wessel 
156*53197fc4SJason Wessel 		/*
157*53197fc4SJason Wessel 		 * If we get the start of another packet, this means
158*53197fc4SJason Wessel 		 * that GDB is attempting to reconnect.  We will NAK
159*53197fc4SJason Wessel 		 * the packet being sent, and stop trying to send this
160*53197fc4SJason Wessel 		 * packet.
161*53197fc4SJason Wessel 		 */
162*53197fc4SJason Wessel 		if (ch == '$') {
163*53197fc4SJason Wessel 			dbg_io_ops->write_char('-');
164*53197fc4SJason Wessel 			if (dbg_io_ops->flush)
165*53197fc4SJason Wessel 				dbg_io_ops->flush();
166*53197fc4SJason Wessel 			return;
167*53197fc4SJason Wessel 		}
168*53197fc4SJason Wessel 	}
169*53197fc4SJason Wessel }
170*53197fc4SJason Wessel 
171*53197fc4SJason Wessel static char gdbmsgbuf[BUFMAX + 1];
172*53197fc4SJason Wessel 
173*53197fc4SJason Wessel void gdbstub_msg_write(const char *s, int len)
174*53197fc4SJason Wessel {
175*53197fc4SJason Wessel 	char *bufptr;
176*53197fc4SJason Wessel 	int wcount;
177*53197fc4SJason Wessel 	int i;
178*53197fc4SJason Wessel 
179*53197fc4SJason Wessel 	/* 'O'utput */
180*53197fc4SJason Wessel 	gdbmsgbuf[0] = 'O';
181*53197fc4SJason Wessel 
182*53197fc4SJason Wessel 	/* Fill and send buffers... */
183*53197fc4SJason Wessel 	while (len > 0) {
184*53197fc4SJason Wessel 		bufptr = gdbmsgbuf + 1;
185*53197fc4SJason Wessel 
186*53197fc4SJason Wessel 		/* Calculate how many this time */
187*53197fc4SJason Wessel 		if ((len << 1) > (BUFMAX - 2))
188*53197fc4SJason Wessel 			wcount = (BUFMAX - 2) >> 1;
189*53197fc4SJason Wessel 		else
190*53197fc4SJason Wessel 			wcount = len;
191*53197fc4SJason Wessel 
192*53197fc4SJason Wessel 		/* Pack in hex chars */
193*53197fc4SJason Wessel 		for (i = 0; i < wcount; i++)
194*53197fc4SJason Wessel 			bufptr = pack_hex_byte(bufptr, s[i]);
195*53197fc4SJason Wessel 		*bufptr = '\0';
196*53197fc4SJason Wessel 
197*53197fc4SJason Wessel 		/* Move up */
198*53197fc4SJason Wessel 		s += wcount;
199*53197fc4SJason Wessel 		len -= wcount;
200*53197fc4SJason Wessel 
201*53197fc4SJason Wessel 		/* Write packet */
202*53197fc4SJason Wessel 		put_packet(gdbmsgbuf);
203*53197fc4SJason Wessel 	}
204*53197fc4SJason Wessel }
205*53197fc4SJason Wessel 
206*53197fc4SJason Wessel /*
207*53197fc4SJason Wessel  * Convert the memory pointed to by mem into hex, placing result in
208*53197fc4SJason Wessel  * buf.  Return a pointer to the last char put in buf (null). May
209*53197fc4SJason Wessel  * return an error.
210*53197fc4SJason Wessel  */
211*53197fc4SJason Wessel int kgdb_mem2hex(char *mem, char *buf, int count)
212*53197fc4SJason Wessel {
213*53197fc4SJason Wessel 	char *tmp;
214*53197fc4SJason Wessel 	int err;
215*53197fc4SJason Wessel 
216*53197fc4SJason Wessel 	/*
217*53197fc4SJason Wessel 	 * We use the upper half of buf as an intermediate buffer for the
218*53197fc4SJason Wessel 	 * raw memory copy.  Hex conversion will work against this one.
219*53197fc4SJason Wessel 	 */
220*53197fc4SJason Wessel 	tmp = buf + count;
221*53197fc4SJason Wessel 
222*53197fc4SJason Wessel 	err = probe_kernel_read(tmp, mem, count);
223*53197fc4SJason Wessel 	if (!err) {
224*53197fc4SJason Wessel 		while (count > 0) {
225*53197fc4SJason Wessel 			buf = pack_hex_byte(buf, *tmp);
226*53197fc4SJason Wessel 			tmp++;
227*53197fc4SJason Wessel 			count--;
228*53197fc4SJason Wessel 		}
229*53197fc4SJason Wessel 
230*53197fc4SJason Wessel 		*buf = 0;
231*53197fc4SJason Wessel 	}
232*53197fc4SJason Wessel 
233*53197fc4SJason Wessel 	return err;
234*53197fc4SJason Wessel }
235*53197fc4SJason Wessel 
236*53197fc4SJason Wessel /*
237*53197fc4SJason Wessel  * Convert the hex array pointed to by buf into binary to be placed in
238*53197fc4SJason Wessel  * mem.  Return a pointer to the character AFTER the last byte
239*53197fc4SJason Wessel  * written.  May return an error.
240*53197fc4SJason Wessel  */
241*53197fc4SJason Wessel int kgdb_hex2mem(char *buf, char *mem, int count)
242*53197fc4SJason Wessel {
243*53197fc4SJason Wessel 	char *tmp_raw;
244*53197fc4SJason Wessel 	char *tmp_hex;
245*53197fc4SJason Wessel 
246*53197fc4SJason Wessel 	/*
247*53197fc4SJason Wessel 	 * We use the upper half of buf as an intermediate buffer for the
248*53197fc4SJason Wessel 	 * raw memory that is converted from hex.
249*53197fc4SJason Wessel 	 */
250*53197fc4SJason Wessel 	tmp_raw = buf + count * 2;
251*53197fc4SJason Wessel 
252*53197fc4SJason Wessel 	tmp_hex = tmp_raw - 1;
253*53197fc4SJason Wessel 	while (tmp_hex >= buf) {
254*53197fc4SJason Wessel 		tmp_raw--;
255*53197fc4SJason Wessel 		*tmp_raw = hex(*tmp_hex--);
256*53197fc4SJason Wessel 		*tmp_raw |= hex(*tmp_hex--) << 4;
257*53197fc4SJason Wessel 	}
258*53197fc4SJason Wessel 
259*53197fc4SJason Wessel 	return probe_kernel_write(mem, tmp_raw, count);
260*53197fc4SJason Wessel }
261*53197fc4SJason Wessel 
262*53197fc4SJason Wessel /*
263*53197fc4SJason Wessel  * While we find nice hex chars, build a long_val.
264*53197fc4SJason Wessel  * Return number of chars processed.
265*53197fc4SJason Wessel  */
266*53197fc4SJason Wessel int kgdb_hex2long(char **ptr, unsigned long *long_val)
267*53197fc4SJason Wessel {
268*53197fc4SJason Wessel 	int hex_val;
269*53197fc4SJason Wessel 	int num = 0;
270*53197fc4SJason Wessel 	int negate = 0;
271*53197fc4SJason Wessel 
272*53197fc4SJason Wessel 	*long_val = 0;
273*53197fc4SJason Wessel 
274*53197fc4SJason Wessel 	if (**ptr == '-') {
275*53197fc4SJason Wessel 		negate = 1;
276*53197fc4SJason Wessel 		(*ptr)++;
277*53197fc4SJason Wessel 	}
278*53197fc4SJason Wessel 	while (**ptr) {
279*53197fc4SJason Wessel 		hex_val = hex(**ptr);
280*53197fc4SJason Wessel 		if (hex_val < 0)
281*53197fc4SJason Wessel 			break;
282*53197fc4SJason Wessel 
283*53197fc4SJason Wessel 		*long_val = (*long_val << 4) | hex_val;
284*53197fc4SJason Wessel 		num++;
285*53197fc4SJason Wessel 		(*ptr)++;
286*53197fc4SJason Wessel 	}
287*53197fc4SJason Wessel 
288*53197fc4SJason Wessel 	if (negate)
289*53197fc4SJason Wessel 		*long_val = -*long_val;
290*53197fc4SJason Wessel 
291*53197fc4SJason Wessel 	return num;
292*53197fc4SJason Wessel }
293*53197fc4SJason Wessel 
294*53197fc4SJason Wessel /*
295*53197fc4SJason Wessel  * Copy the binary array pointed to by buf into mem.  Fix $, #, and
296*53197fc4SJason Wessel  * 0x7d escaped with 0x7d. Return -EFAULT on failure or 0 on success.
297*53197fc4SJason Wessel  * The input buf is overwitten with the result to write to mem.
298*53197fc4SJason Wessel  */
299*53197fc4SJason Wessel static int kgdb_ebin2mem(char *buf, char *mem, int count)
300*53197fc4SJason Wessel {
301*53197fc4SJason Wessel 	int size = 0;
302*53197fc4SJason Wessel 	char *c = buf;
303*53197fc4SJason Wessel 
304*53197fc4SJason Wessel 	while (count-- > 0) {
305*53197fc4SJason Wessel 		c[size] = *buf++;
306*53197fc4SJason Wessel 		if (c[size] == 0x7d)
307*53197fc4SJason Wessel 			c[size] = *buf++ ^ 0x20;
308*53197fc4SJason Wessel 		size++;
309*53197fc4SJason Wessel 	}
310*53197fc4SJason Wessel 
311*53197fc4SJason Wessel 	return probe_kernel_write(mem, c, size);
312*53197fc4SJason Wessel }
313*53197fc4SJason Wessel 
314*53197fc4SJason Wessel /* Write memory due to an 'M' or 'X' packet. */
315*53197fc4SJason Wessel static int write_mem_msg(int binary)
316*53197fc4SJason Wessel {
317*53197fc4SJason Wessel 	char *ptr = &remcom_in_buffer[1];
318*53197fc4SJason Wessel 	unsigned long addr;
319*53197fc4SJason Wessel 	unsigned long length;
320*53197fc4SJason Wessel 	int err;
321*53197fc4SJason Wessel 
322*53197fc4SJason Wessel 	if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
323*53197fc4SJason Wessel 	    kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
324*53197fc4SJason Wessel 		if (binary)
325*53197fc4SJason Wessel 			err = kgdb_ebin2mem(ptr, (char *)addr, length);
326*53197fc4SJason Wessel 		else
327*53197fc4SJason Wessel 			err = kgdb_hex2mem(ptr, (char *)addr, length);
328*53197fc4SJason Wessel 		if (err)
329*53197fc4SJason Wessel 			return err;
330*53197fc4SJason Wessel 		if (CACHE_FLUSH_IS_SAFE)
331*53197fc4SJason Wessel 			flush_icache_range(addr, addr + length);
332*53197fc4SJason Wessel 		return 0;
333*53197fc4SJason Wessel 	}
334*53197fc4SJason Wessel 
335*53197fc4SJason Wessel 	return -EINVAL;
336*53197fc4SJason Wessel }
337*53197fc4SJason Wessel 
338*53197fc4SJason Wessel static void error_packet(char *pkt, int error)
339*53197fc4SJason Wessel {
340*53197fc4SJason Wessel 	error = -error;
341*53197fc4SJason Wessel 	pkt[0] = 'E';
342*53197fc4SJason Wessel 	pkt[1] = hex_asc[(error / 10)];
343*53197fc4SJason Wessel 	pkt[2] = hex_asc[(error % 10)];
344*53197fc4SJason Wessel 	pkt[3] = '\0';
345*53197fc4SJason Wessel }
346*53197fc4SJason Wessel 
347*53197fc4SJason Wessel /*
348*53197fc4SJason Wessel  * Thread ID accessors. We represent a flat TID space to GDB, where
349*53197fc4SJason Wessel  * the per CPU idle threads (which under Linux all have PID 0) are
350*53197fc4SJason Wessel  * remapped to negative TIDs.
351*53197fc4SJason Wessel  */
352*53197fc4SJason Wessel 
353*53197fc4SJason Wessel #define BUF_THREAD_ID_SIZE	16
354*53197fc4SJason Wessel 
355*53197fc4SJason Wessel static char *pack_threadid(char *pkt, unsigned char *id)
356*53197fc4SJason Wessel {
357*53197fc4SJason Wessel 	char *limit;
358*53197fc4SJason Wessel 
359*53197fc4SJason Wessel 	limit = pkt + BUF_THREAD_ID_SIZE;
360*53197fc4SJason Wessel 	while (pkt < limit)
361*53197fc4SJason Wessel 		pkt = pack_hex_byte(pkt, *id++);
362*53197fc4SJason Wessel 
363*53197fc4SJason Wessel 	return pkt;
364*53197fc4SJason Wessel }
365*53197fc4SJason Wessel 
366*53197fc4SJason Wessel static void int_to_threadref(unsigned char *id, int value)
367*53197fc4SJason Wessel {
368*53197fc4SJason Wessel 	unsigned char *scan;
369*53197fc4SJason Wessel 	int i = 4;
370*53197fc4SJason Wessel 
371*53197fc4SJason Wessel 	scan = (unsigned char *)id;
372*53197fc4SJason Wessel 	while (i--)
373*53197fc4SJason Wessel 		*scan++ = 0;
374*53197fc4SJason Wessel 	put_unaligned_be32(value, scan);
375*53197fc4SJason Wessel }
376*53197fc4SJason Wessel 
377*53197fc4SJason Wessel static struct task_struct *getthread(struct pt_regs *regs, int tid)
378*53197fc4SJason Wessel {
379*53197fc4SJason Wessel 	/*
380*53197fc4SJason Wessel 	 * Non-positive TIDs are remapped to the cpu shadow information
381*53197fc4SJason Wessel 	 */
382*53197fc4SJason Wessel 	if (tid == 0 || tid == -1)
383*53197fc4SJason Wessel 		tid = -atomic_read(&kgdb_active) - 2;
384*53197fc4SJason Wessel 	if (tid < -1 && tid > -NR_CPUS - 2) {
385*53197fc4SJason Wessel 		if (kgdb_info[-tid - 2].task)
386*53197fc4SJason Wessel 			return kgdb_info[-tid - 2].task;
387*53197fc4SJason Wessel 		else
388*53197fc4SJason Wessel 			return idle_task(-tid - 2);
389*53197fc4SJason Wessel 	}
390*53197fc4SJason Wessel 	if (tid <= 0) {
391*53197fc4SJason Wessel 		printk(KERN_ERR "KGDB: Internal thread select error\n");
392*53197fc4SJason Wessel 		dump_stack();
393*53197fc4SJason Wessel 		return NULL;
394*53197fc4SJason Wessel 	}
395*53197fc4SJason Wessel 
396*53197fc4SJason Wessel 	/*
397*53197fc4SJason Wessel 	 * find_task_by_pid_ns() does not take the tasklist lock anymore
398*53197fc4SJason Wessel 	 * but is nicely RCU locked - hence is a pretty resilient
399*53197fc4SJason Wessel 	 * thing to use:
400*53197fc4SJason Wessel 	 */
401*53197fc4SJason Wessel 	return find_task_by_pid_ns(tid, &init_pid_ns);
402*53197fc4SJason Wessel }
403*53197fc4SJason Wessel 
404*53197fc4SJason Wessel 
405*53197fc4SJason Wessel /*
406*53197fc4SJason Wessel  * Remap normal tasks to their real PID,
407*53197fc4SJason Wessel  * CPU shadow threads are mapped to -CPU - 2
408*53197fc4SJason Wessel  */
409*53197fc4SJason Wessel static inline int shadow_pid(int realpid)
410*53197fc4SJason Wessel {
411*53197fc4SJason Wessel 	if (realpid)
412*53197fc4SJason Wessel 		return realpid;
413*53197fc4SJason Wessel 
414*53197fc4SJason Wessel 	return -raw_smp_processor_id() - 2;
415*53197fc4SJason Wessel }
416*53197fc4SJason Wessel 
417*53197fc4SJason Wessel /*
418*53197fc4SJason Wessel  * All the functions that start with gdb_cmd are the various
419*53197fc4SJason Wessel  * operations to implement the handlers for the gdbserial protocol
420*53197fc4SJason Wessel  * where KGDB is communicating with an external debugger
421*53197fc4SJason Wessel  */
422*53197fc4SJason Wessel 
423*53197fc4SJason Wessel /* Handle the '?' status packets */
424*53197fc4SJason Wessel static void gdb_cmd_status(struct kgdb_state *ks)
425*53197fc4SJason Wessel {
426*53197fc4SJason Wessel 	/*
427*53197fc4SJason Wessel 	 * We know that this packet is only sent
428*53197fc4SJason Wessel 	 * during initial connect.  So to be safe,
429*53197fc4SJason Wessel 	 * we clear out our breakpoints now in case
430*53197fc4SJason Wessel 	 * GDB is reconnecting.
431*53197fc4SJason Wessel 	 */
432*53197fc4SJason Wessel 	dbg_remove_all_break();
433*53197fc4SJason Wessel 
434*53197fc4SJason Wessel 	remcom_out_buffer[0] = 'S';
435*53197fc4SJason Wessel 	pack_hex_byte(&remcom_out_buffer[1], ks->signo);
436*53197fc4SJason Wessel }
437*53197fc4SJason Wessel 
438*53197fc4SJason Wessel /* Handle the 'g' get registers request */
439*53197fc4SJason Wessel static void gdb_cmd_getregs(struct kgdb_state *ks)
440*53197fc4SJason Wessel {
441*53197fc4SJason Wessel 	struct task_struct *thread;
442*53197fc4SJason Wessel 	void *local_debuggerinfo;
443*53197fc4SJason Wessel 	int i;
444*53197fc4SJason Wessel 
445*53197fc4SJason Wessel 	thread = kgdb_usethread;
446*53197fc4SJason Wessel 	if (!thread) {
447*53197fc4SJason Wessel 		thread = kgdb_info[ks->cpu].task;
448*53197fc4SJason Wessel 		local_debuggerinfo = kgdb_info[ks->cpu].debuggerinfo;
449*53197fc4SJason Wessel 	} else {
450*53197fc4SJason Wessel 		local_debuggerinfo = NULL;
451*53197fc4SJason Wessel 		for_each_online_cpu(i) {
452*53197fc4SJason Wessel 			/*
453*53197fc4SJason Wessel 			 * Try to find the task on some other
454*53197fc4SJason Wessel 			 * or possibly this node if we do not
455*53197fc4SJason Wessel 			 * find the matching task then we try
456*53197fc4SJason Wessel 			 * to approximate the results.
457*53197fc4SJason Wessel 			 */
458*53197fc4SJason Wessel 			if (thread == kgdb_info[i].task)
459*53197fc4SJason Wessel 				local_debuggerinfo = kgdb_info[i].debuggerinfo;
460*53197fc4SJason Wessel 		}
461*53197fc4SJason Wessel 	}
462*53197fc4SJason Wessel 
463*53197fc4SJason Wessel 	/*
464*53197fc4SJason Wessel 	 * All threads that don't have debuggerinfo should be
465*53197fc4SJason Wessel 	 * in schedule() sleeping, since all other CPUs
466*53197fc4SJason Wessel 	 * are in kgdb_wait, and thus have debuggerinfo.
467*53197fc4SJason Wessel 	 */
468*53197fc4SJason Wessel 	if (local_debuggerinfo) {
469*53197fc4SJason Wessel 		pt_regs_to_gdb_regs(gdb_regs, local_debuggerinfo);
470*53197fc4SJason Wessel 	} else {
471*53197fc4SJason Wessel 		/*
472*53197fc4SJason Wessel 		 * Pull stuff saved during switch_to; nothing
473*53197fc4SJason Wessel 		 * else is accessible (or even particularly
474*53197fc4SJason Wessel 		 * relevant).
475*53197fc4SJason Wessel 		 *
476*53197fc4SJason Wessel 		 * This should be enough for a stack trace.
477*53197fc4SJason Wessel 		 */
478*53197fc4SJason Wessel 		sleeping_thread_to_gdb_regs(gdb_regs, thread);
479*53197fc4SJason Wessel 	}
480*53197fc4SJason Wessel 	kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer, NUMREGBYTES);
481*53197fc4SJason Wessel }
482*53197fc4SJason Wessel 
483*53197fc4SJason Wessel /* Handle the 'G' set registers request */
484*53197fc4SJason Wessel static void gdb_cmd_setregs(struct kgdb_state *ks)
485*53197fc4SJason Wessel {
486*53197fc4SJason Wessel 	kgdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs, NUMREGBYTES);
487*53197fc4SJason Wessel 
488*53197fc4SJason Wessel 	if (kgdb_usethread && kgdb_usethread != current) {
489*53197fc4SJason Wessel 		error_packet(remcom_out_buffer, -EINVAL);
490*53197fc4SJason Wessel 	} else {
491*53197fc4SJason Wessel 		gdb_regs_to_pt_regs(gdb_regs, ks->linux_regs);
492*53197fc4SJason Wessel 		strcpy(remcom_out_buffer, "OK");
493*53197fc4SJason Wessel 	}
494*53197fc4SJason Wessel }
495*53197fc4SJason Wessel 
496*53197fc4SJason Wessel /* Handle the 'm' memory read bytes */
497*53197fc4SJason Wessel static void gdb_cmd_memread(struct kgdb_state *ks)
498*53197fc4SJason Wessel {
499*53197fc4SJason Wessel 	char *ptr = &remcom_in_buffer[1];
500*53197fc4SJason Wessel 	unsigned long length;
501*53197fc4SJason Wessel 	unsigned long addr;
502*53197fc4SJason Wessel 	int err;
503*53197fc4SJason Wessel 
504*53197fc4SJason Wessel 	if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&
505*53197fc4SJason Wessel 					kgdb_hex2long(&ptr, &length) > 0) {
506*53197fc4SJason Wessel 		err = kgdb_mem2hex((char *)addr, remcom_out_buffer, length);
507*53197fc4SJason Wessel 		if (err)
508*53197fc4SJason Wessel 			error_packet(remcom_out_buffer, err);
509*53197fc4SJason Wessel 	} else {
510*53197fc4SJason Wessel 		error_packet(remcom_out_buffer, -EINVAL);
511*53197fc4SJason Wessel 	}
512*53197fc4SJason Wessel }
513*53197fc4SJason Wessel 
514*53197fc4SJason Wessel /* Handle the 'M' memory write bytes */
515*53197fc4SJason Wessel static void gdb_cmd_memwrite(struct kgdb_state *ks)
516*53197fc4SJason Wessel {
517*53197fc4SJason Wessel 	int err = write_mem_msg(0);
518*53197fc4SJason Wessel 
519*53197fc4SJason Wessel 	if (err)
520*53197fc4SJason Wessel 		error_packet(remcom_out_buffer, err);
521*53197fc4SJason Wessel 	else
522*53197fc4SJason Wessel 		strcpy(remcom_out_buffer, "OK");
523*53197fc4SJason Wessel }
524*53197fc4SJason Wessel 
525*53197fc4SJason Wessel /* Handle the 'X' memory binary write bytes */
526*53197fc4SJason Wessel static void gdb_cmd_binwrite(struct kgdb_state *ks)
527*53197fc4SJason Wessel {
528*53197fc4SJason Wessel 	int err = write_mem_msg(1);
529*53197fc4SJason Wessel 
530*53197fc4SJason Wessel 	if (err)
531*53197fc4SJason Wessel 		error_packet(remcom_out_buffer, err);
532*53197fc4SJason Wessel 	else
533*53197fc4SJason Wessel 		strcpy(remcom_out_buffer, "OK");
534*53197fc4SJason Wessel }
535*53197fc4SJason Wessel 
536*53197fc4SJason Wessel /* Handle the 'D' or 'k', detach or kill packets */
537*53197fc4SJason Wessel static void gdb_cmd_detachkill(struct kgdb_state *ks)
538*53197fc4SJason Wessel {
539*53197fc4SJason Wessel 	int error;
540*53197fc4SJason Wessel 
541*53197fc4SJason Wessel 	/* The detach case */
542*53197fc4SJason Wessel 	if (remcom_in_buffer[0] == 'D') {
543*53197fc4SJason Wessel 		error = dbg_remove_all_break();
544*53197fc4SJason Wessel 		if (error < 0) {
545*53197fc4SJason Wessel 			error_packet(remcom_out_buffer, error);
546*53197fc4SJason Wessel 		} else {
547*53197fc4SJason Wessel 			strcpy(remcom_out_buffer, "OK");
548*53197fc4SJason Wessel 			kgdb_connected = 0;
549*53197fc4SJason Wessel 		}
550*53197fc4SJason Wessel 		put_packet(remcom_out_buffer);
551*53197fc4SJason Wessel 	} else {
552*53197fc4SJason Wessel 		/*
553*53197fc4SJason Wessel 		 * Assume the kill case, with no exit code checking,
554*53197fc4SJason Wessel 		 * trying to force detach the debugger:
555*53197fc4SJason Wessel 		 */
556*53197fc4SJason Wessel 		dbg_remove_all_break();
557*53197fc4SJason Wessel 		kgdb_connected = 0;
558*53197fc4SJason Wessel 	}
559*53197fc4SJason Wessel }
560*53197fc4SJason Wessel 
561*53197fc4SJason Wessel /* Handle the 'R' reboot packets */
562*53197fc4SJason Wessel static int gdb_cmd_reboot(struct kgdb_state *ks)
563*53197fc4SJason Wessel {
564*53197fc4SJason Wessel 	/* For now, only honor R0 */
565*53197fc4SJason Wessel 	if (strcmp(remcom_in_buffer, "R0") == 0) {
566*53197fc4SJason Wessel 		printk(KERN_CRIT "Executing emergency reboot\n");
567*53197fc4SJason Wessel 		strcpy(remcom_out_buffer, "OK");
568*53197fc4SJason Wessel 		put_packet(remcom_out_buffer);
569*53197fc4SJason Wessel 
570*53197fc4SJason Wessel 		/*
571*53197fc4SJason Wessel 		 * Execution should not return from
572*53197fc4SJason Wessel 		 * machine_emergency_restart()
573*53197fc4SJason Wessel 		 */
574*53197fc4SJason Wessel 		machine_emergency_restart();
575*53197fc4SJason Wessel 		kgdb_connected = 0;
576*53197fc4SJason Wessel 
577*53197fc4SJason Wessel 		return 1;
578*53197fc4SJason Wessel 	}
579*53197fc4SJason Wessel 	return 0;
580*53197fc4SJason Wessel }
581*53197fc4SJason Wessel 
582*53197fc4SJason Wessel /* Handle the 'q' query packets */
583*53197fc4SJason Wessel static void gdb_cmd_query(struct kgdb_state *ks)
584*53197fc4SJason Wessel {
585*53197fc4SJason Wessel 	struct task_struct *g;
586*53197fc4SJason Wessel 	struct task_struct *p;
587*53197fc4SJason Wessel 	unsigned char thref[8];
588*53197fc4SJason Wessel 	char *ptr;
589*53197fc4SJason Wessel 	int i;
590*53197fc4SJason Wessel 	int cpu;
591*53197fc4SJason Wessel 	int finished = 0;
592*53197fc4SJason Wessel 
593*53197fc4SJason Wessel 	switch (remcom_in_buffer[1]) {
594*53197fc4SJason Wessel 	case 's':
595*53197fc4SJason Wessel 	case 'f':
596*53197fc4SJason Wessel 		if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10)) {
597*53197fc4SJason Wessel 			error_packet(remcom_out_buffer, -EINVAL);
598*53197fc4SJason Wessel 			break;
599*53197fc4SJason Wessel 		}
600*53197fc4SJason Wessel 
601*53197fc4SJason Wessel 		i = 0;
602*53197fc4SJason Wessel 		remcom_out_buffer[0] = 'm';
603*53197fc4SJason Wessel 		ptr = remcom_out_buffer + 1;
604*53197fc4SJason Wessel 		if (remcom_in_buffer[1] == 'f') {
605*53197fc4SJason Wessel 			/* Each cpu is a shadow thread */
606*53197fc4SJason Wessel 			for_each_online_cpu(cpu) {
607*53197fc4SJason Wessel 				ks->thr_query = 0;
608*53197fc4SJason Wessel 				int_to_threadref(thref, -cpu - 2);
609*53197fc4SJason Wessel 				pack_threadid(ptr, thref);
610*53197fc4SJason Wessel 				ptr += BUF_THREAD_ID_SIZE;
611*53197fc4SJason Wessel 				*(ptr++) = ',';
612*53197fc4SJason Wessel 				i++;
613*53197fc4SJason Wessel 			}
614*53197fc4SJason Wessel 		}
615*53197fc4SJason Wessel 
616*53197fc4SJason Wessel 		do_each_thread(g, p) {
617*53197fc4SJason Wessel 			if (i >= ks->thr_query && !finished) {
618*53197fc4SJason Wessel 				int_to_threadref(thref, p->pid);
619*53197fc4SJason Wessel 				pack_threadid(ptr, thref);
620*53197fc4SJason Wessel 				ptr += BUF_THREAD_ID_SIZE;
621*53197fc4SJason Wessel 				*(ptr++) = ',';
622*53197fc4SJason Wessel 				ks->thr_query++;
623*53197fc4SJason Wessel 				if (ks->thr_query % KGDB_MAX_THREAD_QUERY == 0)
624*53197fc4SJason Wessel 					finished = 1;
625*53197fc4SJason Wessel 			}
626*53197fc4SJason Wessel 			i++;
627*53197fc4SJason Wessel 		} while_each_thread(g, p);
628*53197fc4SJason Wessel 
629*53197fc4SJason Wessel 		*(--ptr) = '\0';
630*53197fc4SJason Wessel 		break;
631*53197fc4SJason Wessel 
632*53197fc4SJason Wessel 	case 'C':
633*53197fc4SJason Wessel 		/* Current thread id */
634*53197fc4SJason Wessel 		strcpy(remcom_out_buffer, "QC");
635*53197fc4SJason Wessel 		ks->threadid = shadow_pid(current->pid);
636*53197fc4SJason Wessel 		int_to_threadref(thref, ks->threadid);
637*53197fc4SJason Wessel 		pack_threadid(remcom_out_buffer + 2, thref);
638*53197fc4SJason Wessel 		break;
639*53197fc4SJason Wessel 	case 'T':
640*53197fc4SJason Wessel 		if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16)) {
641*53197fc4SJason Wessel 			error_packet(remcom_out_buffer, -EINVAL);
642*53197fc4SJason Wessel 			break;
643*53197fc4SJason Wessel 		}
644*53197fc4SJason Wessel 		ks->threadid = 0;
645*53197fc4SJason Wessel 		ptr = remcom_in_buffer + 17;
646*53197fc4SJason Wessel 		kgdb_hex2long(&ptr, &ks->threadid);
647*53197fc4SJason Wessel 		if (!getthread(ks->linux_regs, ks->threadid)) {
648*53197fc4SJason Wessel 			error_packet(remcom_out_buffer, -EINVAL);
649*53197fc4SJason Wessel 			break;
650*53197fc4SJason Wessel 		}
651*53197fc4SJason Wessel 		if ((int)ks->threadid > 0) {
652*53197fc4SJason Wessel 			kgdb_mem2hex(getthread(ks->linux_regs,
653*53197fc4SJason Wessel 					ks->threadid)->comm,
654*53197fc4SJason Wessel 					remcom_out_buffer, 16);
655*53197fc4SJason Wessel 		} else {
656*53197fc4SJason Wessel 			static char tmpstr[23 + BUF_THREAD_ID_SIZE];
657*53197fc4SJason Wessel 
658*53197fc4SJason Wessel 			sprintf(tmpstr, "shadowCPU%d",
659*53197fc4SJason Wessel 					(int)(-ks->threadid - 2));
660*53197fc4SJason Wessel 			kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr));
661*53197fc4SJason Wessel 		}
662*53197fc4SJason Wessel 		break;
663*53197fc4SJason Wessel 	}
664*53197fc4SJason Wessel }
665*53197fc4SJason Wessel 
666*53197fc4SJason Wessel /* Handle the 'H' task query packets */
667*53197fc4SJason Wessel static void gdb_cmd_task(struct kgdb_state *ks)
668*53197fc4SJason Wessel {
669*53197fc4SJason Wessel 	struct task_struct *thread;
670*53197fc4SJason Wessel 	char *ptr;
671*53197fc4SJason Wessel 
672*53197fc4SJason Wessel 	switch (remcom_in_buffer[1]) {
673*53197fc4SJason Wessel 	case 'g':
674*53197fc4SJason Wessel 		ptr = &remcom_in_buffer[2];
675*53197fc4SJason Wessel 		kgdb_hex2long(&ptr, &ks->threadid);
676*53197fc4SJason Wessel 		thread = getthread(ks->linux_regs, ks->threadid);
677*53197fc4SJason Wessel 		if (!thread && ks->threadid > 0) {
678*53197fc4SJason Wessel 			error_packet(remcom_out_buffer, -EINVAL);
679*53197fc4SJason Wessel 			break;
680*53197fc4SJason Wessel 		}
681*53197fc4SJason Wessel 		kgdb_usethread = thread;
682*53197fc4SJason Wessel 		ks->kgdb_usethreadid = ks->threadid;
683*53197fc4SJason Wessel 		strcpy(remcom_out_buffer, "OK");
684*53197fc4SJason Wessel 		break;
685*53197fc4SJason Wessel 	case 'c':
686*53197fc4SJason Wessel 		ptr = &remcom_in_buffer[2];
687*53197fc4SJason Wessel 		kgdb_hex2long(&ptr, &ks->threadid);
688*53197fc4SJason Wessel 		if (!ks->threadid) {
689*53197fc4SJason Wessel 			kgdb_contthread = NULL;
690*53197fc4SJason Wessel 		} else {
691*53197fc4SJason Wessel 			thread = getthread(ks->linux_regs, ks->threadid);
692*53197fc4SJason Wessel 			if (!thread && ks->threadid > 0) {
693*53197fc4SJason Wessel 				error_packet(remcom_out_buffer, -EINVAL);
694*53197fc4SJason Wessel 				break;
695*53197fc4SJason Wessel 			}
696*53197fc4SJason Wessel 			kgdb_contthread = thread;
697*53197fc4SJason Wessel 		}
698*53197fc4SJason Wessel 		strcpy(remcom_out_buffer, "OK");
699*53197fc4SJason Wessel 		break;
700*53197fc4SJason Wessel 	}
701*53197fc4SJason Wessel }
702*53197fc4SJason Wessel 
703*53197fc4SJason Wessel /* Handle the 'T' thread query packets */
704*53197fc4SJason Wessel static void gdb_cmd_thread(struct kgdb_state *ks)
705*53197fc4SJason Wessel {
706*53197fc4SJason Wessel 	char *ptr = &remcom_in_buffer[1];
707*53197fc4SJason Wessel 	struct task_struct *thread;
708*53197fc4SJason Wessel 
709*53197fc4SJason Wessel 	kgdb_hex2long(&ptr, &ks->threadid);
710*53197fc4SJason Wessel 	thread = getthread(ks->linux_regs, ks->threadid);
711*53197fc4SJason Wessel 	if (thread)
712*53197fc4SJason Wessel 		strcpy(remcom_out_buffer, "OK");
713*53197fc4SJason Wessel 	else
714*53197fc4SJason Wessel 		error_packet(remcom_out_buffer, -EINVAL);
715*53197fc4SJason Wessel }
716*53197fc4SJason Wessel 
717*53197fc4SJason Wessel /* Handle the 'z' or 'Z' breakpoint remove or set packets */
718*53197fc4SJason Wessel static void gdb_cmd_break(struct kgdb_state *ks)
719*53197fc4SJason Wessel {
720*53197fc4SJason Wessel 	/*
721*53197fc4SJason Wessel 	 * Since GDB-5.3, it's been drafted that '0' is a software
722*53197fc4SJason Wessel 	 * breakpoint, '1' is a hardware breakpoint, so let's do that.
723*53197fc4SJason Wessel 	 */
724*53197fc4SJason Wessel 	char *bpt_type = &remcom_in_buffer[1];
725*53197fc4SJason Wessel 	char *ptr = &remcom_in_buffer[2];
726*53197fc4SJason Wessel 	unsigned long addr;
727*53197fc4SJason Wessel 	unsigned long length;
728*53197fc4SJason Wessel 	int error = 0;
729*53197fc4SJason Wessel 
730*53197fc4SJason Wessel 	if (arch_kgdb_ops.set_hw_breakpoint && *bpt_type >= '1') {
731*53197fc4SJason Wessel 		/* Unsupported */
732*53197fc4SJason Wessel 		if (*bpt_type > '4')
733*53197fc4SJason Wessel 			return;
734*53197fc4SJason Wessel 	} else {
735*53197fc4SJason Wessel 		if (*bpt_type != '0' && *bpt_type != '1')
736*53197fc4SJason Wessel 			/* Unsupported. */
737*53197fc4SJason Wessel 			return;
738*53197fc4SJason Wessel 	}
739*53197fc4SJason Wessel 
740*53197fc4SJason Wessel 	/*
741*53197fc4SJason Wessel 	 * Test if this is a hardware breakpoint, and
742*53197fc4SJason Wessel 	 * if we support it:
743*53197fc4SJason Wessel 	 */
744*53197fc4SJason Wessel 	if (*bpt_type == '1' && !(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT))
745*53197fc4SJason Wessel 		/* Unsupported. */
746*53197fc4SJason Wessel 		return;
747*53197fc4SJason Wessel 
748*53197fc4SJason Wessel 	if (*(ptr++) != ',') {
749*53197fc4SJason Wessel 		error_packet(remcom_out_buffer, -EINVAL);
750*53197fc4SJason Wessel 		return;
751*53197fc4SJason Wessel 	}
752*53197fc4SJason Wessel 	if (!kgdb_hex2long(&ptr, &addr)) {
753*53197fc4SJason Wessel 		error_packet(remcom_out_buffer, -EINVAL);
754*53197fc4SJason Wessel 		return;
755*53197fc4SJason Wessel 	}
756*53197fc4SJason Wessel 	if (*(ptr++) != ',' ||
757*53197fc4SJason Wessel 		!kgdb_hex2long(&ptr, &length)) {
758*53197fc4SJason Wessel 		error_packet(remcom_out_buffer, -EINVAL);
759*53197fc4SJason Wessel 		return;
760*53197fc4SJason Wessel 	}
761*53197fc4SJason Wessel 
762*53197fc4SJason Wessel 	if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0')
763*53197fc4SJason Wessel 		error = dbg_set_sw_break(addr);
764*53197fc4SJason Wessel 	else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0')
765*53197fc4SJason Wessel 		error = dbg_remove_sw_break(addr);
766*53197fc4SJason Wessel 	else if (remcom_in_buffer[0] == 'Z')
767*53197fc4SJason Wessel 		error = arch_kgdb_ops.set_hw_breakpoint(addr,
768*53197fc4SJason Wessel 			(int)length, *bpt_type - '0');
769*53197fc4SJason Wessel 	else if (remcom_in_buffer[0] == 'z')
770*53197fc4SJason Wessel 		error = arch_kgdb_ops.remove_hw_breakpoint(addr,
771*53197fc4SJason Wessel 			(int) length, *bpt_type - '0');
772*53197fc4SJason Wessel 
773*53197fc4SJason Wessel 	if (error == 0)
774*53197fc4SJason Wessel 		strcpy(remcom_out_buffer, "OK");
775*53197fc4SJason Wessel 	else
776*53197fc4SJason Wessel 		error_packet(remcom_out_buffer, error);
777*53197fc4SJason Wessel }
778*53197fc4SJason Wessel 
779*53197fc4SJason Wessel /* Handle the 'C' signal / exception passing packets */
780*53197fc4SJason Wessel static int gdb_cmd_exception_pass(struct kgdb_state *ks)
781*53197fc4SJason Wessel {
782*53197fc4SJason Wessel 	/* C09 == pass exception
783*53197fc4SJason Wessel 	 * C15 == detach kgdb, pass exception
784*53197fc4SJason Wessel 	 */
785*53197fc4SJason Wessel 	if (remcom_in_buffer[1] == '0' && remcom_in_buffer[2] == '9') {
786*53197fc4SJason Wessel 
787*53197fc4SJason Wessel 		ks->pass_exception = 1;
788*53197fc4SJason Wessel 		remcom_in_buffer[0] = 'c';
789*53197fc4SJason Wessel 
790*53197fc4SJason Wessel 	} else if (remcom_in_buffer[1] == '1' && remcom_in_buffer[2] == '5') {
791*53197fc4SJason Wessel 
792*53197fc4SJason Wessel 		ks->pass_exception = 1;
793*53197fc4SJason Wessel 		remcom_in_buffer[0] = 'D';
794*53197fc4SJason Wessel 		dbg_remove_all_break();
795*53197fc4SJason Wessel 		kgdb_connected = 0;
796*53197fc4SJason Wessel 		return 1;
797*53197fc4SJason Wessel 
798*53197fc4SJason Wessel 	} else {
799*53197fc4SJason Wessel 		gdbstub_msg_write("KGDB only knows signal 9 (pass)"
800*53197fc4SJason Wessel 			" and 15 (pass and disconnect)\n"
801*53197fc4SJason Wessel 			"Executing a continue without signal passing\n", 0);
802*53197fc4SJason Wessel 		remcom_in_buffer[0] = 'c';
803*53197fc4SJason Wessel 	}
804*53197fc4SJason Wessel 
805*53197fc4SJason Wessel 	/* Indicate fall through */
806*53197fc4SJason Wessel 	return -1;
807*53197fc4SJason Wessel }
808*53197fc4SJason Wessel 
809*53197fc4SJason Wessel /*
810*53197fc4SJason Wessel  * This function performs all gdbserial command procesing
811*53197fc4SJason Wessel  */
812*53197fc4SJason Wessel int gdb_serial_stub(struct kgdb_state *ks)
813*53197fc4SJason Wessel {
814*53197fc4SJason Wessel 	int error = 0;
815*53197fc4SJason Wessel 	int tmp;
816*53197fc4SJason Wessel 
817*53197fc4SJason Wessel 	/* Clear the out buffer. */
818*53197fc4SJason Wessel 	memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
819*53197fc4SJason Wessel 
820*53197fc4SJason Wessel 	if (kgdb_connected) {
821*53197fc4SJason Wessel 		unsigned char thref[8];
822*53197fc4SJason Wessel 		char *ptr;
823*53197fc4SJason Wessel 
824*53197fc4SJason Wessel 		/* Reply to host that an exception has occurred */
825*53197fc4SJason Wessel 		ptr = remcom_out_buffer;
826*53197fc4SJason Wessel 		*ptr++ = 'T';
827*53197fc4SJason Wessel 		ptr = pack_hex_byte(ptr, ks->signo);
828*53197fc4SJason Wessel 		ptr += strlen(strcpy(ptr, "thread:"));
829*53197fc4SJason Wessel 		int_to_threadref(thref, shadow_pid(current->pid));
830*53197fc4SJason Wessel 		ptr = pack_threadid(ptr, thref);
831*53197fc4SJason Wessel 		*ptr++ = ';';
832*53197fc4SJason Wessel 		put_packet(remcom_out_buffer);
833*53197fc4SJason Wessel 	}
834*53197fc4SJason Wessel 
835*53197fc4SJason Wessel 	kgdb_usethread = kgdb_info[ks->cpu].task;
836*53197fc4SJason Wessel 	ks->kgdb_usethreadid = shadow_pid(kgdb_info[ks->cpu].task->pid);
837*53197fc4SJason Wessel 	ks->pass_exception = 0;
838*53197fc4SJason Wessel 
839*53197fc4SJason Wessel 	while (1) {
840*53197fc4SJason Wessel 		error = 0;
841*53197fc4SJason Wessel 
842*53197fc4SJason Wessel 		/* Clear the out buffer. */
843*53197fc4SJason Wessel 		memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
844*53197fc4SJason Wessel 
845*53197fc4SJason Wessel 		get_packet(remcom_in_buffer);
846*53197fc4SJason Wessel 
847*53197fc4SJason Wessel 		switch (remcom_in_buffer[0]) {
848*53197fc4SJason Wessel 		case '?': /* gdbserial status */
849*53197fc4SJason Wessel 			gdb_cmd_status(ks);
850*53197fc4SJason Wessel 			break;
851*53197fc4SJason Wessel 		case 'g': /* return the value of the CPU registers */
852*53197fc4SJason Wessel 			gdb_cmd_getregs(ks);
853*53197fc4SJason Wessel 			break;
854*53197fc4SJason Wessel 		case 'G': /* set the value of the CPU registers - return OK */
855*53197fc4SJason Wessel 			gdb_cmd_setregs(ks);
856*53197fc4SJason Wessel 			break;
857*53197fc4SJason Wessel 		case 'm': /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
858*53197fc4SJason Wessel 			gdb_cmd_memread(ks);
859*53197fc4SJason Wessel 			break;
860*53197fc4SJason Wessel 		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */
861*53197fc4SJason Wessel 			gdb_cmd_memwrite(ks);
862*53197fc4SJason Wessel 			break;
863*53197fc4SJason Wessel 		case 'X': /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */
864*53197fc4SJason Wessel 			gdb_cmd_binwrite(ks);
865*53197fc4SJason Wessel 			break;
866*53197fc4SJason Wessel 			/* kill or detach. KGDB should treat this like a
867*53197fc4SJason Wessel 			 * continue.
868*53197fc4SJason Wessel 			 */
869*53197fc4SJason Wessel 		case 'D': /* Debugger detach */
870*53197fc4SJason Wessel 		case 'k': /* Debugger detach via kill */
871*53197fc4SJason Wessel 			gdb_cmd_detachkill(ks);
872*53197fc4SJason Wessel 			goto default_handle;
873*53197fc4SJason Wessel 		case 'R': /* Reboot */
874*53197fc4SJason Wessel 			if (gdb_cmd_reboot(ks))
875*53197fc4SJason Wessel 				goto default_handle;
876*53197fc4SJason Wessel 			break;
877*53197fc4SJason Wessel 		case 'q': /* query command */
878*53197fc4SJason Wessel 			gdb_cmd_query(ks);
879*53197fc4SJason Wessel 			break;
880*53197fc4SJason Wessel 		case 'H': /* task related */
881*53197fc4SJason Wessel 			gdb_cmd_task(ks);
882*53197fc4SJason Wessel 			break;
883*53197fc4SJason Wessel 		case 'T': /* Query thread status */
884*53197fc4SJason Wessel 			gdb_cmd_thread(ks);
885*53197fc4SJason Wessel 			break;
886*53197fc4SJason Wessel 		case 'z': /* Break point remove */
887*53197fc4SJason Wessel 		case 'Z': /* Break point set */
888*53197fc4SJason Wessel 			gdb_cmd_break(ks);
889*53197fc4SJason Wessel 			break;
890*53197fc4SJason Wessel 		case 'C': /* Exception passing */
891*53197fc4SJason Wessel 			tmp = gdb_cmd_exception_pass(ks);
892*53197fc4SJason Wessel 			if (tmp > 0)
893*53197fc4SJason Wessel 				goto default_handle;
894*53197fc4SJason Wessel 			if (tmp == 0)
895*53197fc4SJason Wessel 				break;
896*53197fc4SJason Wessel 			/* Fall through on tmp < 0 */
897*53197fc4SJason Wessel 		case 'c': /* Continue packet */
898*53197fc4SJason Wessel 		case 's': /* Single step packet */
899*53197fc4SJason Wessel 			if (kgdb_contthread && kgdb_contthread != current) {
900*53197fc4SJason Wessel 				/* Can't switch threads in kgdb */
901*53197fc4SJason Wessel 				error_packet(remcom_out_buffer, -EINVAL);
902*53197fc4SJason Wessel 				break;
903*53197fc4SJason Wessel 			}
904*53197fc4SJason Wessel 			dbg_activate_sw_breakpoints();
905*53197fc4SJason Wessel 			/* Fall through to default processing */
906*53197fc4SJason Wessel 		default:
907*53197fc4SJason Wessel default_handle:
908*53197fc4SJason Wessel 			error = kgdb_arch_handle_exception(ks->ex_vector,
909*53197fc4SJason Wessel 						ks->signo,
910*53197fc4SJason Wessel 						ks->err_code,
911*53197fc4SJason Wessel 						remcom_in_buffer,
912*53197fc4SJason Wessel 						remcom_out_buffer,
913*53197fc4SJason Wessel 						ks->linux_regs);
914*53197fc4SJason Wessel 			/*
915*53197fc4SJason Wessel 			 * Leave cmd processing on error, detach,
916*53197fc4SJason Wessel 			 * kill, continue, or single step.
917*53197fc4SJason Wessel 			 */
918*53197fc4SJason Wessel 			if (error >= 0 || remcom_in_buffer[0] == 'D' ||
919*53197fc4SJason Wessel 			    remcom_in_buffer[0] == 'k') {
920*53197fc4SJason Wessel 				error = 0;
921*53197fc4SJason Wessel 				goto kgdb_exit;
922*53197fc4SJason Wessel 			}
923*53197fc4SJason Wessel 
924*53197fc4SJason Wessel 		}
925*53197fc4SJason Wessel 
926*53197fc4SJason Wessel 		/* reply to the request */
927*53197fc4SJason Wessel 		put_packet(remcom_out_buffer);
928*53197fc4SJason Wessel 	}
929*53197fc4SJason Wessel 
930*53197fc4SJason Wessel kgdb_exit:
931*53197fc4SJason Wessel 	if (ks->pass_exception)
932*53197fc4SJason Wessel 		error = 1;
933*53197fc4SJason Wessel 	return error;
934*53197fc4SJason Wessel }
935