141475Smckusick /* 247211Skarels * Copyright (c) 1990 Regents of the University of California. 341475Smckusick * All rights reserved. 441475Smckusick * 555673Smckusick * This code is derived from software contributed to Berkeley by 655673Smckusick * Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory. 755673Smckusick * 841475Smckusick * %sccs.include.redist.c% 941475Smckusick * 10*56508Sbostic * @(#)kgdb_stub.c 7.14 (Berkeley) 10/11/92 1141475Smckusick */ 1255673Smckusick 1341475Smckusick /* 1447211Skarels * "Stub" to allow remote cpu to debug over a serial line using gdb. 1547211Skarels */ 1641475Smckusick #ifdef KGDB 1747211Skarels #ifndef lint 1855673Smckusick static char rcsid[] = "$Header: kgdb_stub.c,v 1.2 92/07/23 19:37:50 mccanne Exp $"; 1947211Skarels #endif 2041475Smckusick 21*56508Sbostic #include <sys/param.h> 22*56508Sbostic #include <sys/systm.h> 2347211Skarels 24*56508Sbostic #include <machine/trap.h> 25*56508Sbostic #include <machine/cpu.h> 26*56508Sbostic #include <machine/psl.h> 27*56508Sbostic #include <machine/reg.h> 28*56508Sbostic #include <machine/frame.h> 2947211Skarels 30*56508Sbostic #include <sys/buf.h> 31*56508Sbostic #include <hp/dev/cons.h> 32*56508Sbostic 33*56508Sbostic #include <hp300/hp300/kgdb_proto.h> 34*56508Sbostic #include <machine/remote-sl.h> 35*56508Sbostic 3641475Smckusick extern int kernacc(); 3741475Smckusick extern void chgkprot(); 3841475Smckusick 3942367Smckusick #ifndef KGDBDEV 4050225Skarels #define KGDBDEV NODEV 4142367Smckusick #endif 4242367Smckusick #ifndef KGDBRATE 4342367Smckusick #define KGDBRATE 9600 4442367Smckusick #endif 4542367Smckusick 4650225Skarels dev_t kgdb_dev = KGDBDEV; /* remote debugging device (NODEV if none) */ 4742367Smckusick int kgdb_rate = KGDBRATE; /* remote debugging baud rate */ 4847211Skarels int kgdb_active = 0; /* remote debugging active if != 0 */ 4941475Smckusick int kgdb_debug_init = 0; /* != 0 waits for remote at system init */ 5047471Skarels int kgdb_debug_panic = 1; /* != 0 waits for remote on panic */ 5147211Skarels int kgdb_debug = 0; 5241475Smckusick 5347211Skarels #define GETC ((*kgdb_getc)(kgdb_dev)) 5447211Skarels #define PUTC(c) ((*kgdb_putc)(kgdb_dev, c)) 5547211Skarels #define PUTESC(c) { \ 5647211Skarels if (c == FRAME_END) { \ 5747211Skarels PUTC(FRAME_ESCAPE); \ 5847211Skarels c = TRANS_FRAME_END; \ 5947211Skarels } else if (c == FRAME_ESCAPE) { \ 6047211Skarels PUTC(FRAME_ESCAPE); \ 6147211Skarels c = TRANS_FRAME_ESCAPE; \ 6255673Smckusick } else if (c == FRAME_START) { \ 6355673Smckusick PUTC(FRAME_ESCAPE); \ 6455673Smckusick c = TRANS_FRAME_START; \ 6547211Skarels } \ 6647211Skarels PUTC(c); \ 6742367Smckusick } 6847211Skarels static int (*kgdb_getc)(); 6947211Skarels static int (*kgdb_putc)(); 7041475Smckusick 7141475Smckusick /* 7247211Skarels * Send a message. The host gets one chance to read it. 7341475Smckusick */ 7447211Skarels static void 7547211Skarels kgdb_send(type, bp, len) 7647211Skarels register u_char type; 7747211Skarels register u_char *bp; 7847211Skarels register int len; 7941475Smckusick { 8047211Skarels register u_char csum; 8147211Skarels register u_char *ep = bp + len; 8241475Smckusick 8355673Smckusick PUTC(FRAME_START); 8455673Smckusick PUTESC(type); 8555673Smckusick 8647211Skarels csum = type; 8747211Skarels while (bp < ep) { 8847211Skarels type = *bp++; 8947211Skarels csum += type; 9047211Skarels PUTESC(type) 9147211Skarels } 9247211Skarels csum = -csum; 9347211Skarels PUTESC(csum) 9447211Skarels PUTC(FRAME_END); 9541475Smckusick } 9641475Smckusick 9747211Skarels static int 9847211Skarels kgdb_recv(bp, lenp) 9947211Skarels u_char *bp; 10047211Skarels int *lenp; 10141475Smckusick { 10247211Skarels register u_char c, csum; 10347211Skarels register int escape, len; 10447211Skarels register int type; 10541475Smckusick 10655673Smckusick restart: 10747211Skarels csum = len = escape = 0; 10847211Skarels type = -1; 10947211Skarels while (1) { 11047211Skarels c = GETC; 11147211Skarels switch (c) { 11241475Smckusick 11347211Skarels case FRAME_ESCAPE: 11447211Skarels escape = 1; 11547211Skarels continue; 11641475Smckusick 11747211Skarels case TRANS_FRAME_ESCAPE: 11847211Skarels if (escape) 11947211Skarels c = FRAME_ESCAPE; 12047211Skarels break; 12141475Smckusick 12247211Skarels case TRANS_FRAME_END: 12347211Skarels if (escape) 12447211Skarels c = FRAME_END; 12541475Smckusick break; 12641475Smckusick 12755673Smckusick case TRANS_FRAME_START: 12855673Smckusick if (escape) 12955673Smckusick c = FRAME_START; 13055673Smckusick break; 13155673Smckusick 13255673Smckusick case FRAME_START: 13355673Smckusick goto restart; 13455673Smckusick 13547211Skarels case FRAME_END: 13647211Skarels if (type < 0 || --len < 0) { 13747211Skarels csum = len = escape = 0; 13847211Skarels type = -1; 13947211Skarels continue; 14047211Skarels } 14147211Skarels if (csum != 0) { 14247211Skarels return (0); 14347211Skarels } 14447211Skarels *lenp = len; 14547211Skarels return type; 14641475Smckusick } 14747211Skarels csum += c; 14847211Skarels if (type < 0) { 14947211Skarels type = c; 15047211Skarels escape = 0; 15147211Skarels continue; 15241475Smckusick } 15355673Smckusick if (++len > SL_RPCSIZE) { 15447211Skarels while (GETC != FRAME_END) 15547211Skarels ; 15647211Skarels return (0); 15747211Skarels } 15847211Skarels *bp++ = c; 15947211Skarels escape = 0; 16041475Smckusick } 16141475Smckusick } 16241475Smckusick 16341475Smckusick /* 16441475Smckusick * Translate a trap number into a unix compatible signal value. 16541475Smckusick * (gdb only understands unix signal numbers). 16641475Smckusick */ 16741475Smckusick static int 16847211Skarels computeSignal(type) 16947211Skarels int type; 17041475Smckusick { 17141475Smckusick int sigval; 17241475Smckusick 17347262Skarels switch (type) { 17441475Smckusick case T_BUSERR: 17541475Smckusick sigval = SIGBUS; 17647211Skarels break; 17741475Smckusick case T_ADDRERR: 17841475Smckusick sigval = SIGBUS; 17947211Skarels break; 18041475Smckusick case T_ILLINST: 18141475Smckusick sigval = SIGILL; 18247211Skarels break; 18341475Smckusick case T_ZERODIV: 18441475Smckusick sigval = SIGFPE; 18547211Skarels break; 18641475Smckusick case T_CHKINST: 18741475Smckusick sigval = SIGFPE; 18847211Skarels break; 18941475Smckusick case T_TRAPVINST: 19041475Smckusick sigval = SIGFPE; 19147211Skarels break; 19241475Smckusick case T_PRIVINST: 19341475Smckusick sigval = SIGILL; 19447211Skarels break; 19541475Smckusick case T_TRACE: 19641475Smckusick sigval = SIGTRAP; 19747211Skarels break; 19841475Smckusick case T_MMUFLT: 19941475Smckusick sigval = SIGSEGV; 20041475Smckusick break; 20141475Smckusick case T_SSIR: 20241475Smckusick sigval = SIGSEGV; 20341475Smckusick break; 20441475Smckusick case T_FMTERR: 20541475Smckusick sigval = SIGILL; 20641475Smckusick break; 20741475Smckusick case T_FPERR: 20841475Smckusick sigval = SIGFPE; 20941475Smckusick break; 21041475Smckusick case T_COPERR: 21141475Smckusick sigval = SIGFPE; 21241475Smckusick break; 21343413Shibler case T_ASTFLT: 21441475Smckusick sigval = SIGINT; 21541475Smckusick break; 21641475Smckusick case T_TRAP15: 21747211Skarels sigval = SIGTRAP; 21841475Smckusick break; 21941475Smckusick default: 22041475Smckusick sigval = SIGEMT; 22141475Smckusick break; 22241475Smckusick } 22341475Smckusick return (sigval); 22441475Smckusick } 22541475Smckusick 22647211Skarels /* 22748473Skarels * Trap into kgdb to wait for debugger to connect, 22847471Skarels * noting on the console why nothing else is going on. 22947471Skarels */ 23047471Skarels kgdb_connect(verbose) 23147471Skarels int verbose; 23247471Skarels { 23347471Skarels 23447471Skarels if (verbose) 23547471Skarels printf("kgdb waiting..."); 23647471Skarels /* trap into kgdb */ 23747471Skarels asm("trap #15;"); 23847471Skarels if (verbose) 23947471Skarels printf("connected.\n"); 24047471Skarels } 24147471Skarels 24247471Skarels /* 24347471Skarels * Decide what to do on panic. 24447471Skarels */ 24547471Skarels kgdb_panic() 24647471Skarels { 24747471Skarels 24850225Skarels if (kgdb_active == 0 && kgdb_debug_panic && kgdb_dev != NODEV) 24947471Skarels kgdb_connect(1); 25047471Skarels } 25147471Skarels 25247471Skarels /* 25347211Skarels * Definitions exported from gdb. 25447211Skarels */ 25547211Skarels #define NUM_REGS 18 25647211Skarels #define REGISTER_BYTES ((16+2)*4) 25747211Skarels #define REGISTER_BYTE(N) ((N)*4) 25841475Smckusick 25947211Skarels #define GDB_SR 16 26047211Skarels #define GDB_PC 17 26147211Skarels 26247262Skarels static inline void 26347262Skarels kgdb_copy(register u_char *src, register u_char *dst, register u_int nbytes) 26447211Skarels { 26547262Skarels register u_char *ep = src + nbytes; 26647211Skarels 26747262Skarels while (src < ep) 26847262Skarels *dst++ = *src++; 26947211Skarels } 27047211Skarels 27147262Skarels #define regs_to_gdb(fp, regs) \ 27247262Skarels (kgdb_copy((u_char *)((fp)->f_regs), (u_char *)(regs), REGISTER_BYTES)) 27347262Skarels 27447262Skarels #define gdb_to_regs(fp, regs) \ 27547262Skarels (kgdb_copy((u_char *)(regs), (u_char *)((fp)->f_regs), REGISTER_BYTES)) 27647262Skarels 27747211Skarels static u_long reg_cache[NUM_REGS]; 27855673Smckusick static u_char inbuffer[SL_RPCSIZE+1]; 27955673Smckusick static u_char outbuffer[SL_RPCSIZE]; 28047211Skarels 28147211Skarels /* 28241475Smckusick * This function does all command procesing for interfacing to 28341475Smckusick * a remote gdb. 28441475Smckusick */ 28541475Smckusick int 28647262Skarels kgdb_trap(int type, struct frame *frame) 28741475Smckusick { 28847262Skarels register u_long len; 28947262Skarels u_char *addr; 29047262Skarels register u_char *cp; 29147262Skarels register u_char out, in; 29247262Skarels register int outlen; 29347262Skarels int inlen; 29447211Skarels u_long gdb_regs[NUM_REGS]; 29541475Smckusick 29647211Skarels if (kgdb_dev < 0) { 29741475Smckusick /* not debugging */ 29841475Smckusick return (0); 29947211Skarels } 30047211Skarels if (kgdb_active == 0) { 30147211Skarels if (type != T_TRAP15) { 30247211Skarels /* No debugger active -- let trap handle this. */ 30347211Skarels return (0); 30447211Skarels } 30547471Skarels kgdb_getc = 0; 30647471Skarels for (inlen = 0; constab[inlen].cn_probe; inlen++) 30747471Skarels if (major(constab[inlen].cn_dev) == major(kgdb_dev)) { 30847471Skarels kgdb_getc = constab[inlen].cn_getc; 30947471Skarels kgdb_putc = constab[inlen].cn_putc; 31047471Skarels break; 31147471Skarels } 31247262Skarels if (kgdb_getc == 0 || kgdb_putc == 0) 31347211Skarels return (0); 31447262Skarels /* 31548473Skarels * If the packet that woke us up isn't an exec packet, 31647262Skarels * ignore it since there is no active debugger. Also, 31747262Skarels * we check that it's not an ack to be sure that the 31847262Skarels * remote side doesn't send back a response after the 31947262Skarels * local gdb has exited. Otherwise, the local host 32047262Skarels * could trap into gdb if it's running a gdb kernel too. 32147262Skarels */ 32247262Skarels in = GETC; 32348473Skarels /* 32448473Skarels * If we came in asynchronously through the serial line, 32548473Skarels * the framing character is eaten by the receive interrupt, 32648473Skarels * but if we come in through a synchronous trap (i.e., via 32748473Skarels * kgdb_connect()), we will see the extra character. 32848473Skarels */ 32955673Smckusick if (in == FRAME_START) 33048473Skarels in = GETC; 33148473Skarels 33255673Smckusick /* 33355673Smckusick * Check that this is a debugger exec message. If so, 33455673Smckusick * slurp up the entire message then ack it, and fall 33555673Smckusick * through to the recv loop. 33655673Smckusick */ 33748473Skarels if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0) 33847262Skarels return (0); 33947262Skarels while (GETC != FRAME_END) 34047262Skarels ; 34148473Skarels /* 34248473Skarels * Do the printf *before* we ack the message. This way 34348473Skarels * we won't drop any inbound characters while we're 34448473Skarels * doing the polling printf. 34548473Skarels */ 34648473Skarels printf("kgdb started from device %x\n", kgdb_dev); 34748473Skarels kgdb_send(in | KGDB_ACK, (u_char *)0, 0); 34847211Skarels kgdb_active = 1; 34947211Skarels } 35047211Skarels /* 35147211Skarels * Stick frame regs into our reg cache then tell remote host 35247211Skarels * that an exception has occured. 35347211Skarels */ 35447211Skarels regs_to_gdb(frame, gdb_regs); 35548473Skarels if (type != T_TRAP15) { 35648473Skarels /* 35748473Skarels * Only send an asynchronous SIGNAL message when we hit 35848473Skarels * a breakpoint. Otherwise, we will drop the incoming 35948473Skarels * packet while we output this one (and on entry the other 36048473Skarels * side isn't interested in the SIGNAL type -- if it is, 36148473Skarels * it will have used a signal packet.) 36248473Skarels */ 36348473Skarels outbuffer[0] = computeSignal(type); 36448473Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1); 36548473Skarels } 36641475Smckusick 36747211Skarels while (1) { 36847211Skarels in = kgdb_recv(inbuffer, &inlen); 36947211Skarels if (in == 0 || (in & KGDB_ACK)) 37047211Skarels /* Ignore inbound acks and error conditions. */ 37147211Skarels continue; 37241475Smckusick 37347211Skarels out = in | KGDB_ACK; 37447262Skarels switch (KGDB_CMD(in)) { 37547211Skarels 37647211Skarels case KGDB_SIGNAL: 37747262Skarels /* 37847262Skarels * if this command came from a running gdb, 37947262Skarels * answer it -- the other guy has no way of 38047262Skarels * knowing if we're in or out of this loop 38147262Skarels * when he issues a "remote-signal". (Note 38247262Skarels * that without the length check, we could 38347262Skarels * loop here forever if the ourput line is 38447262Skarels * looped back or the remote host is echoing.) 38547262Skarels */ 38647262Skarels if (inlen == 0) { 38747262Skarels outbuffer[0] = computeSignal(type); 38847262Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1); 38947262Skarels } 39047262Skarels continue; 39147211Skarels 39247211Skarels case KGDB_REG_R: 39347211Skarels case KGDB_REG_R | KGDB_DELTA: 39447211Skarels cp = outbuffer; 39547211Skarels outlen = 0; 39647262Skarels for (len = inbuffer[0]; len < NUM_REGS; ++len) { 39747262Skarels if (reg_cache[len] != gdb_regs[len] || 39847211Skarels (in & KGDB_DELTA) == 0) { 39955673Smckusick if (outlen + 5 > SL_MAXDATA) { 40047211Skarels out |= KGDB_MORE; 40147211Skarels break; 40247211Skarels } 40347262Skarels cp[outlen] = len; 40447262Skarels kgdb_copy((u_char *)&gdb_regs[len], 40547262Skarels &cp[outlen + 1], 4); 40647262Skarels reg_cache[len] = gdb_regs[len]; 40747211Skarels outlen += 5; 40847211Skarels } 40941475Smckusick } 41041475Smckusick break; 41147211Skarels 41247211Skarels case KGDB_REG_W: 41347211Skarels case KGDB_REG_W | KGDB_DELTA: 41447211Skarels cp = inbuffer; 41547262Skarels for (len = 0; len < inlen; len += 5) { 41647262Skarels register int j = cp[len]; 41741475Smckusick 41847262Skarels kgdb_copy(&cp[len + 1], 41947262Skarels (u_char *)&gdb_regs[j], 4); 42047211Skarels reg_cache[j] = gdb_regs[j]; 42141475Smckusick } 42247211Skarels gdb_to_regs(frame, gdb_regs); 42347211Skarels outlen = 0; 42447211Skarels break; 42547211Skarels 42647211Skarels case KGDB_MEM_R: 42747262Skarels len = inbuffer[0]; 42847262Skarels kgdb_copy(&inbuffer[1], (u_char *)&addr, 4); 42955673Smckusick if (len > SL_MAXDATA) { 43047211Skarels outlen = 1; 43147211Skarels outbuffer[0] = E2BIG; 43247262Skarels } else if (!kgdb_acc(addr, len, B_READ)) { 43347211Skarels outlen = 1; 43447211Skarels outbuffer[0] = EFAULT; 43547211Skarels } else { 43647262Skarels outlen = len + 1; 43747211Skarels outbuffer[0] = 0; 43847262Skarels kgdb_copy(addr, &outbuffer[1], len); 43941475Smckusick } 44041475Smckusick break; 44141475Smckusick 44247211Skarels case KGDB_MEM_W: 44347262Skarels len = inlen - 4; 44447262Skarels kgdb_copy(inbuffer, (u_char *)&addr, 4); 44547211Skarels outlen = 1; 44647262Skarels if (!kgdb_acc(addr, len, B_READ)) 44747211Skarels outbuffer[0] = EFAULT; 44847211Skarels else { 44947211Skarels outbuffer[0] = 0; 45047262Skarels if (!kgdb_acc(addr, len, B_WRITE)) 45147262Skarels chgkprot(addr, len, B_WRITE); 45247262Skarels kgdb_copy(&inbuffer[4], addr, len); 45354245Smckusick ICIA(); 45441475Smckusick } 45541475Smckusick break; 45641475Smckusick 45747211Skarels case KGDB_KILL: 45847211Skarels kgdb_active = 0; 45948473Skarels printf("kgdb detached\n"); 46047211Skarels /* fall through */ 46147211Skarels case KGDB_CONT: 46247211Skarels kgdb_send(out, 0, 0); 46347211Skarels frame->f_sr &=~ PSL_T; 46447211Skarels return (1); 46541475Smckusick 46647211Skarels case KGDB_STEP: 46747211Skarels kgdb_send(out, 0, 0); 46847211Skarels frame->f_sr |= PSL_T; 46941475Smckusick return (1); 47041475Smckusick 47148473Skarels case KGDB_EXEC: 47247211Skarels default: 47347211Skarels /* Unknown command. Ack with a null message. */ 47447211Skarels outlen = 0; 47547211Skarels break; 47641475Smckusick } 47747211Skarels /* Send the reply */ 47847211Skarels kgdb_send(out, outbuffer, outlen); 47941475Smckusick } 48041475Smckusick } 48147262Skarels 48247262Skarels /* 48347262Skarels * XXX do kernacc call if safe, otherwise attempt 48447262Skarels * to simulate by simple bounds-checking. 48547262Skarels */ 48647262Skarels kgdb_acc(addr, len, rw) 48747262Skarels caddr_t addr; 48847262Skarels { 48949119Skarels extern char proc0paddr[], kstack[]; /* XXX */ 49047262Skarels extern char *kernel_map; /* XXX! */ 49147262Skarels 49247262Skarels if (kernel_map != NULL) 49347262Skarels return (kernacc(addr, len, rw)); 49447262Skarels if (addr < proc0paddr + UPAGES * NBPG || 49549119Skarels kstack <= addr && addr < kstack + UPAGES * NBPG) 49647262Skarels return (1); 49747262Skarels return (0); 49847262Skarels } 49941475Smckusick #endif 500