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