141475Smckusick /* 247211Skarels * Copyright (c) 1990 Regents of the University of California. 341475Smckusick * All rights reserved. 441475Smckusick * 5*57149Smckusick * This software was developed by the Computer Systems Engineering group 6*57149Smckusick * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7*57149Smckusick * contributed to Berkeley. 855673Smckusick * 9*57149Smckusick * All advertising materials mentioning features or use of this software 10*57149Smckusick * must display the following acknowledgement: 11*57149Smckusick * This product includes software developed by the University of 12*57149Smckusick * California, Lawrence Berkeley Laboratories. 13*57149Smckusick * 1441475Smckusick * %sccs.include.redist.c% 1541475Smckusick * 16*57149Smckusick * @(#)kgdb_stub.c 7.15 (Berkeley) 12/16/92 1741475Smckusick */ 1855673Smckusick 1941475Smckusick /* 2047211Skarels * "Stub" to allow remote cpu to debug over a serial line using gdb. 2147211Skarels */ 2241475Smckusick #ifdef KGDB 2347211Skarels #ifndef lint 2455673Smckusick static char rcsid[] = "$Header: kgdb_stub.c,v 1.2 92/07/23 19:37:50 mccanne 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 27747262Skarels #define regs_to_gdb(fp, regs) \ 27847262Skarels (kgdb_copy((u_char *)((fp)->f_regs), (u_char *)(regs), REGISTER_BYTES)) 27947262Skarels 28047262Skarels #define gdb_to_regs(fp, regs) \ 28147262Skarels (kgdb_copy((u_char *)(regs), (u_char *)((fp)->f_regs), REGISTER_BYTES)) 28247262Skarels 28347211Skarels static u_long reg_cache[NUM_REGS]; 28455673Smckusick static u_char inbuffer[SL_RPCSIZE+1]; 28555673Smckusick static u_char outbuffer[SL_RPCSIZE]; 28647211Skarels 28747211Skarels /* 28841475Smckusick * This function does all command procesing for interfacing to 28941475Smckusick * a remote gdb. 29041475Smckusick */ 29141475Smckusick int 29247262Skarels kgdb_trap(int type, struct frame *frame) 29341475Smckusick { 29447262Skarels register u_long len; 29547262Skarels u_char *addr; 29647262Skarels register u_char *cp; 29747262Skarels register u_char out, in; 29847262Skarels register int outlen; 29947262Skarels int inlen; 30047211Skarels u_long gdb_regs[NUM_REGS]; 30141475Smckusick 30247211Skarels if (kgdb_dev < 0) { 30341475Smckusick /* not debugging */ 30441475Smckusick return (0); 30547211Skarels } 30647211Skarels if (kgdb_active == 0) { 30747211Skarels if (type != T_TRAP15) { 30847211Skarels /* No debugger active -- let trap handle this. */ 30947211Skarels return (0); 31047211Skarels } 31147471Skarels kgdb_getc = 0; 31247471Skarels for (inlen = 0; constab[inlen].cn_probe; inlen++) 31347471Skarels if (major(constab[inlen].cn_dev) == major(kgdb_dev)) { 31447471Skarels kgdb_getc = constab[inlen].cn_getc; 31547471Skarels kgdb_putc = constab[inlen].cn_putc; 31647471Skarels break; 31747471Skarels } 31847262Skarels if (kgdb_getc == 0 || kgdb_putc == 0) 31947211Skarels return (0); 32047262Skarels /* 32148473Skarels * If the packet that woke us up isn't an exec packet, 32247262Skarels * ignore it since there is no active debugger. Also, 32347262Skarels * we check that it's not an ack to be sure that the 32447262Skarels * remote side doesn't send back a response after the 32547262Skarels * local gdb has exited. Otherwise, the local host 32647262Skarels * could trap into gdb if it's running a gdb kernel too. 32747262Skarels */ 32847262Skarels in = GETC; 32948473Skarels /* 33048473Skarels * If we came in asynchronously through the serial line, 33148473Skarels * the framing character is eaten by the receive interrupt, 33248473Skarels * but if we come in through a synchronous trap (i.e., via 33348473Skarels * kgdb_connect()), we will see the extra character. 33448473Skarels */ 33555673Smckusick if (in == FRAME_START) 33648473Skarels in = GETC; 33748473Skarels 33855673Smckusick /* 33955673Smckusick * Check that this is a debugger exec message. If so, 34055673Smckusick * slurp up the entire message then ack it, and fall 34155673Smckusick * through to the recv loop. 34255673Smckusick */ 34348473Skarels if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0) 34447262Skarels return (0); 34547262Skarels while (GETC != FRAME_END) 34647262Skarels ; 34748473Skarels /* 34848473Skarels * Do the printf *before* we ack the message. This way 34948473Skarels * we won't drop any inbound characters while we're 35048473Skarels * doing the polling printf. 35148473Skarels */ 35248473Skarels printf("kgdb started from device %x\n", kgdb_dev); 35348473Skarels kgdb_send(in | KGDB_ACK, (u_char *)0, 0); 35447211Skarels kgdb_active = 1; 35547211Skarels } 35647211Skarels /* 35747211Skarels * Stick frame regs into our reg cache then tell remote host 35847211Skarels * that an exception has occured. 35947211Skarels */ 36047211Skarels regs_to_gdb(frame, gdb_regs); 36148473Skarels if (type != T_TRAP15) { 36248473Skarels /* 36348473Skarels * Only send an asynchronous SIGNAL message when we hit 36448473Skarels * a breakpoint. Otherwise, we will drop the incoming 36548473Skarels * packet while we output this one (and on entry the other 36648473Skarels * side isn't interested in the SIGNAL type -- if it is, 36748473Skarels * it will have used a signal packet.) 36848473Skarels */ 36948473Skarels outbuffer[0] = computeSignal(type); 37048473Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1); 37148473Skarels } 37241475Smckusick 37347211Skarels while (1) { 37447211Skarels in = kgdb_recv(inbuffer, &inlen); 37547211Skarels if (in == 0 || (in & KGDB_ACK)) 37647211Skarels /* Ignore inbound acks and error conditions. */ 37747211Skarels continue; 37841475Smckusick 37947211Skarels out = in | KGDB_ACK; 38047262Skarels switch (KGDB_CMD(in)) { 38147211Skarels 38247211Skarels case KGDB_SIGNAL: 38347262Skarels /* 38447262Skarels * if this command came from a running gdb, 38547262Skarels * answer it -- the other guy has no way of 38647262Skarels * knowing if we're in or out of this loop 38747262Skarels * when he issues a "remote-signal". (Note 38847262Skarels * that without the length check, we could 38947262Skarels * loop here forever if the ourput line is 39047262Skarels * looped back or the remote host is echoing.) 39147262Skarels */ 39247262Skarels if (inlen == 0) { 39347262Skarels outbuffer[0] = computeSignal(type); 39447262Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1); 39547262Skarels } 39647262Skarels continue; 39747211Skarels 39847211Skarels case KGDB_REG_R: 39947211Skarels case KGDB_REG_R | KGDB_DELTA: 40047211Skarels cp = outbuffer; 40147211Skarels outlen = 0; 40247262Skarels for (len = inbuffer[0]; len < NUM_REGS; ++len) { 40347262Skarels if (reg_cache[len] != gdb_regs[len] || 40447211Skarels (in & KGDB_DELTA) == 0) { 40555673Smckusick if (outlen + 5 > SL_MAXDATA) { 40647211Skarels out |= KGDB_MORE; 40747211Skarels break; 40847211Skarels } 40947262Skarels cp[outlen] = len; 41047262Skarels kgdb_copy((u_char *)&gdb_regs[len], 41147262Skarels &cp[outlen + 1], 4); 41247262Skarels reg_cache[len] = gdb_regs[len]; 41347211Skarels outlen += 5; 41447211Skarels } 41541475Smckusick } 41641475Smckusick break; 41747211Skarels 41847211Skarels case KGDB_REG_W: 41947211Skarels case KGDB_REG_W | KGDB_DELTA: 42047211Skarels cp = inbuffer; 42147262Skarels for (len = 0; len < inlen; len += 5) { 42247262Skarels register int j = cp[len]; 42341475Smckusick 42447262Skarels kgdb_copy(&cp[len + 1], 42547262Skarels (u_char *)&gdb_regs[j], 4); 42647211Skarels reg_cache[j] = gdb_regs[j]; 42741475Smckusick } 42847211Skarels gdb_to_regs(frame, gdb_regs); 42947211Skarels outlen = 0; 43047211Skarels break; 43147211Skarels 43247211Skarels case KGDB_MEM_R: 43347262Skarels len = inbuffer[0]; 43447262Skarels kgdb_copy(&inbuffer[1], (u_char *)&addr, 4); 43555673Smckusick if (len > SL_MAXDATA) { 43647211Skarels outlen = 1; 43747211Skarels outbuffer[0] = E2BIG; 43847262Skarels } else if (!kgdb_acc(addr, len, B_READ)) { 43947211Skarels outlen = 1; 44047211Skarels outbuffer[0] = EFAULT; 44147211Skarels } else { 44247262Skarels outlen = len + 1; 44347211Skarels outbuffer[0] = 0; 44447262Skarels kgdb_copy(addr, &outbuffer[1], len); 44541475Smckusick } 44641475Smckusick break; 44741475Smckusick 44847211Skarels case KGDB_MEM_W: 44947262Skarels len = inlen - 4; 45047262Skarels kgdb_copy(inbuffer, (u_char *)&addr, 4); 45147211Skarels outlen = 1; 45247262Skarels if (!kgdb_acc(addr, len, B_READ)) 45347211Skarels outbuffer[0] = EFAULT; 45447211Skarels else { 45547211Skarels outbuffer[0] = 0; 45647262Skarels if (!kgdb_acc(addr, len, B_WRITE)) 45747262Skarels chgkprot(addr, len, B_WRITE); 45847262Skarels kgdb_copy(&inbuffer[4], addr, len); 45954245Smckusick ICIA(); 46041475Smckusick } 46141475Smckusick break; 46241475Smckusick 46347211Skarels case KGDB_KILL: 46447211Skarels kgdb_active = 0; 46548473Skarels printf("kgdb detached\n"); 46647211Skarels /* fall through */ 46747211Skarels case KGDB_CONT: 46847211Skarels kgdb_send(out, 0, 0); 46947211Skarels frame->f_sr &=~ PSL_T; 47047211Skarels return (1); 47141475Smckusick 47247211Skarels case KGDB_STEP: 47347211Skarels kgdb_send(out, 0, 0); 47447211Skarels frame->f_sr |= PSL_T; 47541475Smckusick return (1); 47641475Smckusick 47748473Skarels case KGDB_EXEC: 47847211Skarels default: 47947211Skarels /* Unknown command. Ack with a null message. */ 48047211Skarels outlen = 0; 48147211Skarels break; 48241475Smckusick } 48347211Skarels /* Send the reply */ 48447211Skarels kgdb_send(out, outbuffer, outlen); 48541475Smckusick } 48641475Smckusick } 48747262Skarels 48847262Skarels /* 48947262Skarels * XXX do kernacc call if safe, otherwise attempt 49047262Skarels * to simulate by simple bounds-checking. 49147262Skarels */ 49247262Skarels kgdb_acc(addr, len, rw) 49347262Skarels caddr_t addr; 49447262Skarels { 49549119Skarels extern char proc0paddr[], kstack[]; /* XXX */ 49647262Skarels extern char *kernel_map; /* XXX! */ 49747262Skarels 49847262Skarels if (kernel_map != NULL) 49947262Skarels return (kernacc(addr, len, rw)); 50047262Skarels if (addr < proc0paddr + UPAGES * NBPG || 50149119Skarels kstack <= addr && addr < kstack + UPAGES * NBPG) 50247262Skarels return (1); 50347262Skarels return (0); 50447262Skarels } 50541475Smckusick #endif 506