1 /* $Id: sparc-stub.c,v 1.28 2001/10/30 04:54:21 davem Exp $
2 * sparc-stub.c: KGDB support for the Linux kernel.
3 *
4 * Modifications to run under Linux
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 *
7 * This file originally came from the gdb sources, and the
8 * copyright notices have been retained below.
9 */
10
11 /****************************************************************************
12
13 THIS SOFTWARE IS NOT COPYRIGHTED
14
15 HP offers the following for use in the public domain. HP makes no
16 warranty with regard to the software or its performance and the
17 user accepts the software "AS IS" with all faults.
18
19 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
20 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22
23 ****************************************************************************/
24
25 /****************************************************************************
26 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
27 *
28 * Module name: remcom.c $
29 * Revision: 1.34 $
30 * Date: 91/03/09 12:29:49 $
31 * Contributor: Lake Stevens Instrument Division$
32 *
33 * Description: low level support for gdb debugger. $
34 *
35 * Considerations: only works on target hardware $
36 *
37 * Written by: Glenn Engel $
38 * ModuleState: Experimental $
39 *
40 * NOTES: See Below $
41 *
42 * Modified for SPARC by Stu Grossman, Cygnus Support.
43 *
44 * This code has been extensively tested on the Fujitsu SPARClite demo board.
45 *
46 * To enable debugger support, two things need to happen. One, a
47 * call to set_debug_traps() is necessary in order to allow any breakpoints
48 * or error conditions to be properly intercepted and reported to gdb.
49 * Two, a breakpoint needs to be generated to begin communication. This
50 * is most easily accomplished by a call to breakpoint(). Breakpoint()
51 * simulates a breakpoint by executing a trap #1.
52 *
53 *************
54 *
55 * The following gdb commands are supported:
56 *
57 * command function Return value
58 *
59 * g return the value of the CPU registers hex data or ENN
60 * G set the value of the CPU registers OK or ENN
61 *
62 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
63 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
64 *
65 * c Resume at current address SNN ( signal NN)
66 * cAA..AA Continue at address AA..AA SNN
67 *
68 * s Step one instruction SNN
69 * sAA..AA Step one instruction from AA..AA SNN
70 *
71 * k kill
72 *
73 * ? What was the last sigval ? SNN (signal NN)
74 *
75 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
76 * baud rate
77 *
78 * All commands and responses are sent with a packet which includes a
79 * checksum. A packet consists of
80 *
81 * $<packet info>#<checksum>.
82 *
83 * where
84 * <packet info> :: <characters representing the command or response>
85 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
86 *
87 * When a packet is received, it is first acknowledged with either '+' or '-'.
88 * '+' indicates a successful transfer. '-' indicates a failed transfer.
89 *
90 * Example:
91 *
92 * Host: Reply:
93 * $m0,10#2a +$00010203040506070809101112131415#42
94 *
95 ****************************************************************************/
96
97 #include <linux/kernel.h>
98 #include <linux/string.h>
99 #include <linux/mm.h>
100 #include <linux/smp.h>
101 #include <linux/smp_lock.h>
102
103 #include <asm/system.h>
104 #include <asm/signal.h>
105 #include <asm/oplib.h>
106 #include <asm/head.h>
107 #include <asm/traps.h>
108 #include <asm/vac-ops.h>
109 #include <asm/kgdb.h>
110 #include <asm/pgalloc.h>
111 #include <asm/pgtable.h>
112 /*
113 *
114 * external low-level support routines
115 */
116
117 extern void putDebugChar(char); /* write a single character */
118 extern char getDebugChar(void); /* read and return a single char */
119
120 /*
121 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
122 * at least NUMREGBYTES*2 are needed for register packets
123 */
124 #define BUFMAX 2048
125
126 static int initialized; /* !0 means we've been initialized */
127
128 static const char hexchars[]="0123456789abcdef";
129
130 #define NUMREGS 72
131
132 /* Number of bytes of registers. */
133 #define NUMREGBYTES (NUMREGS * 4)
134 enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
135 O0, O1, O2, O3, O4, O5, SP, O7,
136 L0, L1, L2, L3, L4, L5, L6, L7,
137 I0, I1, I2, I3, I4, I5, FP, I7,
138
139 F0, F1, F2, F3, F4, F5, F6, F7,
140 F8, F9, F10, F11, F12, F13, F14, F15,
141 F16, F17, F18, F19, F20, F21, F22, F23,
142 F24, F25, F26, F27, F28, F29, F30, F31,
143 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
144
145
146 extern void trap_low(void); /* In arch/sparc/kernel/entry.S */
147
get_sun4cpte(unsigned long addr)148 unsigned long get_sun4cpte(unsigned long addr)
149 {
150 unsigned long entry;
151
152 __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
153 "=r" (entry) :
154 "r" (addr), "i" (ASI_PTE));
155 return entry;
156 }
157
get_sun4csegmap(unsigned long addr)158 unsigned long get_sun4csegmap(unsigned long addr)
159 {
160 unsigned long entry;
161
162 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
163 "=r" (entry) :
164 "r" (addr), "i" (ASI_SEGMAP));
165 return entry;
166 }
167
168 #if 0
169 /* Have to sort this out. This cannot be done after initialization. */
170 static void flush_cache_all_nop(void) {}
171 #endif
172
173 /* Place where we save old trap entries for restoration */
174 struct tt_entry kgdb_savettable[256];
175 typedef void (*trapfunc_t)(void);
176
177 /* Helper routine for manipulation of kgdb_savettable */
copy_ttentry(struct tt_entry * src,struct tt_entry * dest)178 static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
179 {
180 dest->inst_one = src->inst_one;
181 dest->inst_two = src->inst_two;
182 dest->inst_three = src->inst_three;
183 dest->inst_four = src->inst_four;
184 }
185
186 /* Initialize the kgdb_savettable so that debugging can commence */
eh_init(void)187 static void eh_init(void)
188 {
189 int i, flags;
190
191 save_and_cli(flags);
192 for(i=0; i < 256; i++)
193 copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
194 restore_flags(flags);
195 }
196
197 /* Install an exception handler for kgdb */
exceptionHandler(int tnum,trapfunc_t trap_entry)198 static void exceptionHandler(int tnum, trapfunc_t trap_entry)
199 {
200 unsigned long te_addr = (unsigned long) trap_entry;
201 int flags;
202
203 /* We are dorking with a live trap table, all irqs off */
204 save_and_cli(flags);
205
206 /* Make new vector */
207 sparc_ttable[tnum].inst_one =
208 SPARC_BRANCH((unsigned long) te_addr,
209 (unsigned long) &sparc_ttable[tnum].inst_one);
210 sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
211 sparc_ttable[tnum].inst_three = SPARC_NOP;
212 sparc_ttable[tnum].inst_four = SPARC_NOP;
213
214 restore_flags(flags);
215 }
216
217 /* Convert ch from a hex digit to an int */
218 static int
hex(unsigned char ch)219 hex(unsigned char ch)
220 {
221 if (ch >= 'a' && ch <= 'f')
222 return ch-'a'+10;
223 if (ch >= '0' && ch <= '9')
224 return ch-'0';
225 if (ch >= 'A' && ch <= 'F')
226 return ch-'A'+10;
227 return -1;
228 }
229
230 /* scan for the sequence $<data>#<checksum> */
231 static void
getpacket(char * buffer)232 getpacket(char *buffer)
233 {
234 unsigned char checksum;
235 unsigned char xmitcsum;
236 int i;
237 int count;
238 unsigned char ch;
239
240 do {
241 /* wait around for the start character, ignore all other characters */
242 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
243
244 checksum = 0;
245 xmitcsum = -1;
246
247 count = 0;
248
249 /* now, read until a # or end of buffer is found */
250 while (count < BUFMAX) {
251 ch = getDebugChar() & 0x7f;
252 if (ch == '#')
253 break;
254 checksum = checksum + ch;
255 buffer[count] = ch;
256 count = count + 1;
257 }
258
259 if (count >= BUFMAX)
260 continue;
261
262 buffer[count] = 0;
263
264 if (ch == '#') {
265 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
266 xmitcsum |= hex(getDebugChar() & 0x7f);
267 if (checksum != xmitcsum)
268 putDebugChar('-'); /* failed checksum */
269 else {
270 putDebugChar('+'); /* successful transfer */
271 /* if a sequence char is present, reply the ID */
272 if (buffer[2] == ':') {
273 putDebugChar(buffer[0]);
274 putDebugChar(buffer[1]);
275 /* remove sequence chars from buffer */
276 count = strlen(buffer);
277 for (i=3; i <= count; i++)
278 buffer[i-3] = buffer[i];
279 }
280 }
281 }
282 } while (checksum != xmitcsum);
283 }
284
285 /* send the packet in buffer. */
286
287 static void
putpacket(unsigned char * buffer)288 putpacket(unsigned char *buffer)
289 {
290 unsigned char checksum;
291 int count;
292 unsigned char ch, recv;
293
294 /* $<packet info>#<checksum>. */
295 do {
296 putDebugChar('$');
297 checksum = 0;
298 count = 0;
299
300 while ((ch = buffer[count])) {
301 putDebugChar(ch);
302 checksum += ch;
303 count += 1;
304 }
305
306 putDebugChar('#');
307 putDebugChar(hexchars[checksum >> 4]);
308 putDebugChar(hexchars[checksum & 0xf]);
309 recv = getDebugChar();
310 } while ((recv & 0x7f) != '+');
311 }
312
313 static char remcomInBuffer[BUFMAX];
314 static char remcomOutBuffer[BUFMAX];
315
316 /* Convert the memory pointed to by mem into hex, placing result in buf.
317 * Return a pointer to the last char put in buf (null), in case of mem fault,
318 * return 0.
319 */
320
321 static unsigned char *
mem2hex(char * mem,char * buf,int count)322 mem2hex(char *mem, char *buf, int count)
323 {
324 unsigned char ch;
325
326 while (count-- > 0) {
327 /* This assembler code is basically: ch = *mem++;
328 * except that we use the SPARC/Linux exception table
329 * mechanism (see how "fixup" works in kernel_mna_trap_fault)
330 * to arrange for a "return 0" upon a memory fault
331 */
332 __asm__(
333 "\n1:\n\t"
334 "ldub [%0], %1\n\t"
335 "inc %0\n\t"
336 ".section .fixup,#alloc,#execinstr\n\t"
337 ".align 4\n"
338 "2:\n\t"
339 "retl\n\t"
340 " mov 0, %%o0\n\t"
341 ".section __ex_table, #alloc\n\t"
342 ".align 4\n\t"
343 ".word 1b, 2b\n\t"
344 ".text\n"
345 : "=r" (mem), "=r" (ch) : "0" (mem));
346 *buf++ = hexchars[ch >> 4];
347 *buf++ = hexchars[ch & 0xf];
348 }
349
350 *buf = 0;
351 return buf;
352 }
353
354 /* convert the hex array pointed to by buf into binary to be placed in mem
355 * return a pointer to the character AFTER the last byte written.
356 */
357 static char *
hex2mem(char * buf,char * mem,int count)358 hex2mem(char *buf, char *mem, int count)
359 {
360 int i;
361 unsigned char ch;
362
363 for (i=0; i<count; i++) {
364
365 ch = hex(*buf++) << 4;
366 ch |= hex(*buf++);
367 /* Assembler code is *mem++ = ch; with return 0 on fault */
368 __asm__(
369 "\n1:\n\t"
370 "stb %1, [%0]\n\t"
371 "inc %0\n\t"
372 ".section .fixup,#alloc,#execinstr\n\t"
373 ".align 4\n"
374 "2:\n\t"
375 "retl\n\t"
376 " mov 0, %%o0\n\t"
377 ".section __ex_table, #alloc\n\t"
378 ".align 4\n\t"
379 ".word 1b, 2b\n\t"
380 ".text\n"
381 : "=r" (mem) : "r" (ch) , "0" (mem));
382 }
383 return mem;
384 }
385
386 /* This table contains the mapping between SPARC hardware trap types, and
387 signals, which are primarily what GDB understands. It also indicates
388 which hardware traps we need to commandeer when initializing the stub. */
389
390 static struct hard_trap_info
391 {
392 unsigned char tt; /* Trap type code for SPARC */
393 unsigned char signo; /* Signal that we map this trap into */
394 } hard_trap_info[] = {
395 {SP_TRAP_SBPT, SIGTRAP}, /* ta 1 - Linux/KGDB software breakpoint */
396 {0, 0} /* Must be last */
397 };
398
399 /* Set up exception handlers for tracing and breakpoints */
400
401 void
set_debug_traps(void)402 set_debug_traps(void)
403 {
404 struct hard_trap_info *ht;
405 unsigned long flags;
406
407 save_and_cli(flags);
408 #if 0
409 /* Have to sort this out. This cannot be done after initialization. */
410 BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);
411 #endif
412
413 /* Initialize our copy of the Linux Sparc trap table */
414 eh_init();
415
416 for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
417 /* Only if it doesn't destroy our fault handlers */
418 if((ht->tt != SP_TRAP_TFLT) &&
419 (ht->tt != SP_TRAP_DFLT))
420 exceptionHandler(ht->tt, trap_low);
421 }
422
423 /* In case GDB is started before us, ack any packets (presumably
424 * "$?#xx") sitting there.
425 *
426 * I've found this code causes more problems than it solves,
427 * so that's why it's commented out. GDB seems to work fine
428 * now starting either before or after the kernel -bwb
429 */
430 #if 0
431 while((c = getDebugChar()) != '$');
432 while((c = getDebugChar()) != '#');
433 c = getDebugChar(); /* eat first csum byte */
434 c = getDebugChar(); /* eat second csum byte */
435 putDebugChar('+'); /* ack it */
436 #endif
437
438 initialized = 1; /* connect! */
439 restore_flags(flags);
440 }
441
442 /* Convert the SPARC hardware trap type code to a unix signal number. */
443
444 static int
computeSignal(int tt)445 computeSignal(int tt)
446 {
447 struct hard_trap_info *ht;
448
449 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
450 if (ht->tt == tt)
451 return ht->signo;
452
453 return SIGHUP; /* default for things we don't know about */
454 }
455
456 /*
457 * While we find nice hex chars, build an int.
458 * Return number of chars processed.
459 */
460
461 static int
hexToInt(char ** ptr,int * intValue)462 hexToInt(char **ptr, int *intValue)
463 {
464 int numChars = 0;
465 int hexValue;
466
467 *intValue = 0;
468
469 while (**ptr) {
470 hexValue = hex(**ptr);
471 if (hexValue < 0)
472 break;
473
474 *intValue = (*intValue << 4) | hexValue;
475 numChars ++;
476
477 (*ptr)++;
478 }
479
480 return (numChars);
481 }
482
483 /*
484 * This function does all command processing for interfacing to gdb. It
485 * returns 1 if you should skip the instruction at the trap address, 0
486 * otherwise.
487 */
488
489 extern void breakinst(void);
490
491 void
handle_exception(unsigned long * registers)492 handle_exception (unsigned long *registers)
493 {
494 int tt; /* Trap type */
495 int sigval;
496 int addr;
497 int length;
498 char *ptr;
499 unsigned long *sp;
500
501 /* First, we must force all of the windows to be spilled out */
502
503 asm("save %sp, -64, %sp\n\t"
504 "save %sp, -64, %sp\n\t"
505 "save %sp, -64, %sp\n\t"
506 "save %sp, -64, %sp\n\t"
507 "save %sp, -64, %sp\n\t"
508 "save %sp, -64, %sp\n\t"
509 "save %sp, -64, %sp\n\t"
510 "save %sp, -64, %sp\n\t"
511 "restore\n\t"
512 "restore\n\t"
513 "restore\n\t"
514 "restore\n\t"
515 "restore\n\t"
516 "restore\n\t"
517 "restore\n\t"
518 "restore\n\t");
519
520 lock_kernel();
521 if (registers[PC] == (unsigned long)breakinst) {
522 /* Skip over breakpoint trap insn */
523 registers[PC] = registers[NPC];
524 registers[NPC] += 4;
525 }
526
527 sp = (unsigned long *)registers[SP];
528
529 tt = (registers[TBR] >> 4) & 0xff;
530
531 /* reply to host that an exception has occurred */
532 sigval = computeSignal(tt);
533 ptr = remcomOutBuffer;
534
535 *ptr++ = 'T';
536 *ptr++ = hexchars[sigval >> 4];
537 *ptr++ = hexchars[sigval & 0xf];
538
539 *ptr++ = hexchars[PC >> 4];
540 *ptr++ = hexchars[PC & 0xf];
541 *ptr++ = ':';
542 ptr = mem2hex((char *)®isters[PC], ptr, 4);
543 *ptr++ = ';';
544
545 *ptr++ = hexchars[FP >> 4];
546 *ptr++ = hexchars[FP & 0xf];
547 *ptr++ = ':';
548 ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
549 *ptr++ = ';';
550
551 *ptr++ = hexchars[SP >> 4];
552 *ptr++ = hexchars[SP & 0xf];
553 *ptr++ = ':';
554 ptr = mem2hex((char *)&sp, ptr, 4);
555 *ptr++ = ';';
556
557 *ptr++ = hexchars[NPC >> 4];
558 *ptr++ = hexchars[NPC & 0xf];
559 *ptr++ = ':';
560 ptr = mem2hex((char *)®isters[NPC], ptr, 4);
561 *ptr++ = ';';
562
563 *ptr++ = hexchars[O7 >> 4];
564 *ptr++ = hexchars[O7 & 0xf];
565 *ptr++ = ':';
566 ptr = mem2hex((char *)®isters[O7], ptr, 4);
567 *ptr++ = ';';
568
569 *ptr++ = 0;
570
571 putpacket(remcomOutBuffer);
572
573 /* XXX We may want to add some features dealing with poking the
574 * XXX page tables, the real ones on the srmmu, and what is currently
575 * XXX loaded in the sun4/sun4c tlb at this point in time. But this
576 * XXX also required hacking to the gdb sources directly...
577 */
578
579 while (1) {
580 remcomOutBuffer[0] = 0;
581
582 getpacket(remcomInBuffer);
583 switch (remcomInBuffer[0]) {
584 case '?':
585 remcomOutBuffer[0] = 'S';
586 remcomOutBuffer[1] = hexchars[sigval >> 4];
587 remcomOutBuffer[2] = hexchars[sigval & 0xf];
588 remcomOutBuffer[3] = 0;
589 break;
590
591 case 'd':
592 /* toggle debug flag */
593 break;
594
595 case 'g': /* return the value of the CPU registers */
596 {
597 ptr = remcomOutBuffer;
598 /* G & O regs */
599 ptr = mem2hex((char *)registers, ptr, 16 * 4);
600 /* L & I regs */
601 ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
602 /* Floating point */
603 memset(ptr, '0', 32 * 8);
604 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
605 mem2hex((char *)®isters[Y], (ptr + 32 * 4 * 2), (8 * 4));
606 }
607 break;
608
609 case 'G': /* set the value of the CPU registers - return OK */
610 {
611 unsigned long *newsp, psr;
612
613 psr = registers[PSR];
614
615 ptr = &remcomInBuffer[1];
616 /* G & O regs */
617 hex2mem(ptr, (char *)registers, 16 * 4);
618 /* L & I regs */
619 hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
620 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
621 hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y], 8 * 4);
622
623 /* See if the stack pointer has moved. If so,
624 * then copy the saved locals and ins to the
625 * new location. This keeps the window
626 * overflow and underflow routines happy.
627 */
628
629 newsp = (unsigned long *)registers[SP];
630 if (sp != newsp)
631 sp = memcpy(newsp, sp, 16 * 4);
632
633 /* Don't allow CWP to be modified. */
634
635 if (psr != registers[PSR])
636 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
637
638 strcpy(remcomOutBuffer,"OK");
639 }
640 break;
641
642 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
643 /* Try to read %x,%x. */
644
645 ptr = &remcomInBuffer[1];
646
647 if (hexToInt(&ptr, &addr)
648 && *ptr++ == ','
649 && hexToInt(&ptr, &length)) {
650 if (mem2hex((char *)addr, remcomOutBuffer, length))
651 break;
652
653 strcpy (remcomOutBuffer, "E03");
654 } else {
655 strcpy(remcomOutBuffer,"E01");
656 }
657 break;
658
659 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
660 /* Try to read '%x,%x:'. */
661
662 ptr = &remcomInBuffer[1];
663
664 if (hexToInt(&ptr, &addr)
665 && *ptr++ == ','
666 && hexToInt(&ptr, &length)
667 && *ptr++ == ':') {
668 if (hex2mem(ptr, (char *)addr, length)) {
669 strcpy(remcomOutBuffer, "OK");
670 } else {
671 strcpy(remcomOutBuffer, "E03");
672 }
673 } else {
674 strcpy(remcomOutBuffer, "E02");
675 }
676 break;
677
678 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
679 /* try to read optional parameter, pc unchanged if no parm */
680
681 ptr = &remcomInBuffer[1];
682 if (hexToInt(&ptr, &addr)) {
683 registers[PC] = addr;
684 registers[NPC] = addr + 4;
685 }
686
687 /* Need to flush the instruction cache here, as we may have deposited a
688 * breakpoint, and the icache probably has no way of knowing that a data ref to
689 * some location may have changed something that is in the instruction cache.
690 */
691 flush_cache_all();
692 unlock_kernel();
693 return;
694
695 /* kill the program */
696 case 'k' : /* do nothing */
697 break;
698 case 'r': /* Reset */
699 asm ("call 0\n\t"
700 "nop\n\t");
701 break;
702 } /* switch */
703
704 /* reply to the request */
705 putpacket(remcomOutBuffer);
706 } /* while(1) */
707 }
708
709 /* This function will generate a breakpoint exception. It is used at the
710 beginning of a program to sync up with a debugger and can be used
711 otherwise as a quick means to stop program execution and "break" into
712 the debugger. */
713
714 void
breakpoint(void)715 breakpoint(void)
716 {
717 if (!initialized)
718 return;
719
720 /* Again, watch those c-prefixes for ELF kernels */
721 #if defined(__svr4__) || defined(__ELF__)
722 asm(".globl breakinst\n"
723 "breakinst:\n\t"
724 "ta 1\n");
725 #else
726 asm(".globl _breakinst\n"
727 "_breakinst:\n\t"
728 "ta 1\n");
729 #endif
730 }
731