141475Smckusick /* 247211Skarels * Copyright (c) 1990 Regents of the University of California. 341475Smckusick * All rights reserved. 441475Smckusick * 541475Smckusick * %sccs.include.redist.c% 641475Smckusick * 7*47471Skarels * @(#)kgdb_stub.c 7.7 (Berkeley) 03/16/91 841475Smckusick */ 941475Smckusick /* 1047211Skarels * "Stub" to allow remote cpu to debug over a serial line using gdb. 1147211Skarels */ 1241475Smckusick #ifdef KGDB 1347211Skarels #ifndef lint 1447262Skarels static char rcsid[] = "$Header: kgdb_stub.c,v 1.9 91/03/08 07:03:13 van Locked $"; 1547211Skarels #endif 1641475Smckusick 1747211Skarels #include "param.h" 1847211Skarels #include "systm.h" 1947211Skarels #include "machine/trap.h" 2047211Skarels #include "machine/cpu.h" 2147211Skarels #include "machine/psl.h" 2247211Skarels #include "machine/reg.h" 2347211Skarels #include "frame.h" 2447211Skarels #include "buf.h" 2547262Skarels #include "cons.h" 2647211Skarels 2747211Skarels #include "kgdb_proto.h" 2847211Skarels #include "machine/remote-sl.h" 2947211Skarels 3041475Smckusick extern int kernacc(); 3141475Smckusick extern void chgkprot(); 3241475Smckusick 3342367Smckusick #ifndef KGDBDEV 3442367Smckusick #define KGDBDEV -1 3542367Smckusick #endif 3642367Smckusick #ifndef KGDBRATE 3742367Smckusick #define KGDBRATE 9600 3842367Smckusick #endif 3942367Smckusick 4042367Smckusick int kgdb_dev = KGDBDEV; /* remote debugging device (-1 if none) */ 4142367Smckusick int kgdb_rate = KGDBRATE; /* remote debugging baud rate */ 4247211Skarels int kgdb_active = 0; /* remote debugging active if != 0 */ 4341475Smckusick int kgdb_debug_init = 0; /* != 0 waits for remote at system init */ 44*47471Skarels int kgdb_debug_panic = 1; /* != 0 waits for remote on panic */ 4547211Skarels int kgdb_debug = 0; 4641475Smckusick 4747211Skarels #define GETC ((*kgdb_getc)(kgdb_dev)) 4847211Skarels #define PUTC(c) ((*kgdb_putc)(kgdb_dev, c)) 4947211Skarels #define PUTESC(c) { \ 5047211Skarels if (c == FRAME_END) { \ 5147211Skarels PUTC(FRAME_ESCAPE); \ 5247211Skarels c = TRANS_FRAME_END; \ 5347211Skarels } else if (c == FRAME_ESCAPE) { \ 5447211Skarels PUTC(FRAME_ESCAPE); \ 5547211Skarels c = TRANS_FRAME_ESCAPE; \ 5647211Skarels } \ 5747211Skarels PUTC(c); \ 5842367Smckusick } 5942367Smckusick 6047211Skarels static int (*kgdb_getc)(); 6147211Skarels static int (*kgdb_putc)(); 6241475Smckusick 6341475Smckusick /* 6447211Skarels * Send a message. The host gets one chance to read it. 6541475Smckusick */ 6647211Skarels static void 6747211Skarels kgdb_send(type, bp, len) 6847211Skarels register u_char type; 6947211Skarels register u_char *bp; 7047211Skarels register int len; 7141475Smckusick { 7247211Skarels register u_char csum; 7347211Skarels register u_char *ep = bp + len; 7441475Smckusick 7547211Skarels csum = type; 7647211Skarels PUTESC(type) 7741475Smckusick 7847211Skarels while (bp < ep) { 7947211Skarels type = *bp++; 8047211Skarels csum += type; 8147211Skarels PUTESC(type) 8247211Skarels } 8347211Skarels csum = -csum; 8447211Skarels PUTESC(csum) 8547211Skarels PUTC(FRAME_END); 8641475Smckusick } 8741475Smckusick 8847211Skarels static int 8947211Skarels kgdb_recv(bp, lenp) 9047211Skarels u_char *bp; 9147211Skarels int *lenp; 9241475Smckusick { 9347211Skarels register u_char c, csum; 9447211Skarels register int escape, len; 9547211Skarels register int type; 9641475Smckusick 9747211Skarels csum = len = escape = 0; 9847211Skarels type = -1; 9947211Skarels while (1) { 10047211Skarels c = GETC; 10147211Skarels switch (c) { 10241475Smckusick 10347211Skarels case FRAME_ESCAPE: 10447211Skarels escape = 1; 10547211Skarels continue; 10641475Smckusick 10747211Skarels case TRANS_FRAME_ESCAPE: 10847211Skarels if (escape) 10947211Skarels c = FRAME_ESCAPE; 11047211Skarels break; 11141475Smckusick 11247211Skarels case TRANS_FRAME_END: 11347211Skarels if (escape) 11447211Skarels c = FRAME_END; 11541475Smckusick break; 11641475Smckusick 11747211Skarels case FRAME_END: 11847211Skarels if (type < 0 || --len < 0) { 11947211Skarels csum = len = escape = 0; 12047211Skarels type = -1; 12147211Skarels continue; 12247211Skarels } 12347211Skarels if (csum != 0) { 12447211Skarels return (0); 12547211Skarels } 12647211Skarels *lenp = len; 12747211Skarels return type; 12841475Smckusick } 12947211Skarels csum += c; 13047211Skarels if (type < 0) { 13147211Skarels type = c; 13247211Skarels escape = 0; 13347211Skarels continue; 13441475Smckusick } 13547211Skarels if (++len > SL_MAXMSG) { 13647211Skarels while (GETC != FRAME_END) 13747211Skarels ; 13847211Skarels return (0); 13947211Skarels } 14047211Skarels *bp++ = c; 14147211Skarels escape = 0; 14241475Smckusick } 14341475Smckusick } 14441475Smckusick 14541475Smckusick /* 14641475Smckusick * Translate a trap number into a unix compatible signal value. 14741475Smckusick * (gdb only understands unix signal numbers). 14841475Smckusick */ 14941475Smckusick static int 15047211Skarels computeSignal(type) 15147211Skarels int type; 15241475Smckusick { 15341475Smckusick int sigval; 15441475Smckusick 15547262Skarels switch (type) { 15641475Smckusick case T_BUSERR: 15741475Smckusick sigval = SIGBUS; 15847211Skarels break; 15941475Smckusick case T_ADDRERR: 16041475Smckusick sigval = SIGBUS; 16147211Skarels break; 16241475Smckusick case T_ILLINST: 16341475Smckusick sigval = SIGILL; 16447211Skarels break; 16541475Smckusick case T_ZERODIV: 16641475Smckusick sigval = SIGFPE; 16747211Skarels break; 16841475Smckusick case T_CHKINST: 16941475Smckusick sigval = SIGFPE; 17047211Skarels break; 17141475Smckusick case T_TRAPVINST: 17241475Smckusick sigval = SIGFPE; 17347211Skarels break; 17441475Smckusick case T_PRIVINST: 17541475Smckusick sigval = SIGILL; 17647211Skarels break; 17741475Smckusick case T_TRACE: 17841475Smckusick sigval = SIGTRAP; 17947211Skarels break; 18041475Smckusick case T_MMUFLT: 18141475Smckusick sigval = SIGSEGV; 18241475Smckusick break; 18341475Smckusick case T_SSIR: 18441475Smckusick sigval = SIGSEGV; 18541475Smckusick break; 18641475Smckusick case T_FMTERR: 18741475Smckusick sigval = SIGILL; 18841475Smckusick break; 18941475Smckusick case T_FPERR: 19041475Smckusick sigval = SIGFPE; 19141475Smckusick break; 19241475Smckusick case T_COPERR: 19341475Smckusick sigval = SIGFPE; 19441475Smckusick break; 19543413Shibler case T_ASTFLT: 19641475Smckusick sigval = SIGINT; 19741475Smckusick break; 19841475Smckusick case T_TRAP15: 19947211Skarels sigval = SIGTRAP; 20041475Smckusick break; 20141475Smckusick default: 20241475Smckusick sigval = SIGEMT; 20341475Smckusick break; 20441475Smckusick } 20541475Smckusick return (sigval); 20641475Smckusick } 20741475Smckusick 20847211Skarels /* 209*47471Skarels * Trap into kgdb to Wait for debugger to connect, 210*47471Skarels * noting on the console why nothing else is going on. 211*47471Skarels */ 212*47471Skarels kgdb_connect(verbose) 213*47471Skarels int verbose; 214*47471Skarels { 215*47471Skarels 216*47471Skarels if (verbose) 217*47471Skarels printf("kgdb waiting..."); 218*47471Skarels /* trap into kgdb */ 219*47471Skarels asm("trap #15;"); 220*47471Skarels if (verbose) 221*47471Skarels printf("connected.\n"); 222*47471Skarels } 223*47471Skarels 224*47471Skarels /* 225*47471Skarels * Decide what to do on panic. 226*47471Skarels */ 227*47471Skarels kgdb_panic() 228*47471Skarels { 229*47471Skarels 230*47471Skarels if (kgdb_active == 0 && kgdb_debug_panic) 231*47471Skarels kgdb_connect(1); 232*47471Skarels } 233*47471Skarels 234*47471Skarels /* 23547211Skarels * Definitions exported from gdb. 23647211Skarels */ 23747211Skarels #define NUM_REGS 18 23847211Skarels #define REGISTER_BYTES ((16+2)*4) 23947211Skarels #define REGISTER_BYTE(N) ((N)*4) 24041475Smckusick 24147211Skarels #define GDB_SR 16 24247211Skarels #define GDB_PC 17 24347211Skarels 24447262Skarels static inline void 24547262Skarels kgdb_copy(register u_char *src, register u_char *dst, register u_int nbytes) 24647211Skarels { 24747262Skarels register u_char *ep = src + nbytes; 24847211Skarels 24947262Skarels while (src < ep) 25047262Skarels *dst++ = *src++; 25147211Skarels } 25247211Skarels 25347262Skarels #define regs_to_gdb(fp, regs) \ 25447262Skarels (kgdb_copy((u_char *)((fp)->f_regs), (u_char *)(regs), REGISTER_BYTES)) 25547262Skarels 25647262Skarels #define gdb_to_regs(fp, regs) \ 25747262Skarels (kgdb_copy((u_char *)(regs), (u_char *)((fp)->f_regs), REGISTER_BYTES)) 25847262Skarels 25947211Skarels static u_long reg_cache[NUM_REGS]; 26047262Skarels static u_char inbuffer[SL_MAXMSG+1]; 26147262Skarels static u_char outbuffer[SL_MAXMSG]; 26247211Skarels 26347211Skarels /* 26441475Smckusick * This function does all command procesing for interfacing to 26541475Smckusick * a remote gdb. 26641475Smckusick */ 26741475Smckusick int 26847262Skarels kgdb_trap(int type, struct frame *frame) 26941475Smckusick { 27047262Skarels register u_long len; 27147262Skarels u_char *addr; 27247262Skarels register u_char *cp; 27347262Skarels register u_char out, in; 27447262Skarels register int outlen; 27547262Skarels int inlen; 27647211Skarels u_long gdb_regs[NUM_REGS]; 27741475Smckusick 27847211Skarels if (kgdb_dev < 0) { 27941475Smckusick /* not debugging */ 28041475Smckusick return (0); 28147211Skarels } 28247211Skarels if (kgdb_active == 0) { 28347211Skarels if (type != T_TRAP15) { 28447211Skarels /* No debugger active -- let trap handle this. */ 28547211Skarels return (0); 28647211Skarels } 287*47471Skarels kgdb_getc = 0; 288*47471Skarels for (inlen = 0; constab[inlen].cn_probe; inlen++) 289*47471Skarels if (major(constab[inlen].cn_dev) == major(kgdb_dev)) { 290*47471Skarels kgdb_getc = constab[inlen].cn_getc; 291*47471Skarels kgdb_putc = constab[inlen].cn_putc; 292*47471Skarels break; 293*47471Skarels } 29447262Skarels if (kgdb_getc == 0 || kgdb_putc == 0) 29547211Skarels return (0); 29647262Skarels /* 29747262Skarels * If the packet that woke us up isn't a signal packet, 29847262Skarels * ignore it since there is no active debugger. Also, 29947262Skarels * we check that it's not an ack to be sure that the 30047262Skarels * remote side doesn't send back a response after the 30147262Skarels * local gdb has exited. Otherwise, the local host 30247262Skarels * could trap into gdb if it's running a gdb kernel too. 30347262Skarels */ 30447262Skarels #ifdef notdef 30547262Skarels in = GETC; 30647262Skarels if (KGDB_CMD(in) != KGDB_SIGNAL || (in & KGDB_ACK) != 0) 30747262Skarels return (0); 30847262Skarels #endif 30947262Skarels while (GETC != FRAME_END) 31047262Skarels ; 31147262Skarels 31247211Skarels kgdb_active = 1; 31347211Skarels } 31447211Skarels /* 31547211Skarels * Stick frame regs into our reg cache then tell remote host 31647211Skarels * that an exception has occured. 31747211Skarels */ 31847211Skarels regs_to_gdb(frame, gdb_regs); 31947211Skarels outbuffer[0] = computeSignal(type); 32047211Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1); 32141475Smckusick 32247211Skarels while (1) { 32347211Skarels in = kgdb_recv(inbuffer, &inlen); 32447211Skarels if (in == 0 || (in & KGDB_ACK)) 32547211Skarels /* Ignore inbound acks and error conditions. */ 32647211Skarels continue; 32741475Smckusick 32847211Skarels out = in | KGDB_ACK; 32947262Skarels switch (KGDB_CMD(in)) { 33047211Skarels 33147211Skarels case KGDB_SIGNAL: 33247262Skarels /* 33347262Skarels * if this command came from a running gdb, 33447262Skarels * answer it -- the other guy has no way of 33547262Skarels * knowing if we're in or out of this loop 33647262Skarels * when he issues a "remote-signal". (Note 33747262Skarels * that without the length check, we could 33847262Skarels * loop here forever if the ourput line is 33947262Skarels * looped back or the remote host is echoing.) 34047262Skarels */ 34147262Skarels if (inlen == 0) { 34247262Skarels outbuffer[0] = computeSignal(type); 34347262Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1); 34447262Skarels } 34547262Skarels continue; 34647211Skarels 34747211Skarels case KGDB_REG_R: 34847211Skarels case KGDB_REG_R | KGDB_DELTA: 34947211Skarels cp = outbuffer; 35047211Skarels outlen = 0; 35147262Skarels for (len = inbuffer[0]; len < NUM_REGS; ++len) { 35247262Skarels if (reg_cache[len] != gdb_regs[len] || 35347211Skarels (in & KGDB_DELTA) == 0) { 35447211Skarels if (outlen + 5 > SL_MAXMSG) { 35547211Skarels out |= KGDB_MORE; 35647211Skarels break; 35747211Skarels } 35847262Skarels cp[outlen] = len; 35947262Skarels kgdb_copy((u_char *)&gdb_regs[len], 36047262Skarels &cp[outlen + 1], 4); 36147262Skarels reg_cache[len] = gdb_regs[len]; 36247211Skarels outlen += 5; 36347211Skarels } 36441475Smckusick } 36541475Smckusick break; 36647211Skarels 36747211Skarels case KGDB_REG_W: 36847211Skarels case KGDB_REG_W | KGDB_DELTA: 36947211Skarels cp = inbuffer; 37047262Skarels for (len = 0; len < inlen; len += 5) { 37147262Skarels register int j = cp[len]; 37241475Smckusick 37347262Skarels kgdb_copy(&cp[len + 1], 37447262Skarels (u_char *)&gdb_regs[j], 4); 37547211Skarels reg_cache[j] = gdb_regs[j]; 37641475Smckusick } 37747211Skarels gdb_to_regs(frame, gdb_regs); 37847211Skarels outlen = 0; 37947211Skarels break; 38047211Skarels 38147211Skarels case KGDB_MEM_R: 38247262Skarels len = inbuffer[0]; 38347262Skarels kgdb_copy(&inbuffer[1], (u_char *)&addr, 4); 38447262Skarels if (len + 1 > SL_MAXMSG) { 38547211Skarels outlen = 1; 38647211Skarels outbuffer[0] = E2BIG; 38747262Skarels } else if (!kgdb_acc(addr, len, B_READ)) { 38847211Skarels outlen = 1; 38947211Skarels outbuffer[0] = EFAULT; 39047211Skarels } else { 39147262Skarels outlen = len + 1; 39247211Skarels outbuffer[0] = 0; 39347262Skarels kgdb_copy(addr, &outbuffer[1], len); 39441475Smckusick } 39541475Smckusick break; 39641475Smckusick 39747211Skarels case KGDB_MEM_W: 39847262Skarels len = inlen - 4; 39947262Skarels kgdb_copy(inbuffer, (u_char *)&addr, 4); 40047211Skarels outlen = 1; 40147262Skarels if (!kgdb_acc(addr, len, B_READ)) 40247211Skarels outbuffer[0] = EFAULT; 40347211Skarels else { 40447211Skarels outbuffer[0] = 0; 40547262Skarels if (!kgdb_acc(addr, len, B_WRITE)) 40647262Skarels chgkprot(addr, len, B_WRITE); 40747262Skarels kgdb_copy(&inbuffer[4], addr, len); 40841475Smckusick } 40941475Smckusick break; 41041475Smckusick 41147211Skarels case KGDB_KILL: 41247211Skarels kgdb_active = 0; 41347211Skarels /* fall through */ 41447211Skarels case KGDB_CONT: 41547211Skarels kgdb_send(out, 0, 0); 41647211Skarels frame->f_sr &=~ PSL_T; 41747211Skarels return (1); 41841475Smckusick 41947211Skarels case KGDB_STEP: 42047211Skarels kgdb_send(out, 0, 0); 42147211Skarels frame->f_sr |= PSL_T; 42241475Smckusick return (1); 42341475Smckusick 42447211Skarels default: 42547211Skarels /* Unknown command. Ack with a null message. */ 42647211Skarels outlen = 0; 42747211Skarels break; 42841475Smckusick } 42947211Skarels /* Send the reply */ 43047211Skarels kgdb_send(out, outbuffer, outlen); 43141475Smckusick } 43241475Smckusick } 43347262Skarels 43447262Skarels /* 43547262Skarels * XXX do kernacc call if safe, otherwise attempt 43647262Skarels * to simulate by simple bounds-checking. 43747262Skarels */ 43847262Skarels kgdb_acc(addr, len, rw) 43947262Skarels caddr_t addr; 44047262Skarels { 44147262Skarels extern char proc0paddr[], u[]; /* XXX! */ 44247262Skarels extern char *kernel_map; /* XXX! */ 44347262Skarels 44447262Skarels if (kernel_map != NULL) 44547262Skarels return (kernacc(addr, len, rw)); 44647262Skarels if (addr < proc0paddr + UPAGES * NBPG || 44747262Skarels u <= addr && addr < u + UPAGES * NBPG) 44847262Skarels return (1); 44947262Skarels return (0); 45047262Skarels } 45141475Smckusick #endif 452