Import 2.3.11pre5
[davej-history.git] / arch / ppc / kernel / ppc-stub.c
blobd7fef0869b7ae7eb7880f9d1475bf13c990d310a
1 /* $Id: ppc-stub.c,v 1.4 1998/07/28 08:25:01 paulus Exp $
2 * ppc-stub.c: KGDB support for the Linux kernel.
4 * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
5 * some stuff borrowed from Paul Mackerras' xmon
6 * Copyright (C) 1998 Michael AK Tesch (tesch@cs.wisc.edu)
8 * Modifications to run under Linux
9 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
11 * This file originally came from the gdb sources, and the
12 * copyright notices have been retained below.
15 /****************************************************************************
17 THIS SOFTWARE IS NOT COPYRIGHTED
19 HP offers the following for use in the public domain. HP makes no
20 warranty with regard to the software or its performance and the
21 user accepts the software "AS IS" with all faults.
23 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
24 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
25 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27 ****************************************************************************/
29 /****************************************************************************
30 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
32 * Module name: remcom.c $
33 * Revision: 1.34 $
34 * Date: 91/03/09 12:29:49 $
35 * Contributor: Lake Stevens Instrument Division$
37 * Description: low level support for gdb debugger. $
39 * Considerations: only works on target hardware $
41 * Written by: Glenn Engel $
42 * ModuleState: Experimental $
44 * NOTES: See Below $
46 * Modified for SPARC by Stu Grossman, Cygnus Support.
48 * This code has been extensively tested on the Fujitsu SPARClite demo board.
50 * To enable debugger support, two things need to happen. One, a
51 * call to set_debug_traps() is necessary in order to allow any breakpoints
52 * or error conditions to be properly intercepted and reported to gdb.
53 * Two, a breakpoint needs to be generated to begin communication. This
54 * is most easily accomplished by a call to breakpoint(). Breakpoint()
55 * simulates a breakpoint by executing a trap #1.
57 *************
59 * The following gdb commands are supported:
61 * command function Return value
63 * g return the value of the CPU registers hex data or ENN
64 * G set the value of the CPU registers OK or ENN
65 * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz
67 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
68 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
70 * c Resume at current address SNN ( signal NN)
71 * cAA..AA Continue at address AA..AA SNN
73 * s Step one instruction SNN
74 * sAA..AA Step one instruction from AA..AA SNN
76 * k kill
78 * ? What was the last sigval ? SNN (signal NN)
80 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
81 * baud rate
83 * All commands and responses are sent with a packet which includes a
84 * checksum. A packet consists of
86 * $<packet info>#<checksum>.
88 * where
89 * <packet info> :: <characters representing the command or response>
90 * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
92 * When a packet is received, it is first acknowledged with either '+' or '-'.
93 * '+' indicates a successful transfer. '-' indicates a failed transfer.
95 * Example:
97 * Host: Reply:
98 * $m0,10#2a +$00010203040506070809101112131415#42
100 ****************************************************************************/
102 #include <linux/kernel.h>
103 #include <linux/string.h>
104 #include <linux/mm.h>
105 #include <linux/smp.h>
106 #include <linux/smp_lock.h>
108 #include <asm/system.h>
109 #include <asm/signal.h>
110 #include <asm/kgdb.h>
111 #include <asm/pgtable.h>
112 #include <asm/ptrace.h>
114 void breakinst(void);
117 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
118 * at least NUMREGBYTES*2 are needed for register packets
120 #define BUFMAX 2048
121 static char remcomInBuffer[BUFMAX];
122 static char remcomOutBuffer[BUFMAX];
124 static int initialized = 0;
125 static int kgdb_active = 0;
126 static u_int fault_jmp_buf[100];
127 static int kdebug;
129 static const char hexchars[]="0123456789abcdef";
131 /* Place where we save old trap entries for restoration - sparc*/
132 /* struct tt_entry kgdb_savettable[256]; */
133 /* typedef void (*trapfunc_t)(void); */
135 #if 0
136 /* Install an exception handler for kgdb */
137 static void exceptionHandler(int tnum, unsigned int *tfunc)
139 /* We are dorking with a live trap table, all irqs off */
141 #endif
144 kgdb_setjmp(long *buf)
146 asm ("mflr 0; stw 0,0(%0);"
147 "stw 1,4(%0); stw 2,8(%0);"
148 "mfcr 0; stw 0,12(%0);"
149 "stmw 13,16(%0)"
150 : : "r" (buf));
151 /* XXX should save fp regs as well */
152 return 0;
154 void
155 kgdb_longjmp(long *buf, int val)
157 if (val == 0)
158 val = 1;
159 asm ("lmw 13,16(%0);"
160 "lwz 0,12(%0); mtcrf 0x38,0;"
161 "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
162 "mtlr 0; mr 3,%1"
163 : : "r" (buf), "r" (val));
165 /* Convert ch from a hex digit to an int */
166 static int
167 hex(unsigned char ch)
169 if (ch >= 'a' && ch <= 'f')
170 return ch-'a'+10;
171 if (ch >= '0' && ch <= '9')
172 return ch-'0';
173 if (ch >= 'A' && ch <= 'F')
174 return ch-'A'+10;
175 return -1;
178 /* Convert the memory pointed to by mem into hex, placing result in buf.
179 * Return a pointer to the last char put in buf (null), in case of mem fault,
180 * return 0.
182 static unsigned char *
183 mem2hex(char *mem, char *buf, int count)
185 unsigned char ch;
187 if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
188 debugger_fault_handler = kgdb_fault_handler;
189 while (count-- > 0) {
190 ch = *mem++;
191 *buf++ = hexchars[ch >> 4];
192 *buf++ = hexchars[ch & 0xf];
194 } else {
195 /* error condition */
197 debugger_fault_handler = 0;
198 *buf = 0;
199 return buf;
202 /* convert the hex array pointed to by buf into binary to be placed in mem
203 * return a pointer to the character AFTER the last byte written.
205 static char *
206 hex2mem(char *buf, char *mem, int count)
208 int i;
209 unsigned char ch;
211 if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
212 debugger_fault_handler = kgdb_fault_handler;
213 for (i=0; i<count; i++) {
214 ch = hex(*buf++) << 4;
215 ch |= hex(*buf++);
216 *mem++ = ch;
218 flush_icache_range((int)mem, (int)mem+count);
219 } else {
220 /* error condition */
222 debugger_fault_handler = 0;
223 return mem;
227 * While we find nice hex chars, build an int.
228 * Return number of chars processed.
230 static int
231 hexToInt(char **ptr, int *intValue)
233 int numChars = 0;
234 int hexValue;
236 *intValue = 0;
238 if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
239 debugger_fault_handler = kgdb_fault_handler;
240 while (**ptr) {
241 hexValue = hex(**ptr);
242 if (hexValue < 0)
243 break;
245 *intValue = (*intValue << 4) | hexValue;
246 numChars ++;
248 (*ptr)++;
250 } else {
251 /* error condition */
253 debugger_fault_handler = 0;
255 return (numChars);
258 /* scan for the sequence $<data>#<checksum> */
259 static void
260 getpacket(char *buffer)
262 unsigned char checksum;
263 unsigned char xmitcsum;
264 int i;
265 int count;
266 unsigned char ch;
268 do {
269 /* wait around for the start character, ignore all other
270 * characters */
271 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
273 checksum = 0;
274 xmitcsum = -1;
276 count = 0;
278 /* now, read until a # or end of buffer is found */
279 while (count < BUFMAX) {
280 ch = getDebugChar() & 0x7f;
281 if (ch == '#')
282 break;
283 checksum = checksum + ch;
284 buffer[count] = ch;
285 count = count + 1;
288 if (count >= BUFMAX)
289 continue;
291 buffer[count] = 0;
293 if (ch == '#') {
294 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
295 xmitcsum |= hex(getDebugChar() & 0x7f);
296 if (checksum != xmitcsum)
297 putDebugChar('-'); /* failed checksum */
298 else {
299 putDebugChar('+'); /* successful transfer */
300 /* if a sequence char is present, reply the ID */
301 if (buffer[2] == ':') {
302 putDebugChar(buffer[0]);
303 putDebugChar(buffer[1]);
304 /* remove sequence chars from buffer */
305 count = strlen(buffer);
306 for (i=3; i <= count; i++)
307 buffer[i-3] = buffer[i];
311 } while (checksum != xmitcsum);
314 /* send the packet in buffer. */
315 static void putpacket(unsigned char *buffer)
317 unsigned char checksum;
318 int count;
319 unsigned char ch, recv;
321 /* $<packet info>#<checksum>. */
322 do {
323 putDebugChar('$');
324 checksum = 0;
325 count = 0;
327 while ((ch = buffer[count])) {
328 putDebugChar(ch);
329 checksum += ch;
330 count += 1;
333 putDebugChar('#');
334 putDebugChar(hexchars[checksum >> 4]);
335 putDebugChar(hexchars[checksum & 0xf]);
336 recv = getDebugChar();
337 } while ((recv & 0x7f) != '+');
340 static void kgdb_flush_cache_all(void)
342 flush_instruction_cache();
345 static inline int get_msr()
347 int msr;
348 asm volatile("mfmsr %0" : "=r" (msr):);
349 return msr;
352 static inline void set_msr(int msr)
354 asm volatile("mfmsr %0" : : "r" (msr));
357 /* Set up exception handlers for tracing and breakpoints
358 * [could be called kgdb_init()]
360 void set_debug_traps(void)
362 #if 0
363 unsigned char c;
365 save_and_cli(flags);
367 /* In case GDB is started before us, ack any packets (presumably
368 * "$?#xx") sitting there.
370 * I've found this code causes more problems than it solves,
371 * so that's why it's commented out. GDB seems to work fine
372 * now starting either before or after the kernel -bwb
375 while((c = getDebugChar()) != '$');
376 while((c = getDebugChar()) != '#');
377 c = getDebugChar(); /* eat first csum byte */
378 c = getDebugChar(); /* eat second csum byte */
379 putDebugChar('+'); /* ack it */
380 #endif
381 debugger = kgdb;
382 debugger_bpt = kgdb_bpt;
383 debugger_sstep = kgdb_sstep;
384 debugger_iabr_match = kgdb_iabr_match;
385 debugger_dabr_match = kgdb_dabr_match;
387 initialized = 1;
390 static void kgdb_fault_handler(struct pt_regs *regs)
392 kgdb_longjmp((long*)fault_jmp_buf, 1);
395 int kgdb_bpt(struct pt_regs *regs)
397 handle_exception(regs);
398 return 1;
401 int kgdb_sstep(struct pt_regs *regs)
403 handle_exception(regs);
404 return 1;
407 void kgdb(struct pt_regs *regs)
409 handle_exception(regs);
412 int kgdb_iabr_match(struct pt_regs *regs)
414 printk("kgdb doesn't support iabr, what?!?\n");
415 handle_exception(regs);
416 return 1;
419 int kgdb_dabr_match(struct pt_regs *regs)
421 printk("kgdb doesn't support dabr, what?!?\n");
422 handle_exception(regs);
423 return 1;
426 /* Convert the SPARC hardware trap type code to a unix signal number. */
428 * This table contains the mapping between PowerPC hardware trap types, and
429 * signals, which are primarily what GDB understands.
431 static struct hard_trap_info
433 unsigned int tt; /* Trap type code for powerpc */
434 unsigned char signo; /* Signal that we map this trap into */
435 } hard_trap_info[] = {
436 { 0x200, SIGSEGV }, /* machine check */
437 { 0x300, SIGSEGV }, /* address error (store) */
438 { 0x400, SIGBUS }, /* instruction bus error */
439 { 0x500, SIGINT }, /* interrupt */
440 { 0x600, SIGBUS }, /* alingment */
441 { 0x700, SIGILL }, /* reserved instruction or sumpin' */
442 { 0x800, SIGFPE }, /* fpu unavail */
443 { 0x900, SIGALRM }, /* decrementer */
444 { 0xa00, SIGILL }, /* reserved */
445 { 0xb00, SIGILL }, /* reserved */
446 { 0xc00, SIGCHLD }, /* syscall */
447 { 0xd00, SIGINT }, /* watch */
448 { 0xe00, SIGFPE }, /* fp assist */
449 { 0, 0} /* Must be last */
452 static int computeSignal(unsigned int tt)
454 struct hard_trap_info *ht;
456 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
457 if (ht->tt == tt)
458 return ht->signo;
460 return SIGHUP; /* default for things we don't know about */
464 * This function does all command processing for interfacing to gdb.
466 static void
467 handle_exception (struct pt_regs *regs)
469 int sigval;
470 int addr;
471 int length;
472 char *ptr;
473 unsigned int msr;
475 if (debugger_fault_handler) {
476 debugger_fault_handler(regs);
477 panic("kgdb longjump failed!\n");
479 if (kgdb_active) {
480 printk("interrupt while in kgdb, returning\n");
481 return;
483 kgdb_active = 1;
485 printk("kgdb: entering handle_exception; trap [0x%x]\n",
486 (unsigned int)regs->trap);
488 kgdb_interruptible(0);
489 lock_kernel();
490 msr = get_msr();
491 set_msr(msr & ~MSR_EE); /* disable interrupts */
493 if (regs->nip == (unsigned long)breakinst) {
494 /* Skip over breakpoint trap insn */
495 regs->nip += 4;
498 /* reply to host that an exception has occurred */
499 sigval = computeSignal(regs->trap);
500 ptr = remcomOutBuffer;
502 *ptr++ = 'S';
503 *ptr++ = hexchars[sigval >> 4];
504 *ptr++ = hexchars[sigval & 0xf];
506 *ptr++ = 0;
508 putpacket(remcomOutBuffer);
510 /* XXX We may want to add some features dealing with poking the
511 * XXX page tables, ... (look at sparc-stub.c for more info)
512 * XXX also required hacking to the gdb sources directly...
515 while (1) {
516 remcomOutBuffer[0] = 0;
518 getpacket(remcomInBuffer);
519 switch (remcomInBuffer[0]) {
520 case '?': /* report most recent signal */
521 remcomOutBuffer[0] = 'S';
522 remcomOutBuffer[1] = hexchars[sigval >> 4];
523 remcomOutBuffer[2] = hexchars[sigval & 0xf];
524 remcomOutBuffer[3] = 0;
525 break;
526 #if 0
527 case 'q': /* this screws up gdb for some reason...*/
529 extern long _start, sdata, __bss_start;
531 ptr = &remcomInBuffer[1];
532 if (strncmp(ptr, "Offsets", 7) != 0)
533 break;
535 ptr = remcomOutBuffer;
536 sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
537 &_start, &sdata, &__bss_start);
538 break;
540 #endif
541 case 'd':
542 /* toggle debug flag */
543 kdebug ^= 1;
544 break;
546 case 'g': /* return the value of the CPU registers.
547 * some of them are non-PowerPC names :(
548 * they are stored in gdb like:
549 * struct {
550 * u32 gpr[32];
551 * f64 fpr[32];
552 * u32 pc, ps, cnd, lr; (ps=msr)
553 * u32 cnt, xer, mq;
557 int i;
558 ptr = remcomOutBuffer;
559 /* General Purpose Regs */
560 ptr = mem2hex((char *)regs, ptr, 32 * 4);
561 /* Floating Point Regs - FIXME */
562 /*ptr = mem2hex((char *), ptr, 32 * 8);*/
563 for(i=0; i<(32*8*2); i++) { /* 2chars/byte */
564 ptr[i] = '0';
566 ptr += 32*8*2;
567 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
568 ptr = mem2hex((char *)&regs->nip, ptr, 4);
569 ptr = mem2hex((char *)&regs->msr, ptr, 4);
570 ptr = mem2hex((char *)&regs->ccr, ptr, 4);
571 ptr = mem2hex((char *)&regs->link, ptr, 4);
572 ptr = mem2hex((char *)&regs->ctr, ptr, 4);
573 ptr = mem2hex((char *)&regs->xer, ptr, 4);
575 break;
577 case 'G': /* set the value of the CPU registers */
579 ptr = &remcomInBuffer[1];
582 * If the stack pointer has moved, you should pray.
583 * (cause only god can help you).
586 /* General Purpose Regs */
587 hex2mem(ptr, (char *)regs, 32 * 4);
589 /* Floating Point Regs - FIXME?? */
590 /*ptr = hex2mem(ptr, ??, 32 * 8);*/
591 ptr += 32*8*2;
593 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
594 ptr = hex2mem(ptr, (char *)&regs->nip, 4);
595 ptr = hex2mem(ptr, (char *)&regs->msr, 4);
596 ptr = hex2mem(ptr, (char *)&regs->ccr, 4);
597 ptr = hex2mem(ptr, (char *)&regs->link, 4);
598 ptr = hex2mem(ptr, (char *)&regs->ctr, 4);
599 ptr = hex2mem(ptr, (char *)&regs->xer, 4);
601 strcpy(remcomOutBuffer,"OK");
603 break;
604 case 'H':
605 /* don't do anything, yet, just acknowledge */
606 hexToInt(&ptr, &addr);
607 strcpy(remcomOutBuffer,"OK");
608 break;
610 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
611 /* Try to read %x,%x. */
613 ptr = &remcomInBuffer[1];
615 if (hexToInt(&ptr, &addr)
616 && *ptr++ == ','
617 && hexToInt(&ptr, &length)) {
618 if (mem2hex((char *)addr, remcomOutBuffer,length))
619 break;
620 strcpy (remcomOutBuffer, "E03");
621 } else {
622 strcpy(remcomOutBuffer,"E01");
624 break;
626 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
627 /* Try to read '%x,%x:'. */
629 ptr = &remcomInBuffer[1];
631 if (hexToInt(&ptr, &addr)
632 && *ptr++ == ','
633 && hexToInt(&ptr, &length)
634 && *ptr++ == ':') {
635 if (hex2mem(ptr, (char *)addr, length)) {
636 strcpy(remcomOutBuffer, "OK");
637 } else {
638 strcpy(remcomOutBuffer, "E03");
640 } else {
641 strcpy(remcomOutBuffer, "E02");
643 break;
646 case 'k': /* kill the program, actually just continue */
647 case 'c': /* cAA..AA Continue; address AA..AA optional */
648 /* try to read optional parameter, pc unchanged if no parm */
650 ptr = &remcomInBuffer[1];
651 if (hexToInt(&ptr, &addr)) {
652 regs->nip = addr;
655 /* Need to flush the instruction cache here, as we may have deposited a
656 * breakpoint, and the icache probably has no way of knowing that a data ref to
657 * some location may have changed something that is in the instruction cache.
659 kgdb_flush_cache_all();
660 set_msr(msr);
661 kgdb_interruptible(1);
662 unlock_kernel();
663 kgdb_active = 0;
664 return;
666 case 's':
667 kgdb_flush_cache_all();
668 regs->msr |= MSR_SE;
669 set_msr(msr | MSR_SE);
670 unlock_kernel();
671 kgdb_active = 0;
672 return;
674 case 'r': /* Reset (if user process..exit ???)*/
675 panic("kgdb reset.");
676 break;
677 } /* switch */
678 if (remcomOutBuffer[0] && kdebug) {
679 printk("remcomInBuffer: %s\n", remcomInBuffer);
680 printk("remcomOutBuffer: %s\n", remcomOutBuffer);
682 /* reply to the request */
683 putpacket(remcomOutBuffer);
684 } /* while(1) */
687 /* This function will generate a breakpoint exception. It is used at the
688 beginning of a program to sync up with a debugger and can be used
689 otherwise as a quick means to stop program execution and "break" into
690 the debugger. */
692 void
693 breakpoint(void)
695 if (!initialized) {
696 printk("breakpoint() called b4 kgdb init\n");
697 return;
700 asm(" .globl breakinst
701 breakinst: trap