xref: /original-bsd/sys/hp300/hp300/kgdb_stub.c (revision be1f24e8)
1 /*
2  * Copyright (c) 1990 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)kgdb_stub.c	7.14 (Berkeley) 10/11/92
11  */
12 
13 /*
14  * "Stub" to allow remote cpu to debug over a serial line using gdb.
15  */
16 #ifdef KGDB
17 #ifndef lint
18 static char rcsid[] = "$Header: kgdb_stub.c,v 1.2 92/07/23 19:37:50 mccanne Exp $";
19 #endif
20 
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 
24 #include <machine/trap.h>
25 #include <machine/cpu.h>
26 #include <machine/psl.h>
27 #include <machine/reg.h>
28 #include <machine/frame.h>
29 
30 #include <sys/buf.h>
31 #include <hp/dev/cons.h>
32 
33 #include <hp300/hp300/kgdb_proto.h>
34 #include <machine/remote-sl.h>
35 
36 extern int kernacc();
37 extern void chgkprot();
38 
39 #ifndef KGDBDEV
40 #define KGDBDEV NODEV
41 #endif
42 #ifndef KGDBRATE
43 #define KGDBRATE 9600
44 #endif
45 
46 dev_t kgdb_dev = KGDBDEV;	/* remote debugging device (NODEV if none) */
47 int kgdb_rate = KGDBRATE;	/* remote debugging baud rate */
48 int kgdb_active = 0;            /* remote debugging active if != 0 */
49 int kgdb_debug_init = 0;	/* != 0 waits for remote at system init */
50 int kgdb_debug_panic = 1;	/* != 0 waits for remote on panic */
51 int kgdb_debug = 0;
52 
53 #define GETC	((*kgdb_getc)(kgdb_dev))
54 #define PUTC(c)	((*kgdb_putc)(kgdb_dev, c))
55 #define PUTESC(c) { \
56 	if (c == FRAME_END) { \
57 		PUTC(FRAME_ESCAPE); \
58 		c = TRANS_FRAME_END; \
59 	} else if (c == FRAME_ESCAPE) { \
60 		PUTC(FRAME_ESCAPE); \
61 		c = TRANS_FRAME_ESCAPE; \
62 	} else if (c == FRAME_START) { \
63 		PUTC(FRAME_ESCAPE); \
64 		c = TRANS_FRAME_START; \
65 	} \
66 	PUTC(c); \
67 }
68 static int (*kgdb_getc)();
69 static int (*kgdb_putc)();
70 
71 /*
72  * Send a message.  The host gets one chance to read it.
73  */
74 static void
75 kgdb_send(type, bp, len)
76 	register u_char type;
77 	register u_char *bp;
78 	register int len;
79 {
80 	register u_char csum;
81 	register u_char *ep = bp + len;
82 
83 	PUTC(FRAME_START);
84 	PUTESC(type);
85 
86 	csum = type;
87 	while (bp < ep) {
88 		type = *bp++;
89 		csum += type;
90 		PUTESC(type)
91 	}
92 	csum = -csum;
93 	PUTESC(csum)
94 	PUTC(FRAME_END);
95 }
96 
97 static int
98 kgdb_recv(bp, lenp)
99 	u_char *bp;
100 	int *lenp;
101 {
102 	register u_char c, csum;
103 	register int escape, len;
104 	register int type;
105 
106 restart:
107 	csum = len = escape = 0;
108 	type = -1;
109 	while (1) {
110 		c = GETC;
111 		switch (c) {
112 
113 		case FRAME_ESCAPE:
114 			escape = 1;
115 			continue;
116 
117 		case TRANS_FRAME_ESCAPE:
118 			if (escape)
119 				c = FRAME_ESCAPE;
120 			break;
121 
122 		case TRANS_FRAME_END:
123 			if (escape)
124 				c = FRAME_END;
125 			break;
126 
127 		case TRANS_FRAME_START:
128 			if (escape)
129 				c = FRAME_START;
130 			break;
131 
132 		case FRAME_START:
133 			goto restart;
134 
135 		case FRAME_END:
136 			if (type < 0 || --len < 0) {
137 				csum = len = escape = 0;
138 				type = -1;
139 				continue;
140 			}
141 			if (csum != 0) {
142 				return (0);
143 			}
144 			*lenp = len;
145 			return type;
146 		}
147 		csum += c;
148 		if (type < 0) {
149 			type = c;
150 			escape = 0;
151 			continue;
152 		}
153 		if (++len > SL_RPCSIZE) {
154 			while (GETC != FRAME_END)
155 				;
156 			return (0);
157 		}
158 		*bp++ = c;
159 		escape = 0;
160 	}
161 }
162 
163 /*
164  * Translate a trap number into a unix compatible signal value.
165  * (gdb only understands unix signal numbers).
166  */
167 static int
168 computeSignal(type)
169 	int type;
170 {
171 	int sigval;
172 
173 	switch (type) {
174 	case T_BUSERR:
175 		sigval = SIGBUS;
176 		break;
177 	case T_ADDRERR:
178 		sigval = SIGBUS;
179 		break;
180 	case T_ILLINST:
181 		sigval = SIGILL;
182 		break;
183 	case T_ZERODIV:
184 		sigval = SIGFPE;
185 		break;
186 	case T_CHKINST:
187 		sigval = SIGFPE;
188 		break;
189 	case T_TRAPVINST:
190 		sigval = SIGFPE;
191 		break;
192 	case T_PRIVINST:
193 		sigval = SIGILL;
194 		break;
195 	case T_TRACE:
196 		sigval = SIGTRAP;
197 		break;
198 	case T_MMUFLT:
199 		sigval = SIGSEGV;
200 		break;
201 	case T_SSIR:
202 		sigval = SIGSEGV;
203 		break;
204 	case T_FMTERR:
205 		sigval = SIGILL;
206 		break;
207 	case T_FPERR:
208 		sigval = SIGFPE;
209 		break;
210 	case T_COPERR:
211 		sigval = SIGFPE;
212 		break;
213 	case T_ASTFLT:
214 		sigval = SIGINT;
215 		break;
216 	case T_TRAP15:
217 		sigval = SIGTRAP;
218 		break;
219 	default:
220 		sigval = SIGEMT;
221 		break;
222 	}
223 	return (sigval);
224 }
225 
226 /*
227  * Trap into kgdb to wait for debugger to connect,
228  * noting on the console why nothing else is going on.
229  */
230 kgdb_connect(verbose)
231 	int verbose;
232 {
233 
234 	if (verbose)
235 		printf("kgdb waiting...");
236 	/* trap into kgdb */
237 	asm("trap #15;");
238 	if (verbose)
239 		printf("connected.\n");
240 }
241 
242 /*
243  * Decide what to do on panic.
244  */
245 kgdb_panic()
246 {
247 
248 	if (kgdb_active == 0 && kgdb_debug_panic && kgdb_dev != NODEV)
249 		kgdb_connect(1);
250 }
251 
252 /*
253  * Definitions exported from gdb.
254  */
255 #define NUM_REGS 18
256 #define REGISTER_BYTES ((16+2)*4)
257 #define REGISTER_BYTE(N)  ((N)*4)
258 
259 #define GDB_SR 16
260 #define GDB_PC 17
261 
262 static inline void
263 kgdb_copy(register u_char *src, register u_char *dst, register u_int nbytes)
264 {
265 	register u_char *ep = src + nbytes;
266 
267 	while (src < ep)
268 		*dst++ = *src++;
269 }
270 
271 #define regs_to_gdb(fp, regs) \
272 	(kgdb_copy((u_char *)((fp)->f_regs), (u_char *)(regs), REGISTER_BYTES))
273 
274 #define gdb_to_regs(fp, regs) \
275 	(kgdb_copy((u_char *)(regs), (u_char *)((fp)->f_regs), REGISTER_BYTES))
276 
277 static u_long reg_cache[NUM_REGS];
278 static u_char inbuffer[SL_RPCSIZE+1];
279 static u_char outbuffer[SL_RPCSIZE];
280 
281 /*
282  * This function does all command procesing for interfacing to
283  * a remote gdb.
284  */
285 int
286 kgdb_trap(int type, struct frame *frame)
287 {
288 	register u_long len;
289 	u_char *addr;
290 	register u_char *cp;
291 	register u_char out, in;
292 	register int outlen;
293 	int inlen;
294 	u_long gdb_regs[NUM_REGS];
295 
296 	if (kgdb_dev < 0) {
297 		/* not debugging */
298 		return (0);
299 	}
300 	if (kgdb_active == 0) {
301 		if (type != T_TRAP15) {
302 			/* No debugger active -- let trap handle this. */
303 			return (0);
304 		}
305 		kgdb_getc = 0;
306 		for (inlen = 0; constab[inlen].cn_probe; inlen++)
307 		    if (major(constab[inlen].cn_dev) == major(kgdb_dev)) {
308 			kgdb_getc = constab[inlen].cn_getc;
309 			kgdb_putc = constab[inlen].cn_putc;
310 			break;
311 		}
312 		if (kgdb_getc == 0 || kgdb_putc == 0)
313 			return (0);
314 		/*
315 		 * If the packet that woke us up isn't an exec packet,
316 		 * ignore it since there is no active debugger.  Also,
317 		 * we check that it's not an ack to be sure that the
318 		 * remote side doesn't send back a response after the
319 		 * local gdb has exited.  Otherwise, the local host
320 		 * could trap into gdb if it's running a gdb kernel too.
321 		 */
322 		in = GETC;
323 		/*
324 		 * If we came in asynchronously through the serial line,
325 		 * the framing character is eaten by the receive interrupt,
326 		 * but if we come in through a synchronous trap (i.e., via
327 		 * kgdb_connect()), we will see the extra character.
328 		 */
329 		if (in == FRAME_START)
330 			in = GETC;
331 
332 		/*
333 		 * Check that this is a debugger exec message.  If so,
334 		 * slurp up the entire message then ack it, and fall
335 		 * through to the recv loop.
336 		 */
337 		if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0)
338 			return (0);
339 		while (GETC != FRAME_END)
340 			;
341 		/*
342 		 * Do the printf *before* we ack the message.  This way
343 		 * we won't drop any inbound characters while we're
344 		 * doing the polling printf.
345 		 */
346 		printf("kgdb started from device %x\n", kgdb_dev);
347 		kgdb_send(in | KGDB_ACK, (u_char *)0, 0);
348 		kgdb_active = 1;
349 	}
350 	/*
351 	 * Stick frame regs into our reg cache then tell remote host
352 	 * that an exception has occured.
353 	 */
354 	regs_to_gdb(frame, gdb_regs);
355 	if (type != T_TRAP15) {
356 		/*
357 		 * Only send an asynchronous SIGNAL message when we hit
358 		 * a breakpoint.  Otherwise, we will drop the incoming
359 		 * packet while we output this one (and on entry the other
360 		 * side isn't interested in the SIGNAL type -- if it is,
361 		 * it will have used a signal packet.)
362 		 */
363 		outbuffer[0] = computeSignal(type);
364 		kgdb_send(KGDB_SIGNAL, outbuffer, 1);
365 	}
366 
367 	while (1) {
368 		in = kgdb_recv(inbuffer, &inlen);
369 		if (in == 0 || (in & KGDB_ACK))
370 			/* Ignore inbound acks and error conditions. */
371 			continue;
372 
373 		out = in | KGDB_ACK;
374 		switch (KGDB_CMD(in)) {
375 
376 		case KGDB_SIGNAL:
377 			/*
378 			 * if this command came from a running gdb,
379 			 * answer it -- the other guy has no way of
380 			 * knowing if we're in or out of this loop
381 			 * when he issues a "remote-signal".  (Note
382 			 * that without the length check, we could
383 			 * loop here forever if the ourput line is
384 			 * looped back or the remote host is echoing.)
385 			 */
386 			if (inlen == 0) {
387 				outbuffer[0] = computeSignal(type);
388 				kgdb_send(KGDB_SIGNAL, outbuffer, 1);
389 			}
390 			continue;
391 
392 		case KGDB_REG_R:
393 		case KGDB_REG_R | KGDB_DELTA:
394 			cp = outbuffer;
395 			outlen = 0;
396 			for (len = inbuffer[0]; len < NUM_REGS; ++len) {
397 				if (reg_cache[len] != gdb_regs[len] ||
398 				    (in & KGDB_DELTA) == 0) {
399 					if (outlen + 5 > SL_MAXDATA) {
400 						out |= KGDB_MORE;
401 						break;
402 					}
403 					cp[outlen] = len;
404 					kgdb_copy((u_char *)&gdb_regs[len],
405 						  &cp[outlen + 1], 4);
406 					reg_cache[len] = gdb_regs[len];
407 					outlen += 5;
408 				}
409 			}
410 			break;
411 
412 		case KGDB_REG_W:
413 		case KGDB_REG_W | KGDB_DELTA:
414 			cp = inbuffer;
415 			for (len = 0; len < inlen; len += 5) {
416 				register int j = cp[len];
417 
418 				kgdb_copy(&cp[len + 1],
419 					  (u_char *)&gdb_regs[j], 4);
420 				reg_cache[j] = gdb_regs[j];
421 			}
422 			gdb_to_regs(frame, gdb_regs);
423 			outlen = 0;
424 			break;
425 
426 		case KGDB_MEM_R:
427 			len = inbuffer[0];
428 			kgdb_copy(&inbuffer[1], (u_char *)&addr, 4);
429 			if (len > SL_MAXDATA) {
430 				outlen = 1;
431 				outbuffer[0] = E2BIG;
432 			} else if (!kgdb_acc(addr, len, B_READ)) {
433 				outlen = 1;
434 				outbuffer[0] = EFAULT;
435 			} else {
436 				outlen = len + 1;
437 				outbuffer[0] = 0;
438 				kgdb_copy(addr, &outbuffer[1], len);
439 			}
440 			break;
441 
442 		case KGDB_MEM_W:
443 			len = inlen - 4;
444 			kgdb_copy(inbuffer, (u_char *)&addr, 4);
445 			outlen = 1;
446 			if (!kgdb_acc(addr, len, B_READ))
447 				outbuffer[0] = EFAULT;
448 			else {
449 				outbuffer[0] = 0;
450 				if (!kgdb_acc(addr, len, B_WRITE))
451 					chgkprot(addr, len, B_WRITE);
452 				kgdb_copy(&inbuffer[4], addr, len);
453 				ICIA();
454 			}
455 			break;
456 
457 		case KGDB_KILL:
458 			kgdb_active = 0;
459 			printf("kgdb detached\n");
460 			/* fall through */
461 		case KGDB_CONT:
462 			kgdb_send(out, 0, 0);
463 			frame->f_sr &=~ PSL_T;
464 			return (1);
465 
466 		case KGDB_STEP:
467 			kgdb_send(out, 0, 0);
468 			frame->f_sr |= PSL_T;
469 			return (1);
470 
471 		case KGDB_EXEC:
472 		default:
473 			/* Unknown command.  Ack with a null message. */
474 			outlen = 0;
475 			break;
476 		}
477 		/* Send the reply */
478 		kgdb_send(out, outbuffer, outlen);
479 	}
480 }
481 
482 /*
483  * XXX do kernacc call if safe, otherwise attempt
484  * to simulate by simple bounds-checking.
485  */
486 kgdb_acc(addr, len, rw)
487 	caddr_t addr;
488 {
489 	extern char proc0paddr[], kstack[];	/* XXX */
490 	extern char *kernel_map;		/* XXX! */
491 
492 	if (kernel_map != NULL)
493 		return (kernacc(addr, len, rw));
494 	if (addr < proc0paddr + UPAGES * NBPG  ||
495 	    kstack <= addr && addr < kstack + UPAGES * NBPG)
496 		return (1);
497 	return (0);
498 }
499 #endif
500