Home | History | Annotate | Line # | Download | only in x68k
      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
     54 static 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 
     72 extern int kernacc();
     73 extern 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 
     82 dev_t kgdb_dev = KGDB_DEV;	/* remote debugging device (NODEV if none) */
     83 int kgdb_rate = KGDB_DEVRATE;	/* remote debugging baud rate */
     84 int kgdb_active = 0;            /* remote debugging active if != 0 */
     85 int kgdb_debug_init = 0;	/* != 0 waits for remote at system init */
     86 int kgdb_debug_panic = 1;	/* != 0 waits for remote on panic */
     87 int 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 }
    104 static int (*kgdb_getc)();
    105 static int (*kgdb_putc)();
    106 
    107 /*
    108  * Send a message.  The host gets one chance to read it.
    109  */
    110 static void
    111 kgdb_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 
    130 static int
    131 kgdb_recv(u_char *bp, int *lenp)
    132 {
    133 	u_char c, csum;
    134 	int escape, len;
    135 	int type;
    136 
    137 restart:
    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  */
    198 static int
    199 computeSignal(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  */
    250 void
    251 kgdb_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  */
    265 void
    266 kgdb_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 
    283 static inline void
    284 kgdb_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  */
    298 static inline void
    299 regs_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 *)&regs[GDB_SR], 2*4);
    303 }
    304 
    305 static inline void
    306 gdb_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 *)&regs[GDB_SR], (u_char *)&fp->f_stackadj, 2*4);
    310 }
    311 
    312 static u_long reg_cache[NUM_REGS];
    313 static u_char inbuffer[SL_RPCSIZE+1];
    314 static u_char outbuffer[SL_RPCSIZE];
    315 
    316 /*
    317  * This function does all command processing for interfacing to
    318  * a remote gdb.
    319  */
    320 int
    321 kgdb_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  */
    522 int
    523 kgdb_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