141475Smckusick /*
263157Sbostic * Copyright (c) 1990, 1993
363157Sbostic * 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*65700Shibler * @(#)kgdb_stub.c 8.4 (Berkeley) 01/12/94
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
kgdb_send(type,bp,len)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
kgdb_recv(bp,lenp)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
computeSignal(type)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 */
kgdb_connect(verbose)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 */
kgdb_panic()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
kgdb_copy(src,dst,nbytes)26965628Sbostic kgdb_copy(src, dst, nbytes)
27065628Sbostic register u_char *src, *dst;
27165628Sbostic register u_int nbytes;
27247211Skarels {
27347262Skarels register u_char *ep = src + nbytes;
27447211Skarels
27547262Skarels while (src < ep)
27647262Skarels *dst++ = *src++;
27747211Skarels }
27847211Skarels
27957339Shibler /*
28057339Shibler * There is a short pad word between SP (A7) and SR which keeps the
28157339Shibler * kernel stack long word aligned (note that this is in addition to
28257339Shibler * the stack adjust short that we treat as the upper half of a longword
28357339Shibler * SR). We must skip this when copying into and out of gdb.
28457339Shibler */
28557339Shibler static inline void
regs_to_gdb(fp,regs)28665628Sbostic regs_to_gdb(fp, regs)
28765628Sbostic struct frame *fp;
28865628Sbostic u_long *regs;
28957339Shibler {
29057339Shibler kgdb_copy((u_char *)fp->f_regs, (u_char *)regs, 16*4);
29157339Shibler kgdb_copy((u_char *)&fp->f_stackadj, (u_char *)®s[GDB_SR], 2*4);
29257339Shibler }
29347262Skarels
29457339Shibler static inline void
gdb_to_regs(fp,regs)29565628Sbostic gdb_to_regs(fp, regs)
29665628Sbostic struct frame *fp;
29765647Sbostic u_long *regs;
29857339Shibler {
29957339Shibler kgdb_copy((u_char *)regs, (u_char *)fp->f_regs, 16*4);
30057339Shibler kgdb_copy((u_char *)®s[GDB_SR], (u_char *)&fp->f_stackadj, 2*4);
30157339Shibler }
30247262Skarels
30347211Skarels static u_long reg_cache[NUM_REGS];
30455673Smckusick static u_char inbuffer[SL_RPCSIZE+1];
30555673Smckusick static u_char outbuffer[SL_RPCSIZE];
30647211Skarels
30747211Skarels /*
30841475Smckusick * This function does all command procesing for interfacing to
30941475Smckusick * a remote gdb.
31041475Smckusick */
31141475Smckusick int
kgdb_trap(type,frame)31265628Sbostic kgdb_trap(type, frame)
31365628Sbostic int type;
31465628Sbostic struct frame *frame;
31541475Smckusick {
31647262Skarels register u_long len;
31747262Skarels u_char *addr;
31847262Skarels register u_char *cp;
31947262Skarels register u_char out, in;
32047262Skarels register int outlen;
32147262Skarels int inlen;
32247211Skarels u_long gdb_regs[NUM_REGS];
32341475Smckusick
324*65700Shibler if ((int)kgdb_dev < 0) {
32541475Smckusick /* not debugging */
32641475Smckusick return (0);
32747211Skarels }
32847211Skarels if (kgdb_active == 0) {
32947211Skarels if (type != T_TRAP15) {
33047211Skarels /* No debugger active -- let trap handle this. */
33147211Skarels return (0);
33247211Skarels }
33347471Skarels kgdb_getc = 0;
33447471Skarels for (inlen = 0; constab[inlen].cn_probe; inlen++)
33547471Skarels if (major(constab[inlen].cn_dev) == major(kgdb_dev)) {
33647471Skarels kgdb_getc = constab[inlen].cn_getc;
33747471Skarels kgdb_putc = constab[inlen].cn_putc;
33847471Skarels break;
33947471Skarels }
34047262Skarels if (kgdb_getc == 0 || kgdb_putc == 0)
34147211Skarels return (0);
34247262Skarels /*
34348473Skarels * If the packet that woke us up isn't an exec packet,
34447262Skarels * ignore it since there is no active debugger. Also,
34547262Skarels * we check that it's not an ack to be sure that the
34647262Skarels * remote side doesn't send back a response after the
34747262Skarels * local gdb has exited. Otherwise, the local host
34847262Skarels * could trap into gdb if it's running a gdb kernel too.
34947262Skarels */
35047262Skarels in = GETC;
35148473Skarels /*
35248473Skarels * If we came in asynchronously through the serial line,
35348473Skarels * the framing character is eaten by the receive interrupt,
35448473Skarels * but if we come in through a synchronous trap (i.e., via
35548473Skarels * kgdb_connect()), we will see the extra character.
35648473Skarels */
35755673Smckusick if (in == FRAME_START)
35848473Skarels in = GETC;
35948473Skarels
36055673Smckusick /*
36155673Smckusick * Check that this is a debugger exec message. If so,
36255673Smckusick * slurp up the entire message then ack it, and fall
36355673Smckusick * through to the recv loop.
36455673Smckusick */
36548473Skarels if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0)
36647262Skarels return (0);
36747262Skarels while (GETC != FRAME_END)
36847262Skarels ;
36948473Skarels /*
37048473Skarels * Do the printf *before* we ack the message. This way
37148473Skarels * we won't drop any inbound characters while we're
37248473Skarels * doing the polling printf.
37348473Skarels */
37448473Skarels printf("kgdb started from device %x\n", kgdb_dev);
37548473Skarels kgdb_send(in | KGDB_ACK, (u_char *)0, 0);
37647211Skarels kgdb_active = 1;
37747211Skarels }
37847211Skarels /*
37947211Skarels * Stick frame regs into our reg cache then tell remote host
38047211Skarels * that an exception has occured.
38147211Skarels */
38247211Skarels regs_to_gdb(frame, gdb_regs);
38348473Skarels if (type != T_TRAP15) {
38448473Skarels /*
38548473Skarels * Only send an asynchronous SIGNAL message when we hit
38648473Skarels * a breakpoint. Otherwise, we will drop the incoming
38748473Skarels * packet while we output this one (and on entry the other
38848473Skarels * side isn't interested in the SIGNAL type -- if it is,
38948473Skarels * it will have used a signal packet.)
39048473Skarels */
39148473Skarels outbuffer[0] = computeSignal(type);
39248473Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1);
39348473Skarels }
39441475Smckusick
39547211Skarels while (1) {
39647211Skarels in = kgdb_recv(inbuffer, &inlen);
39747211Skarels if (in == 0 || (in & KGDB_ACK))
39847211Skarels /* Ignore inbound acks and error conditions. */
39947211Skarels continue;
40041475Smckusick
40147211Skarels out = in | KGDB_ACK;
40247262Skarels switch (KGDB_CMD(in)) {
40347211Skarels
40447211Skarels case KGDB_SIGNAL:
40547262Skarels /*
40647262Skarels * if this command came from a running gdb,
40747262Skarels * answer it -- the other guy has no way of
40847262Skarels * knowing if we're in or out of this loop
40947262Skarels * when he issues a "remote-signal". (Note
41047262Skarels * that without the length check, we could
41147262Skarels * loop here forever if the ourput line is
41247262Skarels * looped back or the remote host is echoing.)
41347262Skarels */
41447262Skarels if (inlen == 0) {
41547262Skarels outbuffer[0] = computeSignal(type);
41647262Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1);
41747262Skarels }
41847262Skarels continue;
41947211Skarels
42047211Skarels case KGDB_REG_R:
42147211Skarels case KGDB_REG_R | KGDB_DELTA:
42247211Skarels cp = outbuffer;
42347211Skarels outlen = 0;
42447262Skarels for (len = inbuffer[0]; len < NUM_REGS; ++len) {
42547262Skarels if (reg_cache[len] != gdb_regs[len] ||
42647211Skarels (in & KGDB_DELTA) == 0) {
42755673Smckusick if (outlen + 5 > SL_MAXDATA) {
42847211Skarels out |= KGDB_MORE;
42947211Skarels break;
43047211Skarels }
43147262Skarels cp[outlen] = len;
43247262Skarels kgdb_copy((u_char *)&gdb_regs[len],
43347262Skarels &cp[outlen + 1], 4);
43447262Skarels reg_cache[len] = gdb_regs[len];
43547211Skarels outlen += 5;
43647211Skarels }
43741475Smckusick }
43841475Smckusick break;
43947211Skarels
44047211Skarels case KGDB_REG_W:
44147211Skarels case KGDB_REG_W | KGDB_DELTA:
44247211Skarels cp = inbuffer;
44347262Skarels for (len = 0; len < inlen; len += 5) {
44447262Skarels register int j = cp[len];
44541475Smckusick
44647262Skarels kgdb_copy(&cp[len + 1],
44747262Skarels (u_char *)&gdb_regs[j], 4);
44847211Skarels reg_cache[j] = gdb_regs[j];
44941475Smckusick }
45047211Skarels gdb_to_regs(frame, gdb_regs);
45147211Skarels outlen = 0;
45247211Skarels break;
45347211Skarels
45447211Skarels case KGDB_MEM_R:
45547262Skarels len = inbuffer[0];
45647262Skarels kgdb_copy(&inbuffer[1], (u_char *)&addr, 4);
45755673Smckusick if (len > SL_MAXDATA) {
45847211Skarels outlen = 1;
45947211Skarels outbuffer[0] = E2BIG;
46047262Skarels } else if (!kgdb_acc(addr, len, B_READ)) {
46147211Skarels outlen = 1;
46247211Skarels outbuffer[0] = EFAULT;
46347211Skarels } else {
46447262Skarels outlen = len + 1;
46547211Skarels outbuffer[0] = 0;
46647262Skarels kgdb_copy(addr, &outbuffer[1], len);
46741475Smckusick }
46841475Smckusick break;
46941475Smckusick
47047211Skarels case KGDB_MEM_W:
47147262Skarels len = inlen - 4;
47247262Skarels kgdb_copy(inbuffer, (u_char *)&addr, 4);
47347211Skarels outlen = 1;
47447262Skarels if (!kgdb_acc(addr, len, B_READ))
47547211Skarels outbuffer[0] = EFAULT;
47647211Skarels else {
47747211Skarels outbuffer[0] = 0;
47847262Skarels if (!kgdb_acc(addr, len, B_WRITE))
47947262Skarels chgkprot(addr, len, B_WRITE);
48047262Skarels kgdb_copy(&inbuffer[4], addr, len);
48154245Smckusick ICIA();
48241475Smckusick }
48341475Smckusick break;
48441475Smckusick
48547211Skarels case KGDB_KILL:
48647211Skarels kgdb_active = 0;
48748473Skarels printf("kgdb detached\n");
48847211Skarels /* fall through */
48947211Skarels case KGDB_CONT:
49047211Skarels kgdb_send(out, 0, 0);
49147211Skarels frame->f_sr &=~ PSL_T;
49247211Skarels return (1);
49341475Smckusick
49447211Skarels case KGDB_STEP:
49547211Skarels kgdb_send(out, 0, 0);
49647211Skarels frame->f_sr |= PSL_T;
49741475Smckusick return (1);
49841475Smckusick
49948473Skarels case KGDB_EXEC:
50047211Skarels default:
50147211Skarels /* Unknown command. Ack with a null message. */
50247211Skarels outlen = 0;
50347211Skarels break;
50441475Smckusick }
50547211Skarels /* Send the reply */
50647211Skarels kgdb_send(out, outbuffer, outlen);
50741475Smckusick }
50841475Smckusick }
50947262Skarels
51047262Skarels /*
51147262Skarels * XXX do kernacc call if safe, otherwise attempt
51247262Skarels * to simulate by simple bounds-checking.
51347262Skarels */
kgdb_acc(addr,len,rw)51447262Skarels kgdb_acc(addr, len, rw)
51547262Skarels caddr_t addr;
51665628Sbostic int len, rw;
51747262Skarels {
51849119Skarels extern char proc0paddr[], kstack[]; /* XXX */
51947262Skarels extern char *kernel_map; /* XXX! */
52047262Skarels
52147262Skarels if (kernel_map != NULL)
52247262Skarels return (kernacc(addr, len, rw));
52347262Skarels if (addr < proc0paddr + UPAGES * NBPG ||
52449119Skarels kstack <= addr && addr < kstack + UPAGES * NBPG)
52547262Skarels return (1);
52647262Skarels return (0);
52747262Skarels }
52865628Sbostic #endif /* KGDB */
529