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