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*65628Sbostic * @(#)kgdb_stub.c 8.2 (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 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 269*65628Sbostic kgdb_copy(src, dst, nbytes) 270*65628Sbostic register u_char *src, *dst; 271*65628Sbostic 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 286*65628Sbostic regs_to_gdb(fp, regs) 287*65628Sbostic struct frame *fp; 288*65628Sbostic 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 295*65628Sbostic gdb_to_regs(fp, regs) 296*65628Sbostic struct frame *fp; 297*65628Sbostic 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 312*65628Sbostic kgdb_trap(type, frame) 313*65628Sbostic int type; 314*65628Sbostic 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 32447211Skarels if (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 */ 51447262Skarels kgdb_acc(addr, len, rw) 51547262Skarels caddr_t addr; 516*65628Sbostic 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 } 528*65628Sbostic #endif /* KGDB */ 529