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.
4 * Modifications to run under Linux
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
7 * This file originally came from the gdb sources, and the
8 * copyright notices have been retained below.
11 /****************************************************************************
13 THIS SOFTWARE IS NOT COPYRIGHTED
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.
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.
23 ****************************************************************************/
25 /****************************************************************************
26 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
28 * Module name: remcom.c $
30 * Date: 91/03/09 12:29:49 $
31 * Contributor: Lake Stevens Instrument Division$
33 * Description: low level support for gdb debugger. $
35 * Considerations: only works on target hardware $
37 * Written by: Glenn Engel $
38 * ModuleState: Experimental $
42 * Modified for SPARC by Stu Grossman, Cygnus Support.
44 * This code has been extensively tested on the Fujitsu SPARClite demo board.
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.
55 * The following gdb commands are supported:
57 * command function Return value
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
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
65 * c Resume at current address SNN ( signal NN)
66 * cAA..AA Continue at address AA..AA SNN
68 * s Step one instruction SNN
69 * sAA..AA Step one instruction from AA..AA SNN
73 * ? What was the last sigval ? SNN (signal NN)
75 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
78 * All commands and responses are sent with a packet which includes a
79 * checksum. A packet consists of
81 * $<packet info>#<checksum>.
84 * <packet info> :: <characters representing the command or response>
85 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
87 * When a packet is received, it is first acknowledged with either '+' or '-'.
88 * '+' indicates a successful transfer. '-' indicates a failed transfer.
93 * $m0,10#2a +$00010203040506070809101112131415#42
95 ****************************************************************************/
97 #include <linux/kernel.h>
98 #include <linux/string.h>
100 #include <linux/smp.h>
101 #include <linux/smp_lock.h>
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>
114 * external low-level support routines
117 extern void putDebugChar(char); /* write a single character */
118 extern char getDebugChar(void); /* read and return a single char */
121 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
122 * at least NUMREGBYTES*2 are needed for register packets
126 static int initialized; /* !0 means we've been initialized */
128 static const char hexchars[]="0123456789abcdef";
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,
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 };
146 extern void trap_low(void); /* In arch/sparc/kernel/entry.S */
148 unsigned long get_sun4cpte(unsigned long addr)
152 __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
154 "r" (addr), "i" (ASI_PTE));
158 unsigned long get_sun4csegmap(unsigned long addr)
162 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
164 "r" (addr), "i" (ASI_SEGMAP));
169 /* Have to sort this out. This cannot be done after initialization. */
170 static void flush_cache_all_nop(void) {}
173 /* Place where we save old trap entries for restoration */
174 struct tt_entry kgdb_savettable[256];
175 typedef void (*trapfunc_t)(void);
177 /* Helper routine for manipulation of kgdb_savettable */
178 static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
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;
186 /* Initialize the kgdb_savettable so that debugging can commence */
187 static void eh_init(void)
192 for(i=0; i < 256; i++)
193 copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
194 restore_flags(flags);
197 /* Install an exception handler for kgdb */
198 static void exceptionHandler(int tnum, trapfunc_t trap_entry)
200 unsigned long te_addr = (unsigned long) trap_entry;
203 /* We are dorking with a live trap table, all irqs off */
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;
214 restore_flags(flags);
217 /* Convert ch from a hex digit to an int */
219 hex(unsigned char ch)
221 if (ch >= 'a' && ch <= 'f')
223 if (ch >= '0' && ch <= '9')
225 if (ch >= 'A' && ch <= 'F')
230 /* scan for the sequence $<data>#<checksum> */
232 getpacket(char *buffer)
234 unsigned char checksum;
235 unsigned char xmitcsum;
241 /* wait around for the start character, ignore all other characters */
242 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
249 /* now, read until a # or end of buffer is found */
250 while (count < BUFMAX) {
251 ch = getDebugChar() & 0x7f;
254 checksum = checksum + ch;
265 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
266 xmitcsum |= hex(getDebugChar() & 0x7f);
267 if (checksum != xmitcsum)
268 putDebugChar('-'); /* failed checksum */
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];
282 } while (checksum != xmitcsum);
285 /* send the packet in buffer. */
288 putpacket(unsigned char *buffer)
290 unsigned char checksum;
292 unsigned char ch, recv;
294 /* $<packet info>#<checksum>. */
300 while ((ch = buffer[count])) {
307 putDebugChar(hexchars[checksum >> 4]);
308 putDebugChar(hexchars[checksum & 0xf]);
309 recv = getDebugChar();
310 } while ((recv & 0x7f) != '+');
313 static char remcomInBuffer[BUFMAX];
314 static char remcomOutBuffer[BUFMAX];
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,
321 static unsigned char *
322 mem2hex(char *mem, char *buf, int count)
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
336 ".section .fixup,#alloc,#execinstr\n\t"
341 ".section __ex_table, #alloc\n\t"
345 : "=r" (mem), "=r" (ch) : "0" (mem));
346 *buf++ = hexchars[ch >> 4];
347 *buf++ = hexchars[ch & 0xf];
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.
358 hex2mem(char *buf, char *mem, int count)
363 for (i=0; i<count; i++) {
365 ch = hex(*buf++) << 4;
367 /* Assembler code is *mem++ = ch; with return 0 on fault */
372 ".section .fixup,#alloc,#execinstr\n\t"
377 ".section __ex_table, #alloc\n\t"
381 : "=r" (mem) : "r" (ch) , "0" (mem));
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. */
390 static struct hard_trap_info
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 */
399 /* Set up exception handlers for tracing and breakpoints */
402 set_debug_traps(void)
404 struct hard_trap_info *ht;
409 /* Have to sort this out. This cannot be done after initialization. */
410 BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);
413 /* Initialize our copy of the Linux Sparc trap table */
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);
423 /* In case GDB is started before us, ack any packets (presumably
424 * "$?#xx") sitting there.
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
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 */
438 initialized = 1; /* connect! */
439 restore_flags(flags);
442 /* Convert the SPARC hardware trap type code to a unix signal number. */
445 computeSignal(int tt)
447 struct hard_trap_info *ht;
449 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
453 return SIGHUP; /* default for things we don't know about */
457 * While we find nice hex chars, build an int.
458 * Return number of chars processed.
462 hexToInt(char **ptr, int *intValue)
470 hexValue = hex(**ptr);
474 *intValue = (*intValue << 4) | hexValue;
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
489 extern void breakinst(void);
492 handle_exception (unsigned long *registers)
494 int tt; /* Trap type */
501 /* First, we must force all of the windows to be spilled out */
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"
521 if (registers[PC] == (unsigned long)breakinst) {
522 /* Skip over breakpoint trap insn */
523 registers[PC] = registers[NPC];
527 sp = (unsigned long *)registers[SP];
529 tt = (registers[TBR] >> 4) & 0xff;
531 /* reply to host that an exception has occurred */
532 sigval = computeSignal(tt);
533 ptr = remcomOutBuffer;
536 *ptr++ = hexchars[sigval >> 4];
537 *ptr++ = hexchars[sigval & 0xf];
539 *ptr++ = hexchars[PC >> 4];
540 *ptr++ = hexchars[PC & 0xf];
542 ptr = mem2hex((char *)®isters[PC], ptr, 4);
545 *ptr++ = hexchars[FP >> 4];
546 *ptr++ = hexchars[FP & 0xf];
548 ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
551 *ptr++ = hexchars[SP >> 4];
552 *ptr++ = hexchars[SP & 0xf];
554 ptr = mem2hex((char *)&sp, ptr, 4);
557 *ptr++ = hexchars[NPC >> 4];
558 *ptr++ = hexchars[NPC & 0xf];
560 ptr = mem2hex((char *)®isters[NPC], ptr, 4);
563 *ptr++ = hexchars[O7 >> 4];
564 *ptr++ = hexchars[O7 & 0xf];
566 ptr = mem2hex((char *)®isters[O7], ptr, 4);
571 putpacket(remcomOutBuffer);
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...
580 remcomOutBuffer[0] = 0;
582 getpacket(remcomInBuffer);
583 switch (remcomInBuffer[0]) {
585 remcomOutBuffer[0] = 'S';
586 remcomOutBuffer[1] = hexchars[sigval >> 4];
587 remcomOutBuffer[2] = hexchars[sigval & 0xf];
588 remcomOutBuffer[3] = 0;
592 /* toggle debug flag */
595 case 'g': /* return the value of the CPU registers */
597 ptr = remcomOutBuffer;
599 ptr = mem2hex((char *)registers, ptr, 16 * 4);
601 ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
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));
609 case 'G': /* set the value of the CPU registers - return OK */
611 unsigned long *newsp, psr;
613 psr = registers[PSR];
615 ptr = &remcomInBuffer[1];
617 hex2mem(ptr, (char *)registers, 16 * 4);
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);
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.
629 newsp = (unsigned long *)registers[SP];
631 sp = memcpy(newsp, sp, 16 * 4);
633 /* Don't allow CWP to be modified. */
635 if (psr != registers[PSR])
636 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
638 strcpy(remcomOutBuffer,"OK");
642 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
643 /* Try to read %x,%x. */
645 ptr = &remcomInBuffer[1];
647 if (hexToInt(&ptr, &addr)
649 && hexToInt(&ptr, &length)) {
650 if (mem2hex((char *)addr, remcomOutBuffer, length))
653 strcpy (remcomOutBuffer, "E03");
655 strcpy(remcomOutBuffer,"E01");
659 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
660 /* Try to read '%x,%x:'. */
662 ptr = &remcomInBuffer[1];
664 if (hexToInt(&ptr, &addr)
666 && hexToInt(&ptr, &length)
668 if (hex2mem(ptr, (char *)addr, length)) {
669 strcpy(remcomOutBuffer, "OK");
671 strcpy(remcomOutBuffer, "E03");
674 strcpy(remcomOutBuffer, "E02");
678 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
679 /* try to read optional parameter, pc unchanged if no parm */
681 ptr = &remcomInBuffer[1];
682 if (hexToInt(&ptr, &addr)) {
683 registers[PC] = addr;
684 registers[NPC] = addr + 4;
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.
695 /* kill the program */
696 case 'k' : /* do nothing */
698 case 'r': /* Reset */
704 /* reply to the request */
705 putpacket(remcomOutBuffer);
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
720 /* Again, watch those c-prefixes for ELF kernels */
721 #if defined(__svr4__) || defined(__ELF__)
722 asm(".globl breakinst\n"
726 asm(".globl _breakinst\n"