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 *)®s[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 *)®s[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