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 *)®s[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 *)®s[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