xref: /csrg-svn/sys/hp300/hp300/kgdb_stub.c (revision 63157)
141475Smckusick /*
2*63157Sbostic  * Copyright (c) 1990, 1993
3*63157Sbostic  *	The Regents of the University of California.  All rights reserved.
441475Smckusick  *
557149Smckusick  * This software was developed by the Computer Systems Engineering group
657149Smckusick  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
757149Smckusick  * contributed to Berkeley.
855673Smckusick  *
957149Smckusick  * All advertising materials mentioning features or use of this software
1057149Smckusick  * must display the following acknowledgement:
1157149Smckusick  *	This product includes software developed by the University of
1257149Smckusick  *	California, Lawrence Berkeley Laboratories.
1357149Smckusick  *
1441475Smckusick  * %sccs.include.redist.c%
1541475Smckusick  *
16*63157Sbostic  *	@(#)kgdb_stub.c	8.1 (Berkeley) 06/10/93
1741475Smckusick  */
1855673Smckusick 
1941475Smckusick /*
2047211Skarels  * "Stub" to allow remote cpu to debug over a serial line using gdb.
2147211Skarels  */
2241475Smckusick #ifdef KGDB
2347211Skarels #ifndef lint
2457339Shibler static char rcsid[] = "$Header: /usr/src/sys/hp300/hp300/RCS/kgdb_stub.c,v 1.5 92/12/20 15:49:01 mike Exp $";
2547211Skarels #endif
2641475Smckusick 
2756508Sbostic #include <sys/param.h>
2856508Sbostic #include <sys/systm.h>
2947211Skarels 
3056508Sbostic #include <machine/trap.h>
3156508Sbostic #include <machine/cpu.h>
3256508Sbostic #include <machine/psl.h>
3356508Sbostic #include <machine/reg.h>
3456508Sbostic #include <machine/frame.h>
3547211Skarels 
3656508Sbostic #include <sys/buf.h>
3756508Sbostic #include <hp/dev/cons.h>
3856508Sbostic 
3956508Sbostic #include <hp300/hp300/kgdb_proto.h>
4056508Sbostic #include <machine/remote-sl.h>
4156508Sbostic 
4241475Smckusick extern int kernacc();
4341475Smckusick extern void chgkprot();
4441475Smckusick 
4542367Smckusick #ifndef KGDBDEV
4650225Skarels #define KGDBDEV NODEV
4742367Smckusick #endif
4842367Smckusick #ifndef KGDBRATE
4942367Smckusick #define KGDBRATE 9600
5042367Smckusick #endif
5142367Smckusick 
5250225Skarels dev_t kgdb_dev = KGDBDEV;	/* remote debugging device (NODEV if none) */
5342367Smckusick int kgdb_rate = KGDBRATE;	/* remote debugging baud rate */
5447211Skarels int kgdb_active = 0;            /* remote debugging active if != 0 */
5541475Smckusick int kgdb_debug_init = 0;	/* != 0 waits for remote at system init */
5647471Skarels int kgdb_debug_panic = 1;	/* != 0 waits for remote on panic */
5747211Skarels int kgdb_debug = 0;
5841475Smckusick 
5947211Skarels #define GETC	((*kgdb_getc)(kgdb_dev))
6047211Skarels #define PUTC(c)	((*kgdb_putc)(kgdb_dev, c))
6147211Skarels #define PUTESC(c) { \
6247211Skarels 	if (c == FRAME_END) { \
6347211Skarels 		PUTC(FRAME_ESCAPE); \
6447211Skarels 		c = TRANS_FRAME_END; \
6547211Skarels 	} else if (c == FRAME_ESCAPE) { \
6647211Skarels 		PUTC(FRAME_ESCAPE); \
6747211Skarels 		c = TRANS_FRAME_ESCAPE; \
6855673Smckusick 	} else if (c == FRAME_START) { \
6955673Smckusick 		PUTC(FRAME_ESCAPE); \
7055673Smckusick 		c = TRANS_FRAME_START; \
7147211Skarels 	} \
7247211Skarels 	PUTC(c); \
7342367Smckusick }
7447211Skarels static int (*kgdb_getc)();
7547211Skarels static int (*kgdb_putc)();
7641475Smckusick 
7741475Smckusick /*
7847211Skarels  * Send a message.  The host gets one chance to read it.
7941475Smckusick  */
8047211Skarels static void
8147211Skarels kgdb_send(type, bp, len)
8247211Skarels 	register u_char type;
8347211Skarels 	register u_char *bp;
8447211Skarels 	register int len;
8541475Smckusick {
8647211Skarels 	register u_char csum;
8747211Skarels 	register u_char *ep = bp + len;
8841475Smckusick 
8955673Smckusick 	PUTC(FRAME_START);
9055673Smckusick 	PUTESC(type);
9155673Smckusick 
9247211Skarels 	csum = type;
9347211Skarels 	while (bp < ep) {
9447211Skarels 		type = *bp++;
9547211Skarels 		csum += type;
9647211Skarels 		PUTESC(type)
9747211Skarels 	}
9847211Skarels 	csum = -csum;
9947211Skarels 	PUTESC(csum)
10047211Skarels 	PUTC(FRAME_END);
10141475Smckusick }
10241475Smckusick 
10347211Skarels static int
10447211Skarels kgdb_recv(bp, lenp)
10547211Skarels 	u_char *bp;
10647211Skarels 	int *lenp;
10741475Smckusick {
10847211Skarels 	register u_char c, csum;
10947211Skarels 	register int escape, len;
11047211Skarels 	register int type;
11141475Smckusick 
11255673Smckusick restart:
11347211Skarels 	csum = len = escape = 0;
11447211Skarels 	type = -1;
11547211Skarels 	while (1) {
11647211Skarels 		c = GETC;
11747211Skarels 		switch (c) {
11841475Smckusick 
11947211Skarels 		case FRAME_ESCAPE:
12047211Skarels 			escape = 1;
12147211Skarels 			continue;
12241475Smckusick 
12347211Skarels 		case TRANS_FRAME_ESCAPE:
12447211Skarels 			if (escape)
12547211Skarels 				c = FRAME_ESCAPE;
12647211Skarels 			break;
12741475Smckusick 
12847211Skarels 		case TRANS_FRAME_END:
12947211Skarels 			if (escape)
13047211Skarels 				c = FRAME_END;
13141475Smckusick 			break;
13241475Smckusick 
13355673Smckusick 		case TRANS_FRAME_START:
13455673Smckusick 			if (escape)
13555673Smckusick 				c = FRAME_START;
13655673Smckusick 			break;
13755673Smckusick 
13855673Smckusick 		case FRAME_START:
13955673Smckusick 			goto restart;
14055673Smckusick 
14147211Skarels 		case FRAME_END:
14247211Skarels 			if (type < 0 || --len < 0) {
14347211Skarels 				csum = len = escape = 0;
14447211Skarels 				type = -1;
14547211Skarels 				continue;
14647211Skarels 			}
14747211Skarels 			if (csum != 0) {
14847211Skarels 				return (0);
14947211Skarels 			}
15047211Skarels 			*lenp = len;
15147211Skarels 			return type;
15241475Smckusick 		}
15347211Skarels 		csum += c;
15447211Skarels 		if (type < 0) {
15547211Skarels 			type = c;
15647211Skarels 			escape = 0;
15747211Skarels 			continue;
15841475Smckusick 		}
15955673Smckusick 		if (++len > SL_RPCSIZE) {
16047211Skarels 			while (GETC != FRAME_END)
16147211Skarels 				;
16247211Skarels 			return (0);
16347211Skarels 		}
16447211Skarels 		*bp++ = c;
16547211Skarels 		escape = 0;
16641475Smckusick 	}
16741475Smckusick }
16841475Smckusick 
16941475Smckusick /*
17041475Smckusick  * Translate a trap number into a unix compatible signal value.
17141475Smckusick  * (gdb only understands unix signal numbers).
17241475Smckusick  */
17341475Smckusick static int
17447211Skarels computeSignal(type)
17547211Skarels 	int type;
17641475Smckusick {
17741475Smckusick 	int sigval;
17841475Smckusick 
17947262Skarels 	switch (type) {
18041475Smckusick 	case T_BUSERR:
18141475Smckusick 		sigval = SIGBUS;
18247211Skarels 		break;
18341475Smckusick 	case T_ADDRERR:
18441475Smckusick 		sigval = SIGBUS;
18547211Skarels 		break;
18641475Smckusick 	case T_ILLINST:
18741475Smckusick 		sigval = SIGILL;
18847211Skarels 		break;
18941475Smckusick 	case T_ZERODIV:
19041475Smckusick 		sigval = SIGFPE;
19147211Skarels 		break;
19241475Smckusick 	case T_CHKINST:
19341475Smckusick 		sigval = SIGFPE;
19447211Skarels 		break;
19541475Smckusick 	case T_TRAPVINST:
19641475Smckusick 		sigval = SIGFPE;
19747211Skarels 		break;
19841475Smckusick 	case T_PRIVINST:
19941475Smckusick 		sigval = SIGILL;
20047211Skarels 		break;
20141475Smckusick 	case T_TRACE:
20241475Smckusick 		sigval = SIGTRAP;
20347211Skarels 		break;
20441475Smckusick 	case T_MMUFLT:
20541475Smckusick 		sigval = SIGSEGV;
20641475Smckusick 		break;
20741475Smckusick 	case T_SSIR:
20841475Smckusick 		sigval = SIGSEGV;
20941475Smckusick 		break;
21041475Smckusick 	case T_FMTERR:
21141475Smckusick 		sigval = SIGILL;
21241475Smckusick 		break;
21341475Smckusick 	case T_FPERR:
21441475Smckusick 		sigval = SIGFPE;
21541475Smckusick 		break;
21641475Smckusick 	case T_COPERR:
21741475Smckusick 		sigval = SIGFPE;
21841475Smckusick 		break;
21943413Shibler 	case T_ASTFLT:
22041475Smckusick 		sigval = SIGINT;
22141475Smckusick 		break;
22241475Smckusick 	case T_TRAP15:
22347211Skarels 		sigval = SIGTRAP;
22441475Smckusick 		break;
22541475Smckusick 	default:
22641475Smckusick 		sigval = SIGEMT;
22741475Smckusick 		break;
22841475Smckusick 	}
22941475Smckusick 	return (sigval);
23041475Smckusick }
23141475Smckusick 
23247211Skarels /*
23348473Skarels  * Trap into kgdb to wait for debugger to connect,
23447471Skarels  * noting on the console why nothing else is going on.
23547471Skarels  */
23647471Skarels kgdb_connect(verbose)
23747471Skarels 	int verbose;
23847471Skarels {
23947471Skarels 
24047471Skarels 	if (verbose)
24147471Skarels 		printf("kgdb waiting...");
24247471Skarels 	/* trap into kgdb */
24347471Skarels 	asm("trap #15;");
24447471Skarels 	if (verbose)
24547471Skarels 		printf("connected.\n");
24647471Skarels }
24747471Skarels 
24847471Skarels /*
24947471Skarels  * Decide what to do on panic.
25047471Skarels  */
25147471Skarels kgdb_panic()
25247471Skarels {
25347471Skarels 
25450225Skarels 	if (kgdb_active == 0 && kgdb_debug_panic && kgdb_dev != NODEV)
25547471Skarels 		kgdb_connect(1);
25647471Skarels }
25747471Skarels 
25847471Skarels /*
25947211Skarels  * Definitions exported from gdb.
26047211Skarels  */
26147211Skarels #define NUM_REGS 18
26247211Skarels #define REGISTER_BYTES ((16+2)*4)
26347211Skarels #define REGISTER_BYTE(N)  ((N)*4)
26441475Smckusick 
26547211Skarels #define GDB_SR 16
26647211Skarels #define GDB_PC 17
26747211Skarels 
26847262Skarels static inline void
26947262Skarels kgdb_copy(register u_char *src, register u_char *dst, register u_int nbytes)
27047211Skarels {
27147262Skarels 	register u_char *ep = src + nbytes;
27247211Skarels 
27347262Skarels 	while (src < ep)
27447262Skarels 		*dst++ = *src++;
27547211Skarels }
27647211Skarels 
27757339Shibler /*
27857339Shibler  * There is a short pad word between SP (A7) and SR which keeps the
27957339Shibler  * kernel stack long word aligned (note that this is in addition to
28057339Shibler  * the stack adjust short that we treat as the upper half of a longword
28157339Shibler  * SR).  We must skip this when copying into and out of gdb.
28257339Shibler  */
28357339Shibler static inline void
28457339Shibler regs_to_gdb(struct frame *fp, u_long *regs)
28557339Shibler {
28657339Shibler 	kgdb_copy((u_char *)fp->f_regs, (u_char *)regs, 16*4);
28757339Shibler 	kgdb_copy((u_char *)&fp->f_stackadj, (u_char *)&regs[GDB_SR], 2*4);
28857339Shibler }
28947262Skarels 
29057339Shibler static inline void
29157339Shibler gdb_to_regs(struct frame *fp, u_long *regs)
29257339Shibler {
29357339Shibler 	kgdb_copy((u_char *)regs, (u_char *)fp->f_regs, 16*4);
29457339Shibler 	kgdb_copy((u_char *)&regs[GDB_SR], (u_char *)&fp->f_stackadj, 2*4);
29557339Shibler }
29647262Skarels 
29747211Skarels static u_long reg_cache[NUM_REGS];
29855673Smckusick static u_char inbuffer[SL_RPCSIZE+1];
29955673Smckusick static u_char outbuffer[SL_RPCSIZE];
30047211Skarels 
30147211Skarels /*
30241475Smckusick  * This function does all command procesing for interfacing to
30341475Smckusick  * a remote gdb.
30441475Smckusick  */
30541475Smckusick int
30647262Skarels kgdb_trap(int type, struct frame *frame)
30741475Smckusick {
30847262Skarels 	register u_long len;
30947262Skarels 	u_char *addr;
31047262Skarels 	register u_char *cp;
31147262Skarels 	register u_char out, in;
31247262Skarels 	register int outlen;
31347262Skarels 	int inlen;
31447211Skarels 	u_long gdb_regs[NUM_REGS];
31541475Smckusick 
31647211Skarels 	if (kgdb_dev < 0) {
31741475Smckusick 		/* not debugging */
31841475Smckusick 		return (0);
31947211Skarels 	}
32047211Skarels 	if (kgdb_active == 0) {
32147211Skarels 		if (type != T_TRAP15) {
32247211Skarels 			/* No debugger active -- let trap handle this. */
32347211Skarels 			return (0);
32447211Skarels 		}
32547471Skarels 		kgdb_getc = 0;
32647471Skarels 		for (inlen = 0; constab[inlen].cn_probe; inlen++)
32747471Skarels 		    if (major(constab[inlen].cn_dev) == major(kgdb_dev)) {
32847471Skarels 			kgdb_getc = constab[inlen].cn_getc;
32947471Skarels 			kgdb_putc = constab[inlen].cn_putc;
33047471Skarels 			break;
33147471Skarels 		}
33247262Skarels 		if (kgdb_getc == 0 || kgdb_putc == 0)
33347211Skarels 			return (0);
33447262Skarels 		/*
33548473Skarels 		 * If the packet that woke us up isn't an exec packet,
33647262Skarels 		 * ignore it since there is no active debugger.  Also,
33747262Skarels 		 * we check that it's not an ack to be sure that the
33847262Skarels 		 * remote side doesn't send back a response after the
33947262Skarels 		 * local gdb has exited.  Otherwise, the local host
34047262Skarels 		 * could trap into gdb if it's running a gdb kernel too.
34147262Skarels 		 */
34247262Skarels 		in = GETC;
34348473Skarels 		/*
34448473Skarels 		 * If we came in asynchronously through the serial line,
34548473Skarels 		 * the framing character is eaten by the receive interrupt,
34648473Skarels 		 * but if we come in through a synchronous trap (i.e., via
34748473Skarels 		 * kgdb_connect()), we will see the extra character.
34848473Skarels 		 */
34955673Smckusick 		if (in == FRAME_START)
35048473Skarels 			in = GETC;
35148473Skarels 
35255673Smckusick 		/*
35355673Smckusick 		 * Check that this is a debugger exec message.  If so,
35455673Smckusick 		 * slurp up the entire message then ack it, and fall
35555673Smckusick 		 * through to the recv loop.
35655673Smckusick 		 */
35748473Skarels 		if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0)
35847262Skarels 			return (0);
35947262Skarels 		while (GETC != FRAME_END)
36047262Skarels 			;
36148473Skarels 		/*
36248473Skarels 		 * Do the printf *before* we ack the message.  This way
36348473Skarels 		 * we won't drop any inbound characters while we're
36448473Skarels 		 * doing the polling printf.
36548473Skarels 		 */
36648473Skarels 		printf("kgdb started from device %x\n", kgdb_dev);
36748473Skarels 		kgdb_send(in | KGDB_ACK, (u_char *)0, 0);
36847211Skarels 		kgdb_active = 1;
36947211Skarels 	}
37047211Skarels 	/*
37147211Skarels 	 * Stick frame regs into our reg cache then tell remote host
37247211Skarels 	 * that an exception has occured.
37347211Skarels 	 */
37447211Skarels 	regs_to_gdb(frame, gdb_regs);
37548473Skarels 	if (type != T_TRAP15) {
37648473Skarels 		/*
37748473Skarels 		 * Only send an asynchronous SIGNAL message when we hit
37848473Skarels 		 * a breakpoint.  Otherwise, we will drop the incoming
37948473Skarels 		 * packet while we output this one (and on entry the other
38048473Skarels 		 * side isn't interested in the SIGNAL type -- if it is,
38148473Skarels 		 * it will have used a signal packet.)
38248473Skarels 		 */
38348473Skarels 		outbuffer[0] = computeSignal(type);
38448473Skarels 		kgdb_send(KGDB_SIGNAL, outbuffer, 1);
38548473Skarels 	}
38641475Smckusick 
38747211Skarels 	while (1) {
38847211Skarels 		in = kgdb_recv(inbuffer, &inlen);
38947211Skarels 		if (in == 0 || (in & KGDB_ACK))
39047211Skarels 			/* Ignore inbound acks and error conditions. */
39147211Skarels 			continue;
39241475Smckusick 
39347211Skarels 		out = in | KGDB_ACK;
39447262Skarels 		switch (KGDB_CMD(in)) {
39547211Skarels 
39647211Skarels 		case KGDB_SIGNAL:
39747262Skarels 			/*
39847262Skarels 			 * if this command came from a running gdb,
39947262Skarels 			 * answer it -- the other guy has no way of
40047262Skarels 			 * knowing if we're in or out of this loop
40147262Skarels 			 * when he issues a "remote-signal".  (Note
40247262Skarels 			 * that without the length check, we could
40347262Skarels 			 * loop here forever if the ourput line is
40447262Skarels 			 * looped back or the remote host is echoing.)
40547262Skarels 			 */
40647262Skarels 			if (inlen == 0) {
40747262Skarels 				outbuffer[0] = computeSignal(type);
40847262Skarels 				kgdb_send(KGDB_SIGNAL, outbuffer, 1);
40947262Skarels 			}
41047262Skarels 			continue;
41147211Skarels 
41247211Skarels 		case KGDB_REG_R:
41347211Skarels 		case KGDB_REG_R | KGDB_DELTA:
41447211Skarels 			cp = outbuffer;
41547211Skarels 			outlen = 0;
41647262Skarels 			for (len = inbuffer[0]; len < NUM_REGS; ++len) {
41747262Skarels 				if (reg_cache[len] != gdb_regs[len] ||
41847211Skarels 				    (in & KGDB_DELTA) == 0) {
41955673Smckusick 					if (outlen + 5 > SL_MAXDATA) {
42047211Skarels 						out |= KGDB_MORE;
42147211Skarels 						break;
42247211Skarels 					}
42347262Skarels 					cp[outlen] = len;
42447262Skarels 					kgdb_copy((u_char *)&gdb_regs[len],
42547262Skarels 						  &cp[outlen + 1], 4);
42647262Skarels 					reg_cache[len] = gdb_regs[len];
42747211Skarels 					outlen += 5;
42847211Skarels 				}
42941475Smckusick 			}
43041475Smckusick 			break;
43147211Skarels 
43247211Skarels 		case KGDB_REG_W:
43347211Skarels 		case KGDB_REG_W | KGDB_DELTA:
43447211Skarels 			cp = inbuffer;
43547262Skarels 			for (len = 0; len < inlen; len += 5) {
43647262Skarels 				register int j = cp[len];
43741475Smckusick 
43847262Skarels 				kgdb_copy(&cp[len + 1],
43947262Skarels 					  (u_char *)&gdb_regs[j], 4);
44047211Skarels 				reg_cache[j] = gdb_regs[j];
44141475Smckusick 			}
44247211Skarels 			gdb_to_regs(frame, gdb_regs);
44347211Skarels 			outlen = 0;
44447211Skarels 			break;
44547211Skarels 
44647211Skarels 		case KGDB_MEM_R:
44747262Skarels 			len = inbuffer[0];
44847262Skarels 			kgdb_copy(&inbuffer[1], (u_char *)&addr, 4);
44955673Smckusick 			if (len > SL_MAXDATA) {
45047211Skarels 				outlen = 1;
45147211Skarels 				outbuffer[0] = E2BIG;
45247262Skarels 			} else if (!kgdb_acc(addr, len, B_READ)) {
45347211Skarels 				outlen = 1;
45447211Skarels 				outbuffer[0] = EFAULT;
45547211Skarels 			} else {
45647262Skarels 				outlen = len + 1;
45747211Skarels 				outbuffer[0] = 0;
45847262Skarels 				kgdb_copy(addr, &outbuffer[1], len);
45941475Smckusick 			}
46041475Smckusick 			break;
46141475Smckusick 
46247211Skarels 		case KGDB_MEM_W:
46347262Skarels 			len = inlen - 4;
46447262Skarels 			kgdb_copy(inbuffer, (u_char *)&addr, 4);
46547211Skarels 			outlen = 1;
46647262Skarels 			if (!kgdb_acc(addr, len, B_READ))
46747211Skarels 				outbuffer[0] = EFAULT;
46847211Skarels 			else {
46947211Skarels 				outbuffer[0] = 0;
47047262Skarels 				if (!kgdb_acc(addr, len, B_WRITE))
47147262Skarels 					chgkprot(addr, len, B_WRITE);
47247262Skarels 				kgdb_copy(&inbuffer[4], addr, len);
47354245Smckusick 				ICIA();
47441475Smckusick 			}
47541475Smckusick 			break;
47641475Smckusick 
47747211Skarels 		case KGDB_KILL:
47847211Skarels 			kgdb_active = 0;
47948473Skarels 			printf("kgdb detached\n");
48047211Skarels 			/* fall through */
48147211Skarels 		case KGDB_CONT:
48247211Skarels 			kgdb_send(out, 0, 0);
48347211Skarels 			frame->f_sr &=~ PSL_T;
48447211Skarels 			return (1);
48541475Smckusick 
48647211Skarels 		case KGDB_STEP:
48747211Skarels 			kgdb_send(out, 0, 0);
48847211Skarels 			frame->f_sr |= PSL_T;
48941475Smckusick 			return (1);
49041475Smckusick 
49148473Skarels 		case KGDB_EXEC:
49247211Skarels 		default:
49347211Skarels 			/* Unknown command.  Ack with a null message. */
49447211Skarels 			outlen = 0;
49547211Skarels 			break;
49641475Smckusick 		}
49747211Skarels 		/* Send the reply */
49847211Skarels 		kgdb_send(out, outbuffer, outlen);
49941475Smckusick 	}
50041475Smckusick }
50147262Skarels 
50247262Skarels /*
50347262Skarels  * XXX do kernacc call if safe, otherwise attempt
50447262Skarels  * to simulate by simple bounds-checking.
50547262Skarels  */
50647262Skarels kgdb_acc(addr, len, rw)
50747262Skarels 	caddr_t addr;
50847262Skarels {
50949119Skarels 	extern char proc0paddr[], kstack[];	/* XXX */
51047262Skarels 	extern char *kernel_map;		/* XXX! */
51147262Skarels 
51247262Skarels 	if (kernel_map != NULL)
51347262Skarels 		return (kernacc(addr, len, rw));
51447262Skarels 	if (addr < proc0paddr + UPAGES * NBPG  ||
51549119Skarels 	    kstack <= addr && addr < kstack + UPAGES * NBPG)
51647262Skarels 		return (1);
51747262Skarels 	return (0);
51847262Skarels }
51941475Smckusick #endif
520