xref: /csrg-svn/sys/hp300/hp300/kgdb_stub.c (revision 47211)
141475Smckusick /*
2*47211Skarels  * Copyright (c) 1990 Regents of the University of California.
341475Smckusick  * All rights reserved.
441475Smckusick  *
541475Smckusick  * %sccs.include.redist.c%
641475Smckusick  *
7*47211Skarels  *	@(#)kgdb_stub.c	7.5 (Berkeley) 03/11/91
841475Smckusick  */
941475Smckusick /*
10*47211Skarels  * "Stub" to allow remote cpu to debug over a serial line using gdb.
11*47211Skarels  */
1241475Smckusick #ifdef KGDB
13*47211Skarels #ifndef lint
14*47211Skarels static char rcsid[] = "$Header: kgdb_stub.c,v 1.6 91/03/05 01:15:03 van Exp $";
15*47211Skarels #endif
1641475Smckusick 
17*47211Skarels #include "param.h"
18*47211Skarels #include "systm.h"
19*47211Skarels #include "machine/trap.h"
20*47211Skarels #include "machine/cpu.h"
21*47211Skarels #include "machine/psl.h"
22*47211Skarels #include "machine/reg.h"
23*47211Skarels #include "frame.h"
24*47211Skarels #include "buf.h"
25*47211Skarels #include "../hp300/cons.h"
26*47211Skarels 
27*47211Skarels #include "kgdb_proto.h"
28*47211Skarels #include "machine/remote-sl.h"
29*47211Skarels 
3041475Smckusick extern void printf();
3141475Smckusick extern void bcopy();
3241475Smckusick extern int kernacc();
3341475Smckusick extern void chgkprot();
3441475Smckusick 
35*47211Skarels /* (XXX from trap.c) user-mode flag in type */
36*47211Skarels #define	USER	0x20
3741475Smckusick 
3842367Smckusick #ifndef KGDBDEV
3942367Smckusick #define KGDBDEV -1
4042367Smckusick #endif
4142367Smckusick #ifndef KGDBRATE
4242367Smckusick #define KGDBRATE 9600
4342367Smckusick #endif
4442367Smckusick 
4542367Smckusick int kgdb_dev = KGDBDEV;		/* remote debugging device (-1 if none) */
4642367Smckusick int kgdb_rate = KGDBRATE;	/* remote debugging baud rate */
47*47211Skarels int kgdb_active = 0;            /* remote debugging active if != 0 */
4841475Smckusick int kgdb_debug_init = 0;	/* != 0 waits for remote at system init */
49*47211Skarels int kgdb_debug = 0;
5041475Smckusick 
51*47211Skarels #define GETC	((*kgdb_getc)(kgdb_dev))
52*47211Skarels #define PUTC(c)	((*kgdb_putc)(kgdb_dev, c))
53*47211Skarels #define PUTESC(c) { \
54*47211Skarels 	if (c == FRAME_END) { \
55*47211Skarels 		PUTC(FRAME_ESCAPE); \
56*47211Skarels 		c = TRANS_FRAME_END; \
57*47211Skarels 	} else if (c == FRAME_ESCAPE) { \
58*47211Skarels 		PUTC(FRAME_ESCAPE); \
59*47211Skarels 		c = TRANS_FRAME_ESCAPE; \
60*47211Skarels 	} \
61*47211Skarels 	PUTC(c); \
6242367Smckusick }
6342367Smckusick 
64*47211Skarels static int (*kgdb_getc)();
65*47211Skarels static int (*kgdb_putc)();
6641475Smckusick 
6741475Smckusick /*
68*47211Skarels  * Send a message.  The host gets one chance to read it.
6941475Smckusick  */
70*47211Skarels static void
71*47211Skarels kgdb_send(type, bp, len)
72*47211Skarels 	register u_char type;
73*47211Skarels 	register u_char *bp;
74*47211Skarels 	register int len;
7541475Smckusick {
76*47211Skarels 	register u_char csum;
77*47211Skarels 	register u_char *ep = bp + len;
7841475Smckusick 
79*47211Skarels 	csum = type;
80*47211Skarels 	PUTESC(type)
8141475Smckusick 
82*47211Skarels 	while (bp < ep) {
83*47211Skarels 		type = *bp++;
84*47211Skarels 		csum += type;
85*47211Skarels 		PUTESC(type)
86*47211Skarels 	}
87*47211Skarels 	csum = -csum;
88*47211Skarels 	PUTESC(csum)
89*47211Skarels 	PUTC(FRAME_END);
9041475Smckusick }
9141475Smckusick 
92*47211Skarels static int
93*47211Skarels kgdb_recv(bp, lenp)
94*47211Skarels 	u_char *bp;
95*47211Skarels 	int *lenp;
9641475Smckusick {
97*47211Skarels 	register u_char c, csum;
98*47211Skarels 	register int escape, len;
99*47211Skarels 	register int type;
10041475Smckusick 
101*47211Skarels 	csum = len = escape = 0;
102*47211Skarels 	type = -1;
103*47211Skarels 	while (1) {
104*47211Skarels 		c = GETC;
105*47211Skarels 		switch (c) {
10641475Smckusick 
107*47211Skarels 		case FRAME_ESCAPE:
108*47211Skarels 			escape = 1;
109*47211Skarels 			continue;
11041475Smckusick 
111*47211Skarels 		case TRANS_FRAME_ESCAPE:
112*47211Skarels 			if (escape)
113*47211Skarels 				c = FRAME_ESCAPE;
114*47211Skarels 			break;
11541475Smckusick 
116*47211Skarels 		case TRANS_FRAME_END:
117*47211Skarels 			if (escape)
118*47211Skarels 				c = FRAME_END;
11941475Smckusick 			break;
12041475Smckusick 
121*47211Skarels 		case FRAME_END:
122*47211Skarels 			if (type < 0 || --len < 0) {
123*47211Skarels 				csum = len = escape = 0;
124*47211Skarels 				type = -1;
125*47211Skarels 				continue;
126*47211Skarels 			}
127*47211Skarels 			if (csum != 0) {
128*47211Skarels 				return (0);
129*47211Skarels 			}
130*47211Skarels 			*lenp = len;
131*47211Skarels 			return type;
13241475Smckusick 		}
133*47211Skarels 		csum += c;
134*47211Skarels 		if (type < 0) {
135*47211Skarels 			type = c;
136*47211Skarels 			escape = 0;
137*47211Skarels 			continue;
13841475Smckusick 		}
139*47211Skarels 		if (++len > SL_MAXMSG) {
140*47211Skarels 			while (GETC != FRAME_END)
141*47211Skarels 				;
142*47211Skarels 			return (0);
143*47211Skarels 		}
144*47211Skarels 		*bp++ = c;
145*47211Skarels 		escape = 0;
14641475Smckusick 	}
14741475Smckusick }
14841475Smckusick 
14941475Smckusick /*
15041475Smckusick  * Translate a trap number into a unix compatible signal value.
15141475Smckusick  * (gdb only understands unix signal numbers).
15241475Smckusick  */
15341475Smckusick static int
154*47211Skarels computeSignal(type)
155*47211Skarels 	int type;
15641475Smckusick {
15741475Smckusick 	int sigval;
15841475Smckusick 
15941475Smckusick 	switch (type &~ USER) {
16041475Smckusick 	case T_BUSERR:
16141475Smckusick 		sigval = SIGBUS;
162*47211Skarels 		break;
16341475Smckusick 	case T_ADDRERR:
16441475Smckusick 		sigval = SIGBUS;
165*47211Skarels 		break;
16641475Smckusick 	case T_ILLINST:
16741475Smckusick 		sigval = SIGILL;
168*47211Skarels 		break;
16941475Smckusick 	case T_ZERODIV:
17041475Smckusick 		sigval = SIGFPE;
171*47211Skarels 		break;
17241475Smckusick 	case T_CHKINST:
17341475Smckusick 		sigval = SIGFPE;
174*47211Skarels 		break;
17541475Smckusick 	case T_TRAPVINST:
17641475Smckusick 		sigval = SIGFPE;
177*47211Skarels 		break;
17841475Smckusick 	case T_PRIVINST:
17941475Smckusick 		sigval = SIGILL;
180*47211Skarels 		break;
18141475Smckusick 	case T_TRACE:
18241475Smckusick 		sigval = SIGTRAP;
183*47211Skarels 		break;
18441475Smckusick 	case T_MMUFLT:
18541475Smckusick 		sigval = SIGSEGV;
18641475Smckusick 		break;
18741475Smckusick 	case T_SSIR:
18841475Smckusick 		sigval = SIGSEGV;
18941475Smckusick 		break;
19041475Smckusick 	case T_FMTERR:
19141475Smckusick 		sigval = SIGILL;
19241475Smckusick 		break;
19341475Smckusick 	case T_FPERR:
19441475Smckusick 		sigval = SIGFPE;
19541475Smckusick 		break;
19641475Smckusick 	case T_COPERR:
19741475Smckusick 		sigval = SIGFPE;
19841475Smckusick 		break;
19943413Shibler 	case T_ASTFLT:
20041475Smckusick 		sigval = SIGINT;
20141475Smckusick 		break;
20241475Smckusick 	case T_TRAP15:
203*47211Skarels 		sigval = SIGTRAP;
20441475Smckusick 		break;
20541475Smckusick 	default:
20641475Smckusick 		sigval = SIGEMT;
20741475Smckusick 		break;
20841475Smckusick 	}
20941475Smckusick 	return (sigval);
21041475Smckusick }
21141475Smckusick 
212*47211Skarels /*
213*47211Skarels  * Definitions exported from gdb.
214*47211Skarels  */
215*47211Skarels #define NUM_REGS 18
216*47211Skarels #define REGISTER_BYTES ((16+2)*4)
217*47211Skarels #define REGISTER_BYTE(N)  ((N)*4)
21841475Smckusick 
219*47211Skarels #define GDB_SR 16
220*47211Skarels #define GDB_PC 17
221*47211Skarels 
22241475Smckusick /*
223*47211Skarels  * # of additional bytes in 680x0 exception frame format n.
224*47211Skarels  */
225*47211Skarels static int frame_bytes[16] = {
226*47211Skarels 	0, 0, sizeof(struct fmt2), 0,
227*47211Skarels 	0, 0, 0, 0,
228*47211Skarels 	0, sizeof(struct fmt9), sizeof(struct fmtA), sizeof(struct fmtB),
229*47211Skarels 	0, 0, 0, 0
230*47211Skarels };
231*47211Skarels 
232*47211Skarels /*
233*47211Skarels  * Translate the values stored in the kernel frame struct to the format
234*47211Skarels  * understood by gdb.
235*47211Skarels  */
236*47211Skarels static void
237*47211Skarels regs_to_gdb(fp, gdb_regs)
238*47211Skarels 	struct frame *fp;
239*47211Skarels 	u_long *gdb_regs;
240*47211Skarels {
241*47211Skarels 	bcopy((caddr_t)fp->f_regs, (caddr_t)gdb_regs, sizeof(fp->f_regs) + 8);
242*47211Skarels }
243*47211Skarels 
244*47211Skarels /*
245*47211Skarels  * Convert gdb register values to kernel format.
246*47211Skarels  */
247*47211Skarels static void
248*47211Skarels gdb_to_regs(fp, gdb_regs)
249*47211Skarels 	struct frame *fp;
250*47211Skarels 	u_long *gdb_regs;
251*47211Skarels {
252*47211Skarels 	bcopy((caddr_t)gdb_regs, (caddr_t)fp->f_regs, sizeof(fp->f_regs) - 4);
253*47211Skarels 	fp->f_sr = gdb_regs[GDB_SR];
254*47211Skarels 	fp->f_pc = gdb_regs[GDB_PC];
255*47211Skarels }
256*47211Skarels 
257*47211Skarels static u_long reg_cache[NUM_REGS];
258*47211Skarels 
259*47211Skarels /*
26041475Smckusick  * This function does all command procesing for interfacing to
26141475Smckusick  * a remote gdb.
26241475Smckusick  */
26341475Smckusick int
26441475Smckusick kgdb_trap(int type, unsigned code, unsigned v, struct frame *frame)
26541475Smckusick {
266*47211Skarels 	int i;
267*47211Skarels 	u_long length;
268*47211Skarels 	caddr_t addr;
269*47211Skarels 	u_char *cp;
270*47211Skarels 	int out, in;
271*47211Skarels 	int inlen, outlen;
272*47211Skarels 	static u_char inbuffer[SL_MAXMSG+1];
273*47211Skarels 	static u_char outbuffer[SL_MAXMSG];
274*47211Skarels 	u_long gdb_regs[NUM_REGS];
27541475Smckusick 
276*47211Skarels 	if (kgdb_dev < 0) {
27741475Smckusick 		/* not debugging */
27841475Smckusick 		return (0);
279*47211Skarels 	}
280*47211Skarels 	if (kgdb_active == 0) {
281*47211Skarels 		if (type != T_TRAP15) {
282*47211Skarels 			/* No debugger active -- let trap handle this. */
283*47211Skarels 			return (0);
284*47211Skarels 		}
285*47211Skarels 		kgdb_getc = constab[major(kgdb_dev)].cn_getc;
286*47211Skarels 		kgdb_putc = constab[major(kgdb_dev)].cn_putc;
287*47211Skarels 		if (kgdb_getc == 0 || kgdb_putc == 0) {
288*47211Skarels 			return (0);
289*47211Skarels 		}
290*47211Skarels 		kgdb_active = 1;
291*47211Skarels 	}
292*47211Skarels 	/*
293*47211Skarels 	 * Stick frame regs into our reg cache then tell remote host
294*47211Skarels 	 * that an exception has occured.
295*47211Skarels 	 */
296*47211Skarels 	if ((type & USER) == 0)
297*47211Skarels 		/*
298*47211Skarels 		 * After a kernel mode trap, the saved sp points at the
299*47211Skarels 		 * PSW and is useless.  The correct saved sp should be
300*47211Skarels 		 * the top of the frame.
301*47211Skarels 		 */
302*47211Skarels 		frame->f_regs[SP] = (int)&frame->F_u +
303*47211Skarels 				    frame_bytes[frame->f_format];
304*47211Skarels 	regs_to_gdb(frame, gdb_regs);
30541475Smckusick 
306*47211Skarels 	outbuffer[0] = computeSignal(type);
307*47211Skarels 	kgdb_send(KGDB_SIGNAL, outbuffer, 1);
30841475Smckusick 
309*47211Skarels 	while (1) {
310*47211Skarels 		in = kgdb_recv(inbuffer, &inlen);
311*47211Skarels 		if (in == 0 || (in & KGDB_ACK))
312*47211Skarels 			/* Ignore inbound acks and error conditions. */
313*47211Skarels 			continue;
31441475Smckusick 
315*47211Skarels 		out = in | KGDB_ACK;
316*47211Skarels 		switch (in) {
317*47211Skarels 
318*47211Skarels 		case KGDB_SIGNAL:
319*47211Skarels 			outbuffer[0] = computeSignal(type);
320*47211Skarels 			outlen = 1;
32141475Smckusick 			break;
322*47211Skarels 
323*47211Skarels 		case KGDB_REG_R:
324*47211Skarels 		case KGDB_REG_R | KGDB_DELTA:
325*47211Skarels 			cp = outbuffer;
326*47211Skarels 			outlen = 0;
327*47211Skarels 			for (i = inbuffer[0]; i < NUM_REGS; ++i) {
328*47211Skarels 				if (reg_cache[i] != gdb_regs[i] ||
329*47211Skarels 				    (in & KGDB_DELTA) == 0) {
330*47211Skarels 					if (outlen + 5 > SL_MAXMSG) {
331*47211Skarels 						out |= KGDB_MORE;
332*47211Skarels 						break;
333*47211Skarels 					}
334*47211Skarels 					cp[outlen] = i;
335*47211Skarels 					bcopy(&gdb_regs[i],
336*47211Skarels 					      &cp[outlen + 1], 4);
337*47211Skarels 					outlen += 5;
338*47211Skarels 					reg_cache[i] = gdb_regs[i];
339*47211Skarels 				}
34041475Smckusick 			}
34141475Smckusick 			break;
342*47211Skarels 
343*47211Skarels 		case KGDB_REG_W:
344*47211Skarels 		case KGDB_REG_W | KGDB_DELTA:
345*47211Skarels 			cp = inbuffer;
346*47211Skarels 			for (i = 0; i < inlen; i += 5) {
347*47211Skarels 				register int j = cp[i];
34841475Smckusick 
349*47211Skarels 				bcopy(&cp[i + 1], &gdb_regs[j], 4);
350*47211Skarels 				reg_cache[j] = gdb_regs[j];
35141475Smckusick 			}
352*47211Skarels 			gdb_to_regs(frame, gdb_regs);
353*47211Skarels 			outlen = 0;
354*47211Skarels 			break;
355*47211Skarels 
356*47211Skarels 		case KGDB_MEM_R:
357*47211Skarels 			length = inbuffer[0];
358*47211Skarels 			bcopy(&inbuffer[1], &addr, 4);
359*47211Skarels 			if (length + 1 > SL_MAXMSG) {
360*47211Skarels 				outlen = 1;
361*47211Skarels 				outbuffer[0] = E2BIG;
362*47211Skarels 			} else if (!kernacc(addr, length, B_READ)) {
363*47211Skarels 				outlen = 1;
364*47211Skarels 				outbuffer[0] = EFAULT;
365*47211Skarels 			} else {
366*47211Skarels 				outlen = length + 1;
367*47211Skarels 				outbuffer[0] = 0;
368*47211Skarels 				bcopy(addr, &outbuffer[1], length);
36941475Smckusick 			}
37041475Smckusick 			break;
37141475Smckusick 
372*47211Skarels 		case KGDB_MEM_W:
373*47211Skarels 			length = inlen - 4;
374*47211Skarels 			bcopy(inbuffer, &addr, 4);
375*47211Skarels 			outlen = 1;
376*47211Skarels 			if (!kernacc(addr, length, B_READ))
377*47211Skarels 				outbuffer[0] = EFAULT;
378*47211Skarels 			else {
379*47211Skarels 				outbuffer[0] = 0;
380*47211Skarels 				if (!kernacc(addr, length, B_WRITE))
381*47211Skarels 					chgkprot(addr, length, B_WRITE);
382*47211Skarels 				bcopy(&inbuffer[4], addr, length);
38341475Smckusick 			}
38441475Smckusick 			break;
38541475Smckusick 
386*47211Skarels 		case KGDB_KILL:
387*47211Skarels 			kgdb_active = 0;
388*47211Skarels 			/* fall through */
389*47211Skarels 		case KGDB_CONT:
390*47211Skarels 			kgdb_send(out, 0, 0);
391*47211Skarels 			frame->f_sr &=~ PSL_T;
392*47211Skarels 			return (1);
39341475Smckusick 
394*47211Skarels 		case KGDB_STEP:
395*47211Skarels 			kgdb_send(out, 0, 0);
396*47211Skarels 			frame->f_sr |= PSL_T;
39741475Smckusick 			return (1);
39841475Smckusick 
399*47211Skarels 		default:
400*47211Skarels 			/* Unknown command.  Ack with a null message. */
401*47211Skarels 			outlen = 0;
402*47211Skarels 			break;
40341475Smckusick 		}
404*47211Skarels 		/* Send the reply */
405*47211Skarels 		kgdb_send(out, outbuffer, outlen);
40641475Smckusick 	}
40741475Smckusick }
40841475Smckusick #endif
409