xref: /netbsd-src/sys/arch/x68k/x68k/kgdb_stub.c (revision 6b664a713479c31d4f17b38b42182a5d5fa21802)
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
kgdb_send(u_char type,u_char * bp,int len)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
kgdb_recv(u_char * bp,int * lenp)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
computeSignal(int type)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
kgdb_connect(int verbose)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
kgdb_panic(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
kgdb_copy(u_char * src,u_char * dst,u_int nbytes)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
regs_to_gdb(struct frame * fp,u_long * regs)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
gdb_to_regs(struct frame * fp,u_long * regs)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
kgdb_trap(int type,struct frame * frame)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
kgdb_acc(void * addr,int len,int rw)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