Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / arch / sparc / kernel / sparc-stub.c
blob828e4deedde5aef3174ee58cfb1587c85966b117
1 /* $Id: sparc-stub.c,v 1.27 2000/10/03 07:28:49 anton 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.
9 */
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 $
29 * Revision: 1.34 $
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 $
40 * NOTES: See Below $
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.
53 *************
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
71 * k kill
73 * ? What was the last sigval ? SNN (signal NN)
75 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
76 * baud rate
78 * All commands and responses are sent with a packet which includes a
79 * checksum. A packet consists of
81 * $<packet info>#<checksum>.
83 * where
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.
90 * Example:
92 * Host: Reply:
93 * $m0,10#2a +$00010203040506070809101112131415#42
95 ****************************************************************************/
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>
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
124 #define BUFMAX 2048
126 static int initialized; /* !0 means we've been initialized */
128 static const char hexchars[]="0123456789abcdef";
130 #define NUMREGS 72
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)
150 unsigned long entry;
152 __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
153 "=r" (entry) :
154 "r" (addr), "i" (ASI_PTE));
155 return entry;
158 unsigned long get_sun4csegmap(unsigned long addr)
160 unsigned long entry;
162 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
163 "=r" (entry) :
164 "r" (addr), "i" (ASI_SEGMAP));
165 return entry;
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
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)
189 int i, flags;
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);
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;
201 int flags;
203 /* We are dorking with a live trap table, all irqs off */
204 save_and_cli(flags);
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 */
218 static int
219 hex(unsigned char ch)
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;
230 /* scan for the sequence $<data>#<checksum> */
231 static void
232 getpacket(char *buffer)
234 unsigned char checksum;
235 unsigned char xmitcsum;
236 int i;
237 int count;
238 unsigned char ch;
240 do {
241 /* wait around for the start character, ignore all other characters */
242 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
244 checksum = 0;
245 xmitcsum = -1;
247 count = 0;
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;
259 if (count >= BUFMAX)
260 continue;
262 buffer[count] = 0;
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];
282 } while (checksum != xmitcsum);
285 /* send the packet in buffer. */
287 static void
288 putpacket(unsigned char *buffer)
290 unsigned char checksum;
291 int count;
292 unsigned char ch, recv;
294 /* $<packet info>#<checksum>. */
295 do {
296 putDebugChar('$');
297 checksum = 0;
298 count = 0;
300 while ((ch = buffer[count])) {
301 putDebugChar(ch);
302 checksum += ch;
303 count += 1;
306 putDebugChar('#');
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,
318 * return 0.
321 static unsigned char *
322 mem2hex(char *mem, char *buf, int count)
324 unsigned char ch;
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
332 __asm__(
333 "1: ldub [%0], %1
334 inc %0
335 .section .fixup,#alloc,#execinstr
336 .align 4
337 2: retl
338 mov 0, %%o0
339 .section __ex_table, #alloc
340 .align 4
341 .word 1b, 2b
342 .text"
343 : "=r" (mem), "=r" (ch) : "0" (mem));
344 *buf++ = hexchars[ch >> 4];
345 *buf++ = hexchars[ch & 0xf];
348 *buf = 0;
349 return buf;
352 /* convert the hex array pointed to by buf into binary to be placed in mem
353 * return a pointer to the character AFTER the last byte written.
355 static char *
356 hex2mem(char *buf, char *mem, int count)
358 int i;
359 unsigned char ch;
361 for (i=0; i<count; i++) {
363 ch = hex(*buf++) << 4;
364 ch |= hex(*buf++);
365 /* Assembler code is *mem++ = ch; with return 0 on fault */
366 __asm__(
367 "1: stb %1, [%0]
368 inc %0
369 .section .fixup,#alloc,#execinstr
370 .align 4
371 2: retl
372 mov 0, %%o0
373 .section __ex_table, #alloc
374 .align 4
375 .word 1b, 2b
376 .text"
377 : "=r" (mem) : "r" (ch) , "0" (mem));
379 return mem;
382 /* This table contains the mapping between SPARC hardware trap types, and
383 signals, which are primarily what GDB understands. It also indicates
384 which hardware traps we need to commandeer when initializing the stub. */
386 static struct hard_trap_info
388 unsigned char tt; /* Trap type code for SPARC */
389 unsigned char signo; /* Signal that we map this trap into */
390 } hard_trap_info[] = {
391 {SP_TRAP_SBPT, SIGTRAP}, /* ta 1 - Linux/KGDB software breakpoint */
392 {0, 0} /* Must be last */
395 /* Set up exception handlers for tracing and breakpoints */
397 void
398 set_debug_traps(void)
400 struct hard_trap_info *ht;
401 unsigned long flags;
403 save_and_cli(flags);
404 #if 0
405 /* Have to sort this out. This cannot be done after initialization. */
406 BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);
407 #endif
409 /* Initialize our copy of the Linux Sparc trap table */
410 eh_init();
412 for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
413 /* Only if it doesn't destroy our fault handlers */
414 if((ht->tt != SP_TRAP_TFLT) &&
415 (ht->tt != SP_TRAP_DFLT))
416 exceptionHandler(ht->tt, trap_low);
419 /* In case GDB is started before us, ack any packets (presumably
420 * "$?#xx") sitting there.
422 * I've found this code causes more problems than it solves,
423 * so that's why it's commented out. GDB seems to work fine
424 * now starting either before or after the kernel -bwb
426 #if 0
427 while((c = getDebugChar()) != '$');
428 while((c = getDebugChar()) != '#');
429 c = getDebugChar(); /* eat first csum byte */
430 c = getDebugChar(); /* eat second csum byte */
431 putDebugChar('+'); /* ack it */
432 #endif
434 initialized = 1; /* connect! */
435 restore_flags(flags);
438 /* Convert the SPARC hardware trap type code to a unix signal number. */
440 static int
441 computeSignal(int tt)
443 struct hard_trap_info *ht;
445 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
446 if (ht->tt == tt)
447 return ht->signo;
449 return SIGHUP; /* default for things we don't know about */
453 * While we find nice hex chars, build an int.
454 * Return number of chars processed.
457 static int
458 hexToInt(char **ptr, int *intValue)
460 int numChars = 0;
461 int hexValue;
463 *intValue = 0;
465 while (**ptr) {
466 hexValue = hex(**ptr);
467 if (hexValue < 0)
468 break;
470 *intValue = (*intValue << 4) | hexValue;
471 numChars ++;
473 (*ptr)++;
476 return (numChars);
480 * This function does all command processing for interfacing to gdb. It
481 * returns 1 if you should skip the instruction at the trap address, 0
482 * otherwise.
485 extern void breakinst(void);
487 void
488 handle_exception (unsigned long *registers)
490 int tt; /* Trap type */
491 int sigval;
492 int addr;
493 int length;
494 char *ptr;
495 unsigned long *sp;
497 /* First, we must force all of the windows to be spilled out */
499 asm("save %sp, -64, %sp\n\t"
500 "save %sp, -64, %sp\n\t"
501 "save %sp, -64, %sp\n\t"
502 "save %sp, -64, %sp\n\t"
503 "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 "restore\n\t"
508 "restore\n\t"
509 "restore\n\t"
510 "restore\n\t"
511 "restore\n\t"
512 "restore\n\t"
513 "restore\n\t"
514 "restore\n\t");
516 lock_kernel();
517 if (registers[PC] == (unsigned long)breakinst) {
518 /* Skip over breakpoint trap insn */
519 registers[PC] = registers[NPC];
520 registers[NPC] += 4;
523 sp = (unsigned long *)registers[SP];
525 tt = (registers[TBR] >> 4) & 0xff;
527 /* reply to host that an exception has occurred */
528 sigval = computeSignal(tt);
529 ptr = remcomOutBuffer;
531 *ptr++ = 'T';
532 *ptr++ = hexchars[sigval >> 4];
533 *ptr++ = hexchars[sigval & 0xf];
535 *ptr++ = hexchars[PC >> 4];
536 *ptr++ = hexchars[PC & 0xf];
537 *ptr++ = ':';
538 ptr = mem2hex((char *)&registers[PC], ptr, 4);
539 *ptr++ = ';';
541 *ptr++ = hexchars[FP >> 4];
542 *ptr++ = hexchars[FP & 0xf];
543 *ptr++ = ':';
544 ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
545 *ptr++ = ';';
547 *ptr++ = hexchars[SP >> 4];
548 *ptr++ = hexchars[SP & 0xf];
549 *ptr++ = ':';
550 ptr = mem2hex((char *)&sp, ptr, 4);
551 *ptr++ = ';';
553 *ptr++ = hexchars[NPC >> 4];
554 *ptr++ = hexchars[NPC & 0xf];
555 *ptr++ = ':';
556 ptr = mem2hex((char *)&registers[NPC], ptr, 4);
557 *ptr++ = ';';
559 *ptr++ = hexchars[O7 >> 4];
560 *ptr++ = hexchars[O7 & 0xf];
561 *ptr++ = ':';
562 ptr = mem2hex((char *)&registers[O7], ptr, 4);
563 *ptr++ = ';';
565 *ptr++ = 0;
567 putpacket(remcomOutBuffer);
569 /* XXX We may want to add some features dealing with poking the
570 * XXX page tables, the real ones on the srmmu, and what is currently
571 * XXX loaded in the sun4/sun4c tlb at this point in time. But this
572 * XXX also required hacking to the gdb sources directly...
575 while (1) {
576 remcomOutBuffer[0] = 0;
578 getpacket(remcomInBuffer);
579 switch (remcomInBuffer[0]) {
580 case '?':
581 remcomOutBuffer[0] = 'S';
582 remcomOutBuffer[1] = hexchars[sigval >> 4];
583 remcomOutBuffer[2] = hexchars[sigval & 0xf];
584 remcomOutBuffer[3] = 0;
585 break;
587 case 'd':
588 /* toggle debug flag */
589 break;
591 case 'g': /* return the value of the CPU registers */
593 ptr = remcomOutBuffer;
594 /* G & O regs */
595 ptr = mem2hex((char *)registers, ptr, 16 * 4);
596 /* L & I regs */
597 ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
598 /* Floating point */
599 memset(ptr, '0', 32 * 8);
600 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
601 mem2hex((char *)&registers[Y], (ptr + 32 * 4 * 2), (8 * 4));
603 break;
605 case 'G': /* set the value of the CPU registers - return OK */
607 unsigned long *newsp, psr;
609 psr = registers[PSR];
611 ptr = &remcomInBuffer[1];
612 /* G & O regs */
613 hex2mem(ptr, (char *)registers, 16 * 4);
614 /* L & I regs */
615 hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
616 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
617 hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y], 8 * 4);
619 /* See if the stack pointer has moved. If so,
620 * then copy the saved locals and ins to the
621 * new location. This keeps the window
622 * overflow and underflow routines happy.
625 newsp = (unsigned long *)registers[SP];
626 if (sp != newsp)
627 sp = memcpy(newsp, sp, 16 * 4);
629 /* Don't allow CWP to be modified. */
631 if (psr != registers[PSR])
632 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
634 strcpy(remcomOutBuffer,"OK");
636 break;
638 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
639 /* Try to read %x,%x. */
641 ptr = &remcomInBuffer[1];
643 if (hexToInt(&ptr, &addr)
644 && *ptr++ == ','
645 && hexToInt(&ptr, &length)) {
646 if (mem2hex((char *)addr, remcomOutBuffer, length))
647 break;
649 strcpy (remcomOutBuffer, "E03");
650 } else {
651 strcpy(remcomOutBuffer,"E01");
653 break;
655 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
656 /* Try to read '%x,%x:'. */
658 ptr = &remcomInBuffer[1];
660 if (hexToInt(&ptr, &addr)
661 && *ptr++ == ','
662 && hexToInt(&ptr, &length)
663 && *ptr++ == ':') {
664 if (hex2mem(ptr, (char *)addr, length)) {
665 strcpy(remcomOutBuffer, "OK");
666 } else {
667 strcpy(remcomOutBuffer, "E03");
669 } else {
670 strcpy(remcomOutBuffer, "E02");
672 break;
674 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
675 /* try to read optional parameter, pc unchanged if no parm */
677 ptr = &remcomInBuffer[1];
678 if (hexToInt(&ptr, &addr)) {
679 registers[PC] = addr;
680 registers[NPC] = addr + 4;
683 /* Need to flush the instruction cache here, as we may have deposited a
684 * breakpoint, and the icache probably has no way of knowing that a data ref to
685 * some location may have changed something that is in the instruction cache.
687 flush_cache_all();
688 unlock_kernel();
689 return;
691 /* kill the program */
692 case 'k' : /* do nothing */
693 break;
694 case 'r': /* Reset */
695 asm ("call 0\n\t"
696 "nop\n\t");
697 break;
698 } /* switch */
700 /* reply to the request */
701 putpacket(remcomOutBuffer);
702 } /* while(1) */
705 /* This function will generate a breakpoint exception. It is used at the
706 beginning of a program to sync up with a debugger and can be used
707 otherwise as a quick means to stop program execution and "break" into
708 the debugger. */
710 void
711 breakpoint(void)
713 if (!initialized)
714 return;
716 /* Again, watch those c-prefixes for ELF kernels */
717 #if defined(__svr4__) || defined(__ELF__)
718 asm(" .globl breakinst
720 breakinst: ta 1
722 #else
723 asm(" .globl _breakinst
725 _breakinst: ta 1
727 #endif