141475Smckusick /* 2*47211Skarels * Copyright (c) 1990 Regents of the University of California. 341475Smckusick * All rights reserved. 441475Smckusick * 541475Smckusick * %sccs.include.redist.c% 641475Smckusick * 7*47211Skarels * @(#)kgdb_stub.c 7.5 (Berkeley) 03/11/91 841475Smckusick */ 941475Smckusick /* 10*47211Skarels * "Stub" to allow remote cpu to debug over a serial line using gdb. 11*47211Skarels */ 1241475Smckusick #ifdef KGDB 13*47211Skarels #ifndef lint 14*47211Skarels static char rcsid[] = "$Header: kgdb_stub.c,v 1.6 91/03/05 01:15:03 van Exp $"; 15*47211Skarels #endif 1641475Smckusick 17*47211Skarels #include "param.h" 18*47211Skarels #include "systm.h" 19*47211Skarels #include "machine/trap.h" 20*47211Skarels #include "machine/cpu.h" 21*47211Skarels #include "machine/psl.h" 22*47211Skarels #include "machine/reg.h" 23*47211Skarels #include "frame.h" 24*47211Skarels #include "buf.h" 25*47211Skarels #include "../hp300/cons.h" 26*47211Skarels 27*47211Skarels #include "kgdb_proto.h" 28*47211Skarels #include "machine/remote-sl.h" 29*47211Skarels 3041475Smckusick extern void printf(); 3141475Smckusick extern void bcopy(); 3241475Smckusick extern int kernacc(); 3341475Smckusick extern void chgkprot(); 3441475Smckusick 35*47211Skarels /* (XXX from trap.c) user-mode flag in type */ 36*47211Skarels #define USER 0x20 3741475Smckusick 3842367Smckusick #ifndef KGDBDEV 3942367Smckusick #define KGDBDEV -1 4042367Smckusick #endif 4142367Smckusick #ifndef KGDBRATE 4242367Smckusick #define KGDBRATE 9600 4342367Smckusick #endif 4442367Smckusick 4542367Smckusick int kgdb_dev = KGDBDEV; /* remote debugging device (-1 if none) */ 4642367Smckusick int kgdb_rate = KGDBRATE; /* remote debugging baud rate */ 47*47211Skarels int kgdb_active = 0; /* remote debugging active if != 0 */ 4841475Smckusick int kgdb_debug_init = 0; /* != 0 waits for remote at system init */ 49*47211Skarels int kgdb_debug = 0; 5041475Smckusick 51*47211Skarels #define GETC ((*kgdb_getc)(kgdb_dev)) 52*47211Skarels #define PUTC(c) ((*kgdb_putc)(kgdb_dev, c)) 53*47211Skarels #define PUTESC(c) { \ 54*47211Skarels if (c == FRAME_END) { \ 55*47211Skarels PUTC(FRAME_ESCAPE); \ 56*47211Skarels c = TRANS_FRAME_END; \ 57*47211Skarels } else if (c == FRAME_ESCAPE) { \ 58*47211Skarels PUTC(FRAME_ESCAPE); \ 59*47211Skarels c = TRANS_FRAME_ESCAPE; \ 60*47211Skarels } \ 61*47211Skarels PUTC(c); \ 6242367Smckusick } 6342367Smckusick 64*47211Skarels static int (*kgdb_getc)(); 65*47211Skarels static int (*kgdb_putc)(); 6641475Smckusick 6741475Smckusick /* 68*47211Skarels * Send a message. The host gets one chance to read it. 6941475Smckusick */ 70*47211Skarels static void 71*47211Skarels kgdb_send(type, bp, len) 72*47211Skarels register u_char type; 73*47211Skarels register u_char *bp; 74*47211Skarels register int len; 7541475Smckusick { 76*47211Skarels register u_char csum; 77*47211Skarels register u_char *ep = bp + len; 7841475Smckusick 79*47211Skarels csum = type; 80*47211Skarels PUTESC(type) 8141475Smckusick 82*47211Skarels while (bp < ep) { 83*47211Skarels type = *bp++; 84*47211Skarels csum += type; 85*47211Skarels PUTESC(type) 86*47211Skarels } 87*47211Skarels csum = -csum; 88*47211Skarels PUTESC(csum) 89*47211Skarels PUTC(FRAME_END); 9041475Smckusick } 9141475Smckusick 92*47211Skarels static int 93*47211Skarels kgdb_recv(bp, lenp) 94*47211Skarels u_char *bp; 95*47211Skarels int *lenp; 9641475Smckusick { 97*47211Skarels register u_char c, csum; 98*47211Skarels register int escape, len; 99*47211Skarels register int type; 10041475Smckusick 101*47211Skarels csum = len = escape = 0; 102*47211Skarels type = -1; 103*47211Skarels while (1) { 104*47211Skarels c = GETC; 105*47211Skarels switch (c) { 10641475Smckusick 107*47211Skarels case FRAME_ESCAPE: 108*47211Skarels escape = 1; 109*47211Skarels continue; 11041475Smckusick 111*47211Skarels case TRANS_FRAME_ESCAPE: 112*47211Skarels if (escape) 113*47211Skarels c = FRAME_ESCAPE; 114*47211Skarels break; 11541475Smckusick 116*47211Skarels case TRANS_FRAME_END: 117*47211Skarels if (escape) 118*47211Skarels c = FRAME_END; 11941475Smckusick break; 12041475Smckusick 121*47211Skarels case FRAME_END: 122*47211Skarels if (type < 0 || --len < 0) { 123*47211Skarels csum = len = escape = 0; 124*47211Skarels type = -1; 125*47211Skarels continue; 126*47211Skarels } 127*47211Skarels if (csum != 0) { 128*47211Skarels return (0); 129*47211Skarels } 130*47211Skarels *lenp = len; 131*47211Skarels return type; 13241475Smckusick } 133*47211Skarels csum += c; 134*47211Skarels if (type < 0) { 135*47211Skarels type = c; 136*47211Skarels escape = 0; 137*47211Skarels continue; 13841475Smckusick } 139*47211Skarels if (++len > SL_MAXMSG) { 140*47211Skarels while (GETC != FRAME_END) 141*47211Skarels ; 142*47211Skarels return (0); 143*47211Skarels } 144*47211Skarels *bp++ = c; 145*47211Skarels escape = 0; 14641475Smckusick } 14741475Smckusick } 14841475Smckusick 14941475Smckusick /* 15041475Smckusick * Translate a trap number into a unix compatible signal value. 15141475Smckusick * (gdb only understands unix signal numbers). 15241475Smckusick */ 15341475Smckusick static int 154*47211Skarels computeSignal(type) 155*47211Skarels int type; 15641475Smckusick { 15741475Smckusick int sigval; 15841475Smckusick 15941475Smckusick switch (type &~ USER) { 16041475Smckusick case T_BUSERR: 16141475Smckusick sigval = SIGBUS; 162*47211Skarels break; 16341475Smckusick case T_ADDRERR: 16441475Smckusick sigval = SIGBUS; 165*47211Skarels break; 16641475Smckusick case T_ILLINST: 16741475Smckusick sigval = SIGILL; 168*47211Skarels break; 16941475Smckusick case T_ZERODIV: 17041475Smckusick sigval = SIGFPE; 171*47211Skarels break; 17241475Smckusick case T_CHKINST: 17341475Smckusick sigval = SIGFPE; 174*47211Skarels break; 17541475Smckusick case T_TRAPVINST: 17641475Smckusick sigval = SIGFPE; 177*47211Skarels break; 17841475Smckusick case T_PRIVINST: 17941475Smckusick sigval = SIGILL; 180*47211Skarels break; 18141475Smckusick case T_TRACE: 18241475Smckusick sigval = SIGTRAP; 183*47211Skarels break; 18441475Smckusick case T_MMUFLT: 18541475Smckusick sigval = SIGSEGV; 18641475Smckusick break; 18741475Smckusick case T_SSIR: 18841475Smckusick sigval = SIGSEGV; 18941475Smckusick break; 19041475Smckusick case T_FMTERR: 19141475Smckusick sigval = SIGILL; 19241475Smckusick break; 19341475Smckusick case T_FPERR: 19441475Smckusick sigval = SIGFPE; 19541475Smckusick break; 19641475Smckusick case T_COPERR: 19741475Smckusick sigval = SIGFPE; 19841475Smckusick break; 19943413Shibler case T_ASTFLT: 20041475Smckusick sigval = SIGINT; 20141475Smckusick break; 20241475Smckusick case T_TRAP15: 203*47211Skarels sigval = SIGTRAP; 20441475Smckusick break; 20541475Smckusick default: 20641475Smckusick sigval = SIGEMT; 20741475Smckusick break; 20841475Smckusick } 20941475Smckusick return (sigval); 21041475Smckusick } 21141475Smckusick 212*47211Skarels /* 213*47211Skarels * Definitions exported from gdb. 214*47211Skarels */ 215*47211Skarels #define NUM_REGS 18 216*47211Skarels #define REGISTER_BYTES ((16+2)*4) 217*47211Skarels #define REGISTER_BYTE(N) ((N)*4) 21841475Smckusick 219*47211Skarels #define GDB_SR 16 220*47211Skarels #define GDB_PC 17 221*47211Skarels 22241475Smckusick /* 223*47211Skarels * # of additional bytes in 680x0 exception frame format n. 224*47211Skarels */ 225*47211Skarels static int frame_bytes[16] = { 226*47211Skarels 0, 0, sizeof(struct fmt2), 0, 227*47211Skarels 0, 0, 0, 0, 228*47211Skarels 0, sizeof(struct fmt9), sizeof(struct fmtA), sizeof(struct fmtB), 229*47211Skarels 0, 0, 0, 0 230*47211Skarels }; 231*47211Skarels 232*47211Skarels /* 233*47211Skarels * Translate the values stored in the kernel frame struct to the format 234*47211Skarels * understood by gdb. 235*47211Skarels */ 236*47211Skarels static void 237*47211Skarels regs_to_gdb(fp, gdb_regs) 238*47211Skarels struct frame *fp; 239*47211Skarels u_long *gdb_regs; 240*47211Skarels { 241*47211Skarels bcopy((caddr_t)fp->f_regs, (caddr_t)gdb_regs, sizeof(fp->f_regs) + 8); 242*47211Skarels } 243*47211Skarels 244*47211Skarels /* 245*47211Skarels * Convert gdb register values to kernel format. 246*47211Skarels */ 247*47211Skarels static void 248*47211Skarels gdb_to_regs(fp, gdb_regs) 249*47211Skarels struct frame *fp; 250*47211Skarels u_long *gdb_regs; 251*47211Skarels { 252*47211Skarels bcopy((caddr_t)gdb_regs, (caddr_t)fp->f_regs, sizeof(fp->f_regs) - 4); 253*47211Skarels fp->f_sr = gdb_regs[GDB_SR]; 254*47211Skarels fp->f_pc = gdb_regs[GDB_PC]; 255*47211Skarels } 256*47211Skarels 257*47211Skarels static u_long reg_cache[NUM_REGS]; 258*47211Skarels 259*47211Skarels /* 26041475Smckusick * This function does all command procesing for interfacing to 26141475Smckusick * a remote gdb. 26241475Smckusick */ 26341475Smckusick int 26441475Smckusick kgdb_trap(int type, unsigned code, unsigned v, struct frame *frame) 26541475Smckusick { 266*47211Skarels int i; 267*47211Skarels u_long length; 268*47211Skarels caddr_t addr; 269*47211Skarels u_char *cp; 270*47211Skarels int out, in; 271*47211Skarels int inlen, outlen; 272*47211Skarels static u_char inbuffer[SL_MAXMSG+1]; 273*47211Skarels static u_char outbuffer[SL_MAXMSG]; 274*47211Skarels u_long gdb_regs[NUM_REGS]; 27541475Smckusick 276*47211Skarels if (kgdb_dev < 0) { 27741475Smckusick /* not debugging */ 27841475Smckusick return (0); 279*47211Skarels } 280*47211Skarels if (kgdb_active == 0) { 281*47211Skarels if (type != T_TRAP15) { 282*47211Skarels /* No debugger active -- let trap handle this. */ 283*47211Skarels return (0); 284*47211Skarels } 285*47211Skarels kgdb_getc = constab[major(kgdb_dev)].cn_getc; 286*47211Skarels kgdb_putc = constab[major(kgdb_dev)].cn_putc; 287*47211Skarels if (kgdb_getc == 0 || kgdb_putc == 0) { 288*47211Skarels return (0); 289*47211Skarels } 290*47211Skarels kgdb_active = 1; 291*47211Skarels } 292*47211Skarels /* 293*47211Skarels * Stick frame regs into our reg cache then tell remote host 294*47211Skarels * that an exception has occured. 295*47211Skarels */ 296*47211Skarels if ((type & USER) == 0) 297*47211Skarels /* 298*47211Skarels * After a kernel mode trap, the saved sp points at the 299*47211Skarels * PSW and is useless. The correct saved sp should be 300*47211Skarels * the top of the frame. 301*47211Skarels */ 302*47211Skarels frame->f_regs[SP] = (int)&frame->F_u + 303*47211Skarels frame_bytes[frame->f_format]; 304*47211Skarels regs_to_gdb(frame, gdb_regs); 30541475Smckusick 306*47211Skarels outbuffer[0] = computeSignal(type); 307*47211Skarels kgdb_send(KGDB_SIGNAL, outbuffer, 1); 30841475Smckusick 309*47211Skarels while (1) { 310*47211Skarels in = kgdb_recv(inbuffer, &inlen); 311*47211Skarels if (in == 0 || (in & KGDB_ACK)) 312*47211Skarels /* Ignore inbound acks and error conditions. */ 313*47211Skarels continue; 31441475Smckusick 315*47211Skarels out = in | KGDB_ACK; 316*47211Skarels switch (in) { 317*47211Skarels 318*47211Skarels case KGDB_SIGNAL: 319*47211Skarels outbuffer[0] = computeSignal(type); 320*47211Skarels outlen = 1; 32141475Smckusick break; 322*47211Skarels 323*47211Skarels case KGDB_REG_R: 324*47211Skarels case KGDB_REG_R | KGDB_DELTA: 325*47211Skarels cp = outbuffer; 326*47211Skarels outlen = 0; 327*47211Skarels for (i = inbuffer[0]; i < NUM_REGS; ++i) { 328*47211Skarels if (reg_cache[i] != gdb_regs[i] || 329*47211Skarels (in & KGDB_DELTA) == 0) { 330*47211Skarels if (outlen + 5 > SL_MAXMSG) { 331*47211Skarels out |= KGDB_MORE; 332*47211Skarels break; 333*47211Skarels } 334*47211Skarels cp[outlen] = i; 335*47211Skarels bcopy(&gdb_regs[i], 336*47211Skarels &cp[outlen + 1], 4); 337*47211Skarels outlen += 5; 338*47211Skarels reg_cache[i] = gdb_regs[i]; 339*47211Skarels } 34041475Smckusick } 34141475Smckusick break; 342*47211Skarels 343*47211Skarels case KGDB_REG_W: 344*47211Skarels case KGDB_REG_W | KGDB_DELTA: 345*47211Skarels cp = inbuffer; 346*47211Skarels for (i = 0; i < inlen; i += 5) { 347*47211Skarels register int j = cp[i]; 34841475Smckusick 349*47211Skarels bcopy(&cp[i + 1], &gdb_regs[j], 4); 350*47211Skarels reg_cache[j] = gdb_regs[j]; 35141475Smckusick } 352*47211Skarels gdb_to_regs(frame, gdb_regs); 353*47211Skarels outlen = 0; 354*47211Skarels break; 355*47211Skarels 356*47211Skarels case KGDB_MEM_R: 357*47211Skarels length = inbuffer[0]; 358*47211Skarels bcopy(&inbuffer[1], &addr, 4); 359*47211Skarels if (length + 1 > SL_MAXMSG) { 360*47211Skarels outlen = 1; 361*47211Skarels outbuffer[0] = E2BIG; 362*47211Skarels } else if (!kernacc(addr, length, B_READ)) { 363*47211Skarels outlen = 1; 364*47211Skarels outbuffer[0] = EFAULT; 365*47211Skarels } else { 366*47211Skarels outlen = length + 1; 367*47211Skarels outbuffer[0] = 0; 368*47211Skarels bcopy(addr, &outbuffer[1], length); 36941475Smckusick } 37041475Smckusick break; 37141475Smckusick 372*47211Skarels case KGDB_MEM_W: 373*47211Skarels length = inlen - 4; 374*47211Skarels bcopy(inbuffer, &addr, 4); 375*47211Skarels outlen = 1; 376*47211Skarels if (!kernacc(addr, length, B_READ)) 377*47211Skarels outbuffer[0] = EFAULT; 378*47211Skarels else { 379*47211Skarels outbuffer[0] = 0; 380*47211Skarels if (!kernacc(addr, length, B_WRITE)) 381*47211Skarels chgkprot(addr, length, B_WRITE); 382*47211Skarels bcopy(&inbuffer[4], addr, length); 38341475Smckusick } 38441475Smckusick break; 38541475Smckusick 386*47211Skarels case KGDB_KILL: 387*47211Skarels kgdb_active = 0; 388*47211Skarels /* fall through */ 389*47211Skarels case KGDB_CONT: 390*47211Skarels kgdb_send(out, 0, 0); 391*47211Skarels frame->f_sr &=~ PSL_T; 392*47211Skarels return (1); 39341475Smckusick 394*47211Skarels case KGDB_STEP: 395*47211Skarels kgdb_send(out, 0, 0); 396*47211Skarels frame->f_sr |= PSL_T; 39741475Smckusick return (1); 39841475Smckusick 399*47211Skarels default: 400*47211Skarels /* Unknown command. Ack with a null message. */ 401*47211Skarels outlen = 0; 402*47211Skarels break; 40341475Smckusick } 404*47211Skarels /* Send the reply */ 405*47211Skarels kgdb_send(out, outbuffer, outlen); 40641475Smckusick } 40741475Smckusick } 40841475Smckusick #endif 409