141475Smckusick /* 247211Skarels * Copyright (c) 1990 Regents of the University of California. 341475Smckusick * All rights reserved. 441475Smckusick * 5*55673Smckusick * This code is derived from software contributed to Berkeley by 6*55673Smckusick * Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory. 7*55673Smckusick * 841475Smckusick * %sccs.include.redist.c% 941475Smckusick * 10*55673Smckusick * @(#)kgdb_stub.c 7.13 (Berkeley) 07/24/92 1141475Smckusick */ 12*55673Smckusick 1341475Smckusick /* 1447211Skarels * "Stub" to allow remote cpu to debug over a serial line using gdb. 1547211Skarels */ 1641475Smckusick #ifdef KGDB 1747211Skarels #ifndef lint 18*55673Smckusick static char rcsid[] = "$Header: kgdb_stub.c,v 1.2 92/07/23 19:37:50 mccanne Exp $"; 1947211Skarels #endif 2041475Smckusick 2147211Skarels #include "param.h" 2247211Skarels #include "systm.h" 2348473Skarels #include "../include/trap.h" 2448473Skarels #include "../include/cpu.h" 2548473Skarels #include "../include/psl.h" 2648473Skarels #include "../include/reg.h" 2748473Skarels #include "../include/frame.h" 2847211Skarels #include "buf.h" 2953933Shibler #include "hp/dev/cons.h" 3047211Skarels 3147211Skarels #include "kgdb_proto.h" 3247211Skarels #include "machine/remote-sl.h" 3347211Skarels 3441475Smckusick extern int kernacc(); 3541475Smckusick extern void chgkprot(); 3641475Smckusick 3742367Smckusick #ifndef KGDBDEV 3850225Skarels #define KGDBDEV NODEV 3942367Smckusick #endif 4042367Smckusick #ifndef KGDBRATE 4142367Smckusick #define KGDBRATE 9600 4242367Smckusick #endif 4342367Smckusick 4450225Skarels dev_t kgdb_dev = KGDBDEV; /* remote debugging device (NODEV if none) */ 4542367Smckusick int kgdb_rate = KGDBRATE; /* remote debugging baud rate */ 4647211Skarels int kgdb_active = 0; /* remote debugging active if != 0 */ 4741475Smckusick int kgdb_debug_init = 0; /* != 0 waits for remote at system init */ 4847471Skarels int kgdb_debug_panic = 1; /* != 0 waits for remote on panic */ 4947211Skarels int kgdb_debug = 0; 5041475Smckusick 5147211Skarels #define GETC ((*kgdb_getc)(kgdb_dev)) 5247211Skarels #define PUTC(c) ((*kgdb_putc)(kgdb_dev, c)) 5347211Skarels #define PUTESC(c) { \ 5447211Skarels if (c == FRAME_END) { \ 5547211Skarels PUTC(FRAME_ESCAPE); \ 5647211Skarels c = TRANS_FRAME_END; \ 5747211Skarels } else if (c == FRAME_ESCAPE) { \ 5847211Skarels PUTC(FRAME_ESCAPE); \ 5947211Skarels c = TRANS_FRAME_ESCAPE; \ 60*55673Smckusick } else if (c == FRAME_START) { \ 61*55673Smckusick PUTC(FRAME_ESCAPE); \ 62*55673Smckusick c = TRANS_FRAME_START; \ 6347211Skarels } \ 6447211Skarels PUTC(c); \ 6542367Smckusick } 6647211Skarels static int (*kgdb_getc)(); 6747211Skarels static int (*kgdb_putc)(); 6841475Smckusick 6941475Smckusick /* 7047211Skarels * Send a message. The host gets one chance to read it. 7141475Smckusick */ 7247211Skarels static void 7347211Skarels kgdb_send(type, bp, len) 7447211Skarels register u_char type; 7547211Skarels register u_char *bp; 7647211Skarels register int len; 7741475Smckusick { 7847211Skarels register u_char csum; 7947211Skarels register u_char *ep = bp + len; 8041475Smckusick 81*55673Smckusick PUTC(FRAME_START); 82*55673Smckusick PUTESC(type); 83*55673Smckusick 8447211Skarels csum = type; 8547211Skarels while (bp < ep) { 8647211Skarels type = *bp++; 8747211Skarels csum += type; 8847211Skarels PUTESC(type) 8947211Skarels } 9047211Skarels csum = -csum; 9147211Skarels PUTESC(csum) 9247211Skarels PUTC(FRAME_END); 9341475Smckusick } 9441475Smckusick 9547211Skarels static int 9647211Skarels kgdb_recv(bp, lenp) 9747211Skarels u_char *bp; 9847211Skarels int *lenp; 9941475Smckusick { 10047211Skarels register u_char c, csum; 10147211Skarels register int escape, len; 10247211Skarels register int type; 10341475Smckusick 104*55673Smckusick restart: 10547211Skarels csum = len = escape = 0; 10647211Skarels type = -1; 10747211Skarels while (1) { 10847211Skarels c = GETC; 10947211Skarels switch (c) { 11041475Smckusick 11147211Skarels case FRAME_ESCAPE: 11247211Skarels escape = 1; 11347211Skarels continue; 11441475Smckusick 11547211Skarels case TRANS_FRAME_ESCAPE: 11647211Skarels if (escape) 11747211Skarels c = FRAME_ESCAPE; 11847211Skarels break; 11941475Smckusick 12047211Skarels case TRANS_FRAME_END: 12147211Skarels if (escape) 12247211Skarels c = FRAME_END; 12341475Smckusick break; 12441475Smckusick 125*55673Smckusick case TRANS_FRAME_START: 126*55673Smckusick if (escape) 127*55673Smckusick c = FRAME_START; 128*55673Smckusick break; 129*55673Smckusick 130*55673Smckusick case FRAME_START: 131*55673Smckusick goto restart; 132*55673Smckusick 13347211Skarels case FRAME_END: 13447211Skarels if (type < 0 || --len < 0) { 13547211Skarels csum = len = escape = 0; 13647211Skarels type = -1; 13747211Skarels continue; 13847211Skarels } 13947211Skarels if (csum != 0) { 14047211Skarels return (0); 14147211Skarels } 14247211Skarels *lenp = len; 14347211Skarels return type; 14441475Smckusick } 14547211Skarels csum += c; 14647211Skarels if (type < 0) { 14747211Skarels type = c; 14847211Skarels escape = 0; 14947211Skarels continue; 15041475Smckusick } 151*55673Smckusick if (++len > SL_RPCSIZE) { 15247211Skarels while (GETC != FRAME_END) 15347211Skarels ; 15447211Skarels return (0); 15547211Skarels } 15647211Skarels *bp++ = c; 15747211Skarels escape = 0; 15841475Smckusick } 15941475Smckusick } 16041475Smckusick 16141475Smckusick /* 16241475Smckusick * Translate a trap number into a unix compatible signal value. 16341475Smckusick * (gdb only understands unix signal numbers). 16441475Smckusick */ 16541475Smckusick static int 16647211Skarels computeSignal(type) 16747211Skarels int type; 16841475Smckusick { 16941475Smckusick int sigval; 17041475Smckusick 17147262Skarels switch (type) { 17241475Smckusick case T_BUSERR: 17341475Smckusick sigval = SIGBUS; 17447211Skarels break; 17541475Smckusick case T_ADDRERR: 17641475Smckusick sigval = SIGBUS; 17747211Skarels break; 17841475Smckusick case T_ILLINST: 17941475Smckusick sigval = SIGILL; 18047211Skarels break; 18141475Smckusick case T_ZERODIV: 18241475Smckusick sigval = SIGFPE; 18347211Skarels break; 18441475Smckusick case T_CHKINST: 18541475Smckusick sigval = SIGFPE; 18647211Skarels break; 18741475Smckusick case T_TRAPVINST: 18841475Smckusick sigval = SIGFPE; 18947211Skarels break; 19041475Smckusick case T_PRIVINST: 19141475Smckusick sigval = SIGILL; 19247211Skarels break; 19341475Smckusick case T_TRACE: 19441475Smckusick sigval = SIGTRAP; 19547211Skarels break; 19641475Smckusick case T_MMUFLT: 19741475Smckusick sigval = SIGSEGV; 19841475Smckusick break; 19941475Smckusick case T_SSIR: 20041475Smckusick sigval = SIGSEGV; 20141475Smckusick break; 20241475Smckusick case T_FMTERR: 20341475Smckusick sigval = SIGILL; 20441475Smckusick break; 20541475Smckusick case T_FPERR: 20641475Smckusick sigval = SIGFPE; 20741475Smckusick break; 20841475Smckusick case T_COPERR: 20941475Smckusick sigval = SIGFPE; 21041475Smckusick break; 21143413Shibler case T_ASTFLT: 21241475Smckusick sigval = SIGINT; 21341475Smckusick break; 21441475Smckusick case T_TRAP15: 21547211Skarels sigval = SIGTRAP; 21641475Smckusick break; 21741475Smckusick default: 21841475Smckusick sigval = SIGEMT; 21941475Smckusick break; 22041475Smckusick } 22141475Smckusick return (sigval); 22241475Smckusick } 22341475Smckusick 22447211Skarels /* 22548473Skarels * Trap into kgdb to wait for debugger to connect, 22647471Skarels * noting on the console why nothing else is going on. 22747471Skarels */ 22847471Skarels kgdb_connect(verbose) 22947471Skarels int verbose; 23047471Skarels { 23147471Skarels 23247471Skarels if (verbose) 23347471Skarels printf("kgdb waiting..."); 23447471Skarels /* trap into kgdb */ 23547471Skarels asm("trap #15;"); 23647471Skarels if (verbose) 23747471Skarels printf("connected.\n"); 23847471Skarels } 23947471Skarels 24047471Skarels /* 24147471Skarels * Decide what to do on panic. 24247471Skarels */ 24347471Skarels kgdb_panic() 24447471Skarels { 24547471Skarels 24650225Skarels if (kgdb_active == 0 && kgdb_debug_panic && kgdb_dev != NODEV) 24747471Skarels kgdb_connect(1); 24847471Skarels } 24947471Skarels 25047471Skarels /* 25147211Skarels * Definitions exported from gdb. 25247211Skarels */ 25347211Skarels #define NUM_REGS 18 25447211Skarels #define REGISTER_BYTES ((16+2)*4) 25547211Skarels #define REGISTER_BYTE(N) ((N)*4) 25641475Smckusick 25747211Skarels #define GDB_SR 16 25847211Skarels #define GDB_PC 17 25947211Skarels 26047262Skarels static inline void 26147262Skarels kgdb_copy(register u_char *src, register u_char *dst, register u_int nbytes) 26247211Skarels { 26347262Skarels register u_char *ep = src + nbytes; 26447211Skarels 26547262Skarels while (src < ep) 26647262Skarels *dst++ = *src++; 26747211Skarels } 26847211Skarels 26947262Skarels #define regs_to_gdb(fp, regs) \ 27047262Skarels (kgdb_copy((u_char *)((fp)->f_regs), (u_char *)(regs), REGISTER_BYTES)) 27147262Skarels 27247262Skarels #define gdb_to_regs(fp, regs) \ 27347262Skarels (kgdb_copy((u_char *)(regs), (u_char *)((fp)->f_regs), REGISTER_BYTES)) 27447262Skarels 27547211Skarels static u_long reg_cache[NUM_REGS]; 276*55673Smckusick static u_char inbuffer[SL_RPCSIZE+1]; 277*55673Smckusick static u_char outbuffer[SL_RPCSIZE]; 27847211Skarels 27947211Skarels /* 28041475Smckusick * This function does all command procesing for interfacing to 28141475Smckusick * a remote gdb. 28241475Smckusick */ 28341475Smckusick int 28447262Skarels kgdb_trap(int type, struct frame *frame) 28541475Smckusick { 28647262Skarels register u_long len; 28747262Skarels u_char *addr; 28847262Skarels register u_char *cp; 28947262Skarels register u_char out, in; 29047262Skarels register int outlen; 29147262Skarels int inlen; 29247211Skarels u_long gdb_regs[NUM_REGS]; 29341475Smckusick 29447211Skarels if (kgdb_dev < 0) { 29541475Smckusick /* not debugging */ 29641475Smckusick return (0); 29747211Skarels } 29847211Skarels if (kgdb_active == 0) { 29947211Skarels if (type != T_TRAP15) { 30047211Skarels /* No debugger active -- let trap handle this. */ 30147211Skarels return (0); 30247211Skarels } 30347471Skarels kgdb_getc = 0; 30447471Skarels for (inlen = 0; constab[inlen].cn_probe; inlen++) 30547471Skarels if (major(constab[inlen].cn_dev) == major(kgdb_dev)) { 30647471Skarels kgdb_getc = constab[inlen].cn_getc; 30747471Skarels kgdb_putc = constab[inlen].cn_putc; 30847471Skarels break; 30947471Skarels } 31047262Skarels if (kgdb_getc == 0 || kgdb_putc == 0) 31147211Skarels return (0); 31247262Skarels /* 31348473Skarels * If the packet that woke us up isn't an exec packet, 31447262Skarels * ignore it since there is no active debugger. Also, 31547262Skarels * we check that it's not an ack to be sure that the 31647262Skarels * remote side doesn't send back a response after the 31747262Skarels * local gdb has exited. Otherwise, the local host 31847262Skarels * could trap into gdb if it's running a gdb kernel too. 31947262Skarels */ 32047262Skarels in = GETC; 32148473Skarels /* 32248473Skarels * If we came in asynchronously through the serial line, 32348473Skarels * the framing character is eaten by the receive interrupt, 32448473Skarels * but if we come in through a synchronous trap (i.e., via 32548473Skarels * kgdb_connect()), we will see the extra character. 32648473Skarels */ 327*55673Smckusick if (in == FRAME_START) 32848473Skarels in = GETC; 32948473Skarels 330*55673Smckusick /* 331*55673Smckusick * Check that this is a debugger exec message. If so, 332*55673Smckusick * slurp up the entire message then ack it, and fall 333*55673Smckusick * through to the recv loop. 334*55673Smckusick */ 33548473Skarels if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0) 33647262Skarels return (0); 33747262Skarels while (GETC != FRAME_END) 33847262Skarels ; 33948473Skarels /* 34048473Skarels * Do the printf *before* we ack the message. This way 34148473Skarels * we won't drop any inbound characters while we're 34248473Skarels * doing the polling printf. 34348473Skarels */ 34448473Skarels printf("kgdb started from device %x\n", kgdb_dev); 34548473Skarels kgdb_send(in | KGDB_ACK, (u_char *)0, 0); 34647211Skarels kgdb_active = 1; 34747211Skarels } 34847211Skarels /* 34947211Skarels * Stick frame regs into our reg cache then tell remote host 35047211Skarels * that an exception has occured. 35147211Skarels */ 35247211Skarels regs_to_gdb(frame, gdb_regs); 35348473Skarels if (type != T_TRAP15) { 35448473Skarels /* 35548473Skarels * Only send an asynchronous SIGNAL message when we hit 35648473Skarels * a breakpoint. Otherwise, we will drop the incoming 35748473Skarels * packet while we output this one (and on entry the other 35848473Skarels * side isn't interested in the SIGNAL type -- if it is, 35948473Skarels * it will have used a signal packet.) 36048473Skarels */ 36148473Skarels outbuffer[0] = computeSignal(type); 36248473Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1); 36348473Skarels } 36441475Smckusick 36547211Skarels while (1) { 36647211Skarels in = kgdb_recv(inbuffer, &inlen); 36747211Skarels if (in == 0 || (in & KGDB_ACK)) 36847211Skarels /* Ignore inbound acks and error conditions. */ 36947211Skarels continue; 37041475Smckusick 37147211Skarels out = in | KGDB_ACK; 37247262Skarels switch (KGDB_CMD(in)) { 37347211Skarels 37447211Skarels case KGDB_SIGNAL: 37547262Skarels /* 37647262Skarels * if this command came from a running gdb, 37747262Skarels * answer it -- the other guy has no way of 37847262Skarels * knowing if we're in or out of this loop 37947262Skarels * when he issues a "remote-signal". (Note 38047262Skarels * that without the length check, we could 38147262Skarels * loop here forever if the ourput line is 38247262Skarels * looped back or the remote host is echoing.) 38347262Skarels */ 38447262Skarels if (inlen == 0) { 38547262Skarels outbuffer[0] = computeSignal(type); 38647262Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1); 38747262Skarels } 38847262Skarels continue; 38947211Skarels 39047211Skarels case KGDB_REG_R: 39147211Skarels case KGDB_REG_R | KGDB_DELTA: 39247211Skarels cp = outbuffer; 39347211Skarels outlen = 0; 39447262Skarels for (len = inbuffer[0]; len < NUM_REGS; ++len) { 39547262Skarels if (reg_cache[len] != gdb_regs[len] || 39647211Skarels (in & KGDB_DELTA) == 0) { 397*55673Smckusick if (outlen + 5 > SL_MAXDATA) { 39847211Skarels out |= KGDB_MORE; 39947211Skarels break; 40047211Skarels } 40147262Skarels cp[outlen] = len; 40247262Skarels kgdb_copy((u_char *)&gdb_regs[len], 40347262Skarels &cp[outlen + 1], 4); 40447262Skarels reg_cache[len] = gdb_regs[len]; 40547211Skarels outlen += 5; 40647211Skarels } 40741475Smckusick } 40841475Smckusick break; 40947211Skarels 41047211Skarels case KGDB_REG_W: 41147211Skarels case KGDB_REG_W | KGDB_DELTA: 41247211Skarels cp = inbuffer; 41347262Skarels for (len = 0; len < inlen; len += 5) { 41447262Skarels register int j = cp[len]; 41541475Smckusick 41647262Skarels kgdb_copy(&cp[len + 1], 41747262Skarels (u_char *)&gdb_regs[j], 4); 41847211Skarels reg_cache[j] = gdb_regs[j]; 41941475Smckusick } 42047211Skarels gdb_to_regs(frame, gdb_regs); 42147211Skarels outlen = 0; 42247211Skarels break; 42347211Skarels 42447211Skarels case KGDB_MEM_R: 42547262Skarels len = inbuffer[0]; 42647262Skarels kgdb_copy(&inbuffer[1], (u_char *)&addr, 4); 427*55673Smckusick if (len > SL_MAXDATA) { 42847211Skarels outlen = 1; 42947211Skarels outbuffer[0] = E2BIG; 43047262Skarels } else if (!kgdb_acc(addr, len, B_READ)) { 43147211Skarels outlen = 1; 43247211Skarels outbuffer[0] = EFAULT; 43347211Skarels } else { 43447262Skarels outlen = len + 1; 43547211Skarels outbuffer[0] = 0; 43647262Skarels kgdb_copy(addr, &outbuffer[1], len); 43741475Smckusick } 43841475Smckusick break; 43941475Smckusick 44047211Skarels case KGDB_MEM_W: 44147262Skarels len = inlen - 4; 44247262Skarels kgdb_copy(inbuffer, (u_char *)&addr, 4); 44347211Skarels outlen = 1; 44447262Skarels if (!kgdb_acc(addr, len, B_READ)) 44547211Skarels outbuffer[0] = EFAULT; 44647211Skarels else { 44747211Skarels outbuffer[0] = 0; 44847262Skarels if (!kgdb_acc(addr, len, B_WRITE)) 44947262Skarels chgkprot(addr, len, B_WRITE); 45047262Skarels kgdb_copy(&inbuffer[4], addr, len); 45154245Smckusick ICIA(); 45241475Smckusick } 45341475Smckusick break; 45441475Smckusick 45547211Skarels case KGDB_KILL: 45647211Skarels kgdb_active = 0; 45748473Skarels printf("kgdb detached\n"); 45847211Skarels /* fall through */ 45947211Skarels case KGDB_CONT: 46047211Skarels kgdb_send(out, 0, 0); 46147211Skarels frame->f_sr &=~ PSL_T; 46247211Skarels return (1); 46341475Smckusick 46447211Skarels case KGDB_STEP: 46547211Skarels kgdb_send(out, 0, 0); 46647211Skarels frame->f_sr |= PSL_T; 46741475Smckusick return (1); 46841475Smckusick 46948473Skarels case KGDB_EXEC: 47047211Skarels default: 47147211Skarels /* Unknown command. Ack with a null message. */ 47247211Skarels outlen = 0; 47347211Skarels break; 47441475Smckusick } 47547211Skarels /* Send the reply */ 47647211Skarels kgdb_send(out, outbuffer, outlen); 47741475Smckusick } 47841475Smckusick } 47947262Skarels 48047262Skarels /* 48147262Skarels * XXX do kernacc call if safe, otherwise attempt 48247262Skarels * to simulate by simple bounds-checking. 48347262Skarels */ 48447262Skarels kgdb_acc(addr, len, rw) 48547262Skarels caddr_t addr; 48647262Skarels { 48749119Skarels extern char proc0paddr[], kstack[]; /* XXX */ 48847262Skarels extern char *kernel_map; /* XXX! */ 48947262Skarels 49047262Skarels if (kernel_map != NULL) 49147262Skarels return (kernacc(addr, len, rw)); 49247262Skarels if (addr < proc0paddr + UPAGES * NBPG || 49349119Skarels kstack <= addr && addr < kstack + UPAGES * NBPG) 49447262Skarels return (1); 49547262Skarels return (0); 49647262Skarels } 49741475Smckusick #endif 498