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