1/* $NetBSD: kgdb_stub.c,v 1.21 2024/01/07 07:58:35 isaki Exp $ */ 2 3/* 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratories. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 41 */ 42 43/* 44 * "Stub" to allow remote CPU to debug over a serial line using gdb. 45 */ 46 47#include <sys/cdefs.h> 48__KERNEL_RCSID(0, "$NetBSD: kgdb_stub.c,v 1.21 2024/01/07 07:58:35 isaki Exp $"); 49 50#include "opt_kgdb.h" 51 52#ifdef KGDB 53#ifndef lint 54static char rcsid[] = "$NetBSD: kgdb_stub.c,v 1.21 2024/01/07 07:58:35 isaki Exp $"; 55#endif 56 57#include <sys/param.h> 58#include <sys/systm.h> 59 60#include <machine/trap.h> 61#include <machine/cpu.h> 62#include <machine/psl.h> 63#include <machine/reg.h> 64#include <machine/frame.h> 65 66#include <sys/buf.h> 67#include <dev/cons.h> 68 69#include <x68k/x68k/kgdb_proto.h> 70#include <machine/remote-sl.h> 71 72extern int kernacc(); 73extern void chgkprot(); 74 75#ifndef KGDB_DEV 76#define KGDB_DEV NODEV 77#endif 78#ifndef KGDB_DEVRATE 79#define KGDB_DEVRATE 9600 80#endif 81 82dev_t kgdb_dev = KGDB_DEV; /* remote debugging device (NODEV if none) */ 83int kgdb_rate = KGDB_DEVRATE; /* remote debugging baud rate */ 84int kgdb_active = 0; /* remote debugging active if != 0 */ 85int kgdb_debug_init = 0; /* != 0 waits for remote at system init */ 86int kgdb_debug_panic = 1; /* != 0 waits for remote on panic */ 87int kgdb_debug = 0; 88 89#define GETC ((*kgdb_getc)(kgdb_dev)) 90#define PUTC(c) ((*kgdb_putc)(kgdb_dev, c)) 91#define PUTESC(c) { \ 92 if (c == FRAME_END) { \ 93 PUTC(FRAME_ESCAPE); \ 94 c = TRANS_FRAME_END; \ 95 } else if (c == FRAME_ESCAPE) { \ 96 PUTC(FRAME_ESCAPE); \ 97 c = TRANS_FRAME_ESCAPE; \ 98 } else if (c == FRAME_START) { \ 99 PUTC(FRAME_ESCAPE); \ 100 c = TRANS_FRAME_START; \ 101 } \ 102 PUTC(c); \ 103} 104static int (*kgdb_getc)(); 105static int (*kgdb_putc)(); 106 107/* 108 * Send a message. The host gets one chance to read it. 109 */ 110static void 111kgdb_send(u_char type, u_char *bp, int len) 112{ 113 u_char csum; 114 u_char *ep = bp + len; 115 116 PUTC(FRAME_START); 117 PUTESC(type); 118 119 csum = type; 120 while (bp < ep) { 121 type = *bp++; 122 csum += type; 123 PUTESC(type) 124 } 125 csum = -csum; 126 PUTESC(csum) 127 PUTC(FRAME_END); 128} 129 130static int 131kgdb_recv(u_char *bp, int *lenp) 132{ 133 u_char c, csum; 134 int escape, len; 135 int type; 136 137restart: 138 csum = len = escape = 0; 139 type = -1; 140 while (1) { 141 c = GETC; 142 switch (c) { 143 144 case FRAME_ESCAPE: 145 escape = 1; 146 continue; 147 148 case TRANS_FRAME_ESCAPE: 149 if (escape) 150 c = FRAME_ESCAPE; 151 break; 152 153 case TRANS_FRAME_END: 154 if (escape) 155 c = FRAME_END; 156 break; 157 158 case TRANS_FRAME_START: 159 if (escape) 160 c = FRAME_START; 161 break; 162 163 case FRAME_START: 164 goto restart; 165 166 case FRAME_END: 167 if (type < 0 || --len < 0) { 168 csum = len = escape = 0; 169 type = -1; 170 continue; 171 } 172 if (csum != 0) { 173 return (0); 174 } 175 *lenp = len; 176 return type; 177 } 178 csum += c; 179 if (type < 0) { 180 type = c; 181 escape = 0; 182 continue; 183 } 184 if (++len > SL_RPCSIZE) { 185 while (GETC != FRAME_END) 186 ; 187 return (0); 188 } 189 *bp++ = c; 190 escape = 0; 191 } 192} 193 194/* 195 * Translate a trap number into a unix compatible signal value. 196 * (gdb only understands unix signal numbers). 197 */ 198static int 199computeSignal(int type) 200{ 201 int sigval; 202 203 switch (type) { 204 case T_BUSERR: 205 case T_ADDRERR: 206 sigval = SIGBUS; 207 break; 208 case T_ILLINST: 209 case T_PRIVINST: 210 sigval = SIGILL; 211 break; 212 case T_ZERODIV: 213 case T_CHKINST: 214 case T_TRAPVINST: 215 sigval = SIGFPE; 216 break; 217 case T_TRACE: 218 sigval = SIGTRAP; 219 break; 220 case T_MMUFLT: 221 sigval = SIGSEGV; 222 break; 223 case T_SSIR: 224 sigval = SIGSEGV; 225 break; 226 case T_FMTERR: 227 sigval = SIGILL; 228 break; 229 case T_FPERR: 230 case T_COPERR: 231 sigval = SIGFPE; 232 break; 233 case T_ASTFLT: 234 sigval = SIGINT; 235 break; 236 case T_TRAP15: 237 sigval = SIGTRAP; 238 break; 239 default: 240 sigval = SIGEMT; 241 break; 242 } 243 return (sigval); 244} 245 246/* 247 * Trap into kgdb to wait for debugger to connect, 248 * noting on the console why nothing else is going on. 249 */ 250void 251kgdb_connect(int verbose) 252{ 253 254 if (verbose) 255 printf("kgdb waiting..."); 256 /* trap into kgdb */ 257 __asm("trap #15;"); 258 if (verbose) 259 printf("connected.\n"); 260} 261 262/* 263 * Decide what to do on panic. 264 */ 265void 266kgdb_panic(void) 267{ 268 269 if (kgdb_active == 0 && kgdb_debug_panic && kgdb_dev != NODEV) 270 kgdb_connect(1); 271} 272 273/* 274 * Definitions exported from gdb. 275 */ 276#define NUM_REGS 18 277#define REGISTER_BYTES ((16+2)*4) 278#define REGISTER_BYTE(N) ((N)*4) 279 280#define GDB_SR 16 281#define GDB_PC 17 282 283static inline void 284kgdb_copy(u_char *src, u_char *dst, u_int nbytes) 285{ 286 u_char *ep = src + nbytes; 287 288 while (src < ep) 289 *dst++ = *src++; 290} 291 292/* 293 * There is a short pad word between SP (A7) and SR which keeps the 294 * kernel stack long word aligned (note that this is in addition to 295 * the stack adjust short that we treat as the upper half of a longword 296 * SR). We must skip this when copying into and out of gdb. 297 */ 298static inline void 299regs_to_gdb(struct frame *fp, u_long *regs) 300{ 301 kgdb_copy((u_char *)fp->f_regs, (u_char *)regs, 16*4); 302 kgdb_copy((u_char *)&fp->f_stackadj, (u_char *)®s[GDB_SR], 2*4); 303} 304 305static inline void 306gdb_to_regs(struct frame *fp, u_long *regs) 307{ 308 kgdb_copy((u_char *)regs, (u_char *)fp->f_regs, 16*4); 309 kgdb_copy((u_char *)®s[GDB_SR], (u_char *)&fp->f_stackadj, 2*4); 310} 311 312static u_long reg_cache[NUM_REGS]; 313static u_char inbuffer[SL_RPCSIZE+1]; 314static u_char outbuffer[SL_RPCSIZE]; 315 316/* 317 * This function does all command processing for interfacing to 318 * a remote gdb. 319 */ 320int 321kgdb_trap(int type, struct frame *frame) 322{ 323 u_long len; 324 u_char *addr; 325 u_char *cp; 326 u_char out, in; 327 int outlen; 328 int inlen; 329 u_long gdb_regs[NUM_REGS]; 330 331 if ((int)kgdb_dev < 0) { 332 /* not debugging */ 333 return (0); 334 } 335 if (kgdb_active == 0) { 336 if (type != T_TRAP15) { 337 /* No debugger active -- let trap handle this. */ 338 return (0); 339 } 340 kgdb_getc = 0; 341 for (inlen = 0; constab[inlen].cn_probe; inlen++) { 342 if (major(constab[inlen].cn_dev) == major(kgdb_dev)) { 343 kgdb_getc = constab[inlen].cn_getc; 344 kgdb_putc = constab[inlen].cn_putc; 345 break; 346 } 347 } 348 if (kgdb_getc == 0 || kgdb_putc == 0) 349 return (0); 350 /* 351 * If the packet that woke us up isn't an exec packet, 352 * ignore it since there is no active debugger. Also, 353 * we check that it's not an ack to be sure that the 354 * remote side doesn't send back a response after the 355 * local gdb has exited. Otherwise, the local host 356 * could trap into gdb if it's running a gdb kernel too. 357 */ 358 in = GETC; 359 /* 360 * If we came in asynchronously through the serial line, 361 * the framing character is eaten by the receive interrupt, 362 * but if we come in through a synchronous trap (i.e., via 363 * kgdb_connect()), we will see the extra character. 364 */ 365 if (in == FRAME_START) 366 in = GETC; 367 368 /* 369 * Check that this is a debugger exec message. If so, 370 * slurp up the entire message then ack it, and fall 371 * through to the recv loop. 372 */ 373 if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0) 374 return (0); 375 while (GETC != FRAME_END) 376 ; 377 /* 378 * Do the printf *before* we ack the message. This way 379 * we won't drop any inbound characters while we're 380 * doing the polling printf. 381 */ 382 printf("kgdb started from device %x\n", kgdb_dev); 383 kgdb_send(in | KGDB_ACK, (u_char *)0, 0); 384 kgdb_active = 1; 385 } 386 /* 387 * Stick frame regs into our reg cache then tell remote host 388 * that an exception has occurred. 389 */ 390 regs_to_gdb(frame, gdb_regs); 391 if (type != T_TRAP15) { 392 /* 393 * Only send an asynchronous SIGNAL message when we hit 394 * a breakpoint. Otherwise, we will drop the incoming 395 * packet while we output this one (and on entry the other 396 * side isn't interested in the SIGNAL type -- if it is, 397 * it will have used a signal packet.) 398 */ 399 outbuffer[0] = computeSignal(type); 400 kgdb_send(KGDB_SIGNAL, outbuffer, 1); 401 } 402 403 while (1) { 404 in = kgdb_recv(inbuffer, &inlen); 405 if (in == 0 || (in & KGDB_ACK)) 406 /* Ignore inbound acks and error conditions. */ 407 continue; 408 409 out = in | KGDB_ACK; 410 switch (KGDB_CMD(in)) { 411 412 case KGDB_SIGNAL: 413 /* 414 * if this command came from a running gdb, 415 * answer it -- the other guy has no way of 416 * knowing if we're in or out of this loop 417 * when he issues a "remote-signal". (Note 418 * that without the length check, we could 419 * loop here forever if the output line is 420 * looped back or the remote host is echoing.) 421 */ 422 if (inlen == 0) { 423 outbuffer[0] = computeSignal(type); 424 kgdb_send(KGDB_SIGNAL, outbuffer, 1); 425 } 426 continue; 427 428 case KGDB_REG_R: 429 case KGDB_REG_R | KGDB_DELTA: 430 cp = outbuffer; 431 outlen = 0; 432 for (len = inbuffer[0]; len < NUM_REGS; ++len) { 433 if (reg_cache[len] != gdb_regs[len] || 434 (in & KGDB_DELTA) == 0) { 435 if (outlen + 5 > SL_MAXDATA) { 436 out |= KGDB_MORE; 437 break; 438 } 439 cp[outlen] = len; 440 kgdb_copy((u_char *)&gdb_regs[len], 441 &cp[outlen + 1], 4); 442 reg_cache[len] = gdb_regs[len]; 443 outlen += 5; 444 } 445 } 446 break; 447 448 case KGDB_REG_W: 449 case KGDB_REG_W | KGDB_DELTA: 450 cp = inbuffer; 451 for (len = 0; len < inlen; len += 5) { 452 int j = cp[len]; 453 454 kgdb_copy(&cp[len + 1], 455 (u_char *)&gdb_regs[j], 4); 456 reg_cache[j] = gdb_regs[j]; 457 } 458 gdb_to_regs(frame, gdb_regs); 459 outlen = 0; 460 break; 461 462 case KGDB_MEM_R: 463 len = inbuffer[0]; 464 kgdb_copy(&inbuffer[1], (u_char *)&addr, 4); 465 if (len > SL_MAXDATA) { 466 outlen = 1; 467 outbuffer[0] = E2BIG; 468 } else if (!kgdb_acc(addr, len, B_READ)) { 469 outlen = 1; 470 outbuffer[0] = EFAULT; 471 } else { 472 outlen = len + 1; 473 outbuffer[0] = 0; 474 kgdb_copy(addr, &outbuffer[1], len); 475 } 476 break; 477 478 case KGDB_MEM_W: 479 len = inlen - 4; 480 kgdb_copy(inbuffer, (u_char *)&addr, 4); 481 outlen = 1; 482 if (!kgdb_acc(addr, len, B_READ)) 483 outbuffer[0] = EFAULT; 484 else { 485 outbuffer[0] = 0; 486 if (!kgdb_acc(addr, len, B_WRITE)) 487 chgkprot(addr, len, B_WRITE); 488 kgdb_copy(&inbuffer[4], addr, len); 489 ICIA(); 490 } 491 break; 492 493 case KGDB_KILL: 494 kgdb_active = 0; 495 printf("kgdb detached\n"); 496 /* fall through */ 497 case KGDB_CONT: 498 kgdb_send(out, 0, 0); 499 frame->f_sr &=~ PSL_T; 500 return (1); 501 502 case KGDB_STEP: 503 kgdb_send(out, 0, 0); 504 frame->f_sr |= PSL_T; 505 return (1); 506 507 case KGDB_EXEC: 508 default: 509 /* Unknown command. Ack with a null message. */ 510 outlen = 0; 511 break; 512 } 513 /* Send the reply */ 514 kgdb_send(out, outbuffer, outlen); 515 } 516} 517 518/* 519 * XXX do kernacc call if safe, otherwise attempt 520 * to simulate by simple bounds-checking. 521 */ 522int 523kgdb_acc(void *addr, int len, int rw) 524{ 525 extern char kstack[]; /* XXX */ 526 extern char *kernel_map; /* XXX! */ 527 528 if (kernel_map != NULL) 529 return (kernacc(addr, len, rw)); 530 if (addr < uvm_lwp_getuarea(&lwp0) + USPACE || 531 kstack <= addr && addr < kstack + USPACE) 532 return (1); 533 return (0); 534} 535#endif /* KGDB */ 536