aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel/ppc-stub.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/kernel/ppc-stub.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/ppc/kernel/ppc-stub.c')
-rw-r--r--arch/ppc/kernel/ppc-stub.c867
1 files changed, 867 insertions, 0 deletions
diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
new file mode 100644
index 000000000000..d61889c24046
--- /dev/null
+++ b/arch/ppc/kernel/ppc-stub.c
@@ -0,0 +1,867 @@
1/*
2 * ppc-stub.c: KGDB support for the Linux kernel.
3 *
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)
7 *
8 * Modifications to run under Linux
9 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
10 *
11 * This file originally came from the gdb sources, and the
12 * copyright notices have been retained below.
13 */
14
15/****************************************************************************
16
17 THIS SOFTWARE IS NOT COPYRIGHTED
18
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.
22
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.
26
27****************************************************************************/
28
29/****************************************************************************
30 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
31 *
32 * Module name: remcom.c $
33 * Revision: 1.34 $
34 * Date: 91/03/09 12:29:49 $
35 * Contributor: Lake Stevens Instrument Division$
36 *
37 * Description: low level support for gdb debugger. $
38 *
39 * Considerations: only works on target hardware $
40 *
41 * Written by: Glenn Engel $
42 * ModuleState: Experimental $
43 *
44 * NOTES: See Below $
45 *
46 * Modified for SPARC by Stu Grossman, Cygnus Support.
47 *
48 * This code has been extensively tested on the Fujitsu SPARClite demo board.
49 *
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.
56 *
57 *************
58 *
59 * The following gdb commands are supported:
60 *
61 * command function Return value
62 *
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
66 *
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
69 *
70 * c Resume at current address SNN ( signal NN)
71 * cAA..AA Continue at address AA..AA SNN
72 *
73 * s Step one instruction SNN
74 * sAA..AA Step one instruction from AA..AA SNN
75 *
76 * k kill
77 *
78 * ? What was the last sigval ? SNN (signal NN)
79 *
80 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
81 * baud rate
82 *
83 * All commands and responses are sent with a packet which includes a
84 * checksum. A packet consists of
85 *
86 * $<packet info>#<checksum>.
87 *
88 * where
89 * <packet info> :: <characters representing the command or response>
90 * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
91 *
92 * When a packet is received, it is first acknowledged with either '+' or '-'.
93 * '+' indicates a successful transfer. '-' indicates a failed transfer.
94 *
95 * Example:
96 *
97 * Host: Reply:
98 * $m0,10#2a +$00010203040506070809101112131415#42
99 *
100 ****************************************************************************/
101
102#include <linux/config.h>
103#include <linux/kernel.h>
104#include <linux/string.h>
105#include <linux/mm.h>
106#include <linux/smp.h>
107#include <linux/smp_lock.h>
108#include <linux/init.h>
109#include <linux/sysrq.h>
110
111#include <asm/cacheflush.h>
112#include <asm/system.h>
113#include <asm/signal.h>
114#include <asm/kgdb.h>
115#include <asm/pgtable.h>
116#include <asm/ptrace.h>
117
118void breakinst(void);
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
125static char remcomInBuffer[BUFMAX];
126static char remcomOutBuffer[BUFMAX];
127
128static int initialized;
129static int kgdb_active;
130static int kgdb_started;
131static u_int fault_jmp_buf[100];
132static int kdebug;
133
134
135static const char hexchars[]="0123456789abcdef";
136
137/* Place where we save old trap entries for restoration - sparc*/
138/* struct tt_entry kgdb_savettable[256]; */
139/* typedef void (*trapfunc_t)(void); */
140
141static void kgdb_fault_handler(struct pt_regs *regs);
142static int handle_exception (struct pt_regs *regs);
143
144#if 0
145/* Install an exception handler for kgdb */
146static void exceptionHandler(int tnum, unsigned int *tfunc)
147{
148 /* We are dorking with a live trap table, all irqs off */
149}
150#endif
151
152int
153kgdb_setjmp(long *buf)
154{
155 asm ("mflr 0; stw 0,0(%0);"
156 "stw 1,4(%0); stw 2,8(%0);"
157 "mfcr 0; stw 0,12(%0);"
158 "stmw 13,16(%0)"
159 : : "r" (buf));
160 /* XXX should save fp regs as well */
161 return 0;
162}
163void
164kgdb_longjmp(long *buf, int val)
165{
166 if (val == 0)
167 val = 1;
168 asm ("lmw 13,16(%0);"
169 "lwz 0,12(%0); mtcrf 0x38,0;"
170 "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
171 "mtlr 0; mr 3,%1"
172 : : "r" (buf), "r" (val));
173}
174/* Convert ch from a hex digit to an int */
175static int
176hex(unsigned char ch)
177{
178 if (ch >= 'a' && ch <= 'f')
179 return ch-'a'+10;
180 if (ch >= '0' && ch <= '9')
181 return ch-'0';
182 if (ch >= 'A' && ch <= 'F')
183 return ch-'A'+10;
184 return -1;
185}
186
187/* Convert the memory pointed to by mem into hex, placing result in buf.
188 * Return a pointer to the last char put in buf (null), in case of mem fault,
189 * return 0.
190 */
191static unsigned char *
192mem2hex(const char *mem, char *buf, int count)
193{
194 unsigned char ch;
195 unsigned short tmp_s;
196 unsigned long tmp_l;
197
198 if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
199 debugger_fault_handler = kgdb_fault_handler;
200
201 /* Accessing 16 bit and 32 bit objects in a single
202 ** load instruction is required to avoid bad side
203 ** effects for some IO registers.
204 */
205
206 if ((count == 2) && (((long)mem & 1) == 0)) {
207 tmp_s = *(unsigned short *)mem;
208 mem += 2;
209 *buf++ = hexchars[(tmp_s >> 12) & 0xf];
210 *buf++ = hexchars[(tmp_s >> 8) & 0xf];
211 *buf++ = hexchars[(tmp_s >> 4) & 0xf];
212 *buf++ = hexchars[tmp_s & 0xf];
213
214 } else if ((count == 4) && (((long)mem & 3) == 0)) {
215 tmp_l = *(unsigned int *)mem;
216 mem += 4;
217 *buf++ = hexchars[(tmp_l >> 28) & 0xf];
218 *buf++ = hexchars[(tmp_l >> 24) & 0xf];
219 *buf++ = hexchars[(tmp_l >> 20) & 0xf];
220 *buf++ = hexchars[(tmp_l >> 16) & 0xf];
221 *buf++ = hexchars[(tmp_l >> 12) & 0xf];
222 *buf++ = hexchars[(tmp_l >> 8) & 0xf];
223 *buf++ = hexchars[(tmp_l >> 4) & 0xf];
224 *buf++ = hexchars[tmp_l & 0xf];
225
226 } else {
227 while (count-- > 0) {
228 ch = *mem++;
229 *buf++ = hexchars[ch >> 4];
230 *buf++ = hexchars[ch & 0xf];
231 }
232 }
233
234 } else {
235 /* error condition */
236 }
237 debugger_fault_handler = NULL;
238 *buf = 0;
239 return buf;
240}
241
242/* convert the hex array pointed to by buf into binary to be placed in mem
243 * return a pointer to the character AFTER the last byte written.
244*/
245static char *
246hex2mem(char *buf, char *mem, int count)
247{
248 unsigned char ch;
249 int i;
250 char *orig_mem;
251 unsigned short tmp_s;
252 unsigned long tmp_l;
253
254 orig_mem = mem;
255
256 if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
257 debugger_fault_handler = kgdb_fault_handler;
258
259 /* Accessing 16 bit and 32 bit objects in a single
260 ** store instruction is required to avoid bad side
261 ** effects for some IO registers.
262 */
263
264 if ((count == 2) && (((long)mem & 1) == 0)) {
265 tmp_s = hex(*buf++) << 12;
266 tmp_s |= hex(*buf++) << 8;
267 tmp_s |= hex(*buf++) << 4;
268 tmp_s |= hex(*buf++);
269
270 *(unsigned short *)mem = tmp_s;
271 mem += 2;
272
273 } else if ((count == 4) && (((long)mem & 3) == 0)) {
274 tmp_l = hex(*buf++) << 28;
275 tmp_l |= hex(*buf++) << 24;
276 tmp_l |= hex(*buf++) << 20;
277 tmp_l |= hex(*buf++) << 16;
278 tmp_l |= hex(*buf++) << 12;
279 tmp_l |= hex(*buf++) << 8;
280 tmp_l |= hex(*buf++) << 4;
281 tmp_l |= hex(*buf++);
282
283 *(unsigned long *)mem = tmp_l;
284 mem += 4;
285
286 } else {
287 for (i=0; i<count; i++) {
288 ch = hex(*buf++) << 4;
289 ch |= hex(*buf++);
290 *mem++ = ch;
291 }
292 }
293
294
295 /*
296 ** Flush the data cache, invalidate the instruction cache.
297 */
298 flush_icache_range((int)orig_mem, (int)orig_mem + count - 1);
299
300 } else {
301 /* error condition */
302 }
303 debugger_fault_handler = NULL;
304 return mem;
305}
306
307/*
308 * While we find nice hex chars, build an int.
309 * Return number of chars processed.
310 */
311static int
312hexToInt(char **ptr, int *intValue)
313{
314 int numChars = 0;
315 int hexValue;
316
317 *intValue = 0;
318
319 if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
320 debugger_fault_handler = kgdb_fault_handler;
321 while (**ptr) {
322 hexValue = hex(**ptr);
323 if (hexValue < 0)
324 break;
325
326 *intValue = (*intValue << 4) | hexValue;
327 numChars ++;
328
329 (*ptr)++;
330 }
331 } else {
332 /* error condition */
333 }
334 debugger_fault_handler = NULL;
335
336 return (numChars);
337}
338
339/* scan for the sequence $<data>#<checksum> */
340static void
341getpacket(char *buffer)
342{
343 unsigned char checksum;
344 unsigned char xmitcsum;
345 int i;
346 int count;
347 unsigned char ch;
348
349 do {
350 /* wait around for the start character, ignore all other
351 * characters */
352 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
353
354 checksum = 0;
355 xmitcsum = -1;
356
357 count = 0;
358
359 /* now, read until a # or end of buffer is found */
360 while (count < BUFMAX) {
361 ch = getDebugChar() & 0x7f;
362 if (ch == '#')
363 break;
364 checksum = checksum + ch;
365 buffer[count] = ch;
366 count = count + 1;
367 }
368
369 if (count >= BUFMAX)
370 continue;
371
372 buffer[count] = 0;
373
374 if (ch == '#') {
375 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
376 xmitcsum |= hex(getDebugChar() & 0x7f);
377 if (checksum != xmitcsum)
378 putDebugChar('-'); /* failed checksum */
379 else {
380 putDebugChar('+'); /* successful transfer */
381 /* if a sequence char is present, reply the ID */
382 if (buffer[2] == ':') {
383 putDebugChar(buffer[0]);
384 putDebugChar(buffer[1]);
385 /* remove sequence chars from buffer */
386 count = strlen(buffer);
387 for (i=3; i <= count; i++)
388 buffer[i-3] = buffer[i];
389 }
390 }
391 }
392 } while (checksum != xmitcsum);
393}
394
395/* send the packet in buffer. */
396static void putpacket(unsigned char *buffer)
397{
398 unsigned char checksum;
399 int count;
400 unsigned char ch, recv;
401
402 /* $<packet info>#<checksum>. */
403 do {
404 putDebugChar('$');
405 checksum = 0;
406 count = 0;
407
408 while ((ch = buffer[count])) {
409 putDebugChar(ch);
410 checksum += ch;
411 count += 1;
412 }
413
414 putDebugChar('#');
415 putDebugChar(hexchars[checksum >> 4]);
416 putDebugChar(hexchars[checksum & 0xf]);
417 recv = getDebugChar();
418 } while ((recv & 0x7f) != '+');
419}
420
421static void kgdb_flush_cache_all(void)
422{
423 flush_instruction_cache();
424}
425
426/* Set up exception handlers for tracing and breakpoints
427 * [could be called kgdb_init()]
428 */
429void set_debug_traps(void)
430{
431#if 0
432 unsigned char c;
433
434 save_and_cli(flags);
435
436 /* In case GDB is started before us, ack any packets (presumably
437 * "$?#xx") sitting there.
438 *
439 * I've found this code causes more problems than it solves,
440 * so that's why it's commented out. GDB seems to work fine
441 * now starting either before or after the kernel -bwb
442 */
443
444 while((c = getDebugChar()) != '$');
445 while((c = getDebugChar()) != '#');
446 c = getDebugChar(); /* eat first csum byte */
447 c = getDebugChar(); /* eat second csum byte */
448 putDebugChar('+'); /* ack it */
449#endif
450 debugger = kgdb;
451 debugger_bpt = kgdb_bpt;
452 debugger_sstep = kgdb_sstep;
453 debugger_iabr_match = kgdb_iabr_match;
454 debugger_dabr_match = kgdb_dabr_match;
455
456 initialized = 1;
457}
458
459static void kgdb_fault_handler(struct pt_regs *regs)
460{
461 kgdb_longjmp((long*)fault_jmp_buf, 1);
462}
463
464int kgdb_bpt(struct pt_regs *regs)
465{
466 return handle_exception(regs);
467}
468
469int kgdb_sstep(struct pt_regs *regs)
470{
471 return handle_exception(regs);
472}
473
474void kgdb(struct pt_regs *regs)
475{
476 handle_exception(regs);
477}
478
479int kgdb_iabr_match(struct pt_regs *regs)
480{
481 printk(KERN_ERR "kgdb doesn't support iabr, what?!?\n");
482 return handle_exception(regs);
483}
484
485int kgdb_dabr_match(struct pt_regs *regs)
486{
487 printk(KERN_ERR "kgdb doesn't support dabr, what?!?\n");
488 return handle_exception(regs);
489}
490
491/* Convert the hardware trap type code to a unix signal number. */
492/*
493 * This table contains the mapping between PowerPC hardware trap types, and
494 * signals, which are primarily what GDB understands.
495 */
496static struct hard_trap_info
497{
498 unsigned int tt; /* Trap type code for powerpc */
499 unsigned char signo; /* Signal that we map this trap into */
500} hard_trap_info[] = {
501#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
502 { 0x100, SIGINT }, /* critical input interrupt */
503 { 0x200, SIGSEGV }, /* machine check */
504 { 0x300, SIGSEGV }, /* data storage */
505 { 0x400, SIGBUS }, /* instruction storage */
506 { 0x500, SIGINT }, /* interrupt */
507 { 0x600, SIGBUS }, /* alignment */
508 { 0x700, SIGILL }, /* program */
509 { 0x800, SIGILL }, /* reserved */
510 { 0x900, SIGILL }, /* reserved */
511 { 0xa00, SIGILL }, /* reserved */
512 { 0xb00, SIGILL }, /* reserved */
513 { 0xc00, SIGCHLD }, /* syscall */
514 { 0xd00, SIGILL }, /* reserved */
515 { 0xe00, SIGILL }, /* reserved */
516 { 0xf00, SIGILL }, /* reserved */
517 /*
518 ** 0x1000 PIT
519 ** 0x1010 FIT
520 ** 0x1020 watchdog
521 ** 0x1100 data TLB miss
522 ** 0x1200 instruction TLB miss
523 */
524 { 0x2002, SIGTRAP}, /* debug */
525#else
526 { 0x200, SIGSEGV }, /* machine check */
527 { 0x300, SIGSEGV }, /* address error (store) */
528 { 0x400, SIGBUS }, /* instruction bus error */
529 { 0x500, SIGINT }, /* interrupt */
530 { 0x600, SIGBUS }, /* alingment */
531 { 0x700, SIGTRAP }, /* breakpoint trap */
532 { 0x800, SIGFPE }, /* fpu unavail */
533 { 0x900, SIGALRM }, /* decrementer */
534 { 0xa00, SIGILL }, /* reserved */
535 { 0xb00, SIGILL }, /* reserved */
536 { 0xc00, SIGCHLD }, /* syscall */
537 { 0xd00, SIGTRAP }, /* single-step/watch */
538 { 0xe00, SIGFPE }, /* fp assist */
539#endif
540 { 0, 0} /* Must be last */
541
542};
543
544static int computeSignal(unsigned int tt)
545{
546 struct hard_trap_info *ht;
547
548 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
549 if (ht->tt == tt)
550 return ht->signo;
551
552 return SIGHUP; /* default for things we don't know about */
553}
554
555#define PC_REGNUM 64
556#define SP_REGNUM 1
557
558/*
559 * This function does all command processing for interfacing to gdb.
560 */
561static int
562handle_exception (struct pt_regs *regs)
563{
564 int sigval;
565 int addr;
566 int length;
567 char *ptr;
568 unsigned int msr;
569
570 /* We don't handle user-mode breakpoints. */
571 if (user_mode(regs))
572 return 0;
573
574 if (debugger_fault_handler) {
575 debugger_fault_handler(regs);
576 panic("kgdb longjump failed!\n");
577 }
578 if (kgdb_active) {
579 printk(KERN_ERR "interrupt while in kgdb, returning\n");
580 return 0;
581 }
582
583 kgdb_active = 1;
584 kgdb_started = 1;
585
586#ifdef KGDB_DEBUG
587 printk("kgdb: entering handle_exception; trap [0x%x]\n",
588 (unsigned int)regs->trap);
589#endif
590
591 kgdb_interruptible(0);
592 lock_kernel();
593 msr = mfmsr();
594 mtmsr(msr & ~MSR_EE); /* disable interrupts */
595
596 if (regs->nip == (unsigned long)breakinst) {
597 /* Skip over breakpoint trap insn */
598 regs->nip += 4;
599 }
600
601 /* reply to host that an exception has occurred */
602 sigval = computeSignal(regs->trap);
603 ptr = remcomOutBuffer;
604
605 *ptr++ = 'T';
606 *ptr++ = hexchars[sigval >> 4];
607 *ptr++ = hexchars[sigval & 0xf];
608 *ptr++ = hexchars[PC_REGNUM >> 4];
609 *ptr++ = hexchars[PC_REGNUM & 0xf];
610 *ptr++ = ':';
611 ptr = mem2hex((char *)&regs->nip, ptr, 4);
612 *ptr++ = ';';
613 *ptr++ = hexchars[SP_REGNUM >> 4];
614 *ptr++ = hexchars[SP_REGNUM & 0xf];
615 *ptr++ = ':';
616 ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);
617 *ptr++ = ';';
618 *ptr++ = 0;
619
620 putpacket(remcomOutBuffer);
621 if (kdebug)
622 printk("remcomOutBuffer: %s\n", remcomOutBuffer);
623
624 /* XXX We may want to add some features dealing with poking the
625 * XXX page tables, ... (look at sparc-stub.c for more info)
626 * XXX also required hacking to the gdb sources directly...
627 */
628
629 while (1) {
630 remcomOutBuffer[0] = 0;
631
632 getpacket(remcomInBuffer);
633 switch (remcomInBuffer[0]) {
634 case '?': /* report most recent signal */
635 remcomOutBuffer[0] = 'S';
636 remcomOutBuffer[1] = hexchars[sigval >> 4];
637 remcomOutBuffer[2] = hexchars[sigval & 0xf];
638 remcomOutBuffer[3] = 0;
639 break;
640#if 0
641 case 'q': /* this screws up gdb for some reason...*/
642 {
643 extern long _start, sdata, __bss_start;
644
645 ptr = &remcomInBuffer[1];
646 if (strncmp(ptr, "Offsets", 7) != 0)
647 break;
648
649 ptr = remcomOutBuffer;
650 sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
651 &_start, &sdata, &__bss_start);
652 break;
653 }
654#endif
655 case 'd':
656 /* toggle debug flag */
657 kdebug ^= 1;
658 break;
659
660 case 'g': /* return the value of the CPU registers.
661 * some of them are non-PowerPC names :(
662 * they are stored in gdb like:
663 * struct {
664 * u32 gpr[32];
665 * f64 fpr[32];
666 * u32 pc, ps, cnd, lr; (ps=msr)
667 * u32 cnt, xer, mq;
668 * }
669 */
670 {
671 int i;
672 ptr = remcomOutBuffer;
673 /* General Purpose Regs */
674 ptr = mem2hex((char *)regs, ptr, 32 * 4);
675 /* Floating Point Regs - FIXME */
676 /*ptr = mem2hex((char *), ptr, 32 * 8);*/
677 for(i=0; i<(32*8*2); i++) { /* 2chars/byte */
678 ptr[i] = '0';
679 }
680 ptr += 32*8*2;
681 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
682 ptr = mem2hex((char *)&regs->nip, ptr, 4);
683 ptr = mem2hex((char *)&regs->msr, ptr, 4);
684 ptr = mem2hex((char *)&regs->ccr, ptr, 4);
685 ptr = mem2hex((char *)&regs->link, ptr, 4);
686 ptr = mem2hex((char *)&regs->ctr, ptr, 4);
687 ptr = mem2hex((char *)&regs->xer, ptr, 4);
688 }
689 break;
690
691 case 'G': /* set the value of the CPU registers */
692 {
693 ptr = &remcomInBuffer[1];
694
695 /*
696 * If the stack pointer has moved, you should pray.
697 * (cause only god can help you).
698 */
699
700 /* General Purpose Regs */
701 hex2mem(ptr, (char *)regs, 32 * 4);
702
703 /* Floating Point Regs - FIXME?? */
704 /*ptr = hex2mem(ptr, ??, 32 * 8);*/
705 ptr += 32*8*2;
706
707 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
708 ptr = hex2mem(ptr, (char *)&regs->nip, 4);
709 ptr = hex2mem(ptr, (char *)&regs->msr, 4);
710 ptr = hex2mem(ptr, (char *)&regs->ccr, 4);
711 ptr = hex2mem(ptr, (char *)&regs->link, 4);
712 ptr = hex2mem(ptr, (char *)&regs->ctr, 4);
713 ptr = hex2mem(ptr, (char *)&regs->xer, 4);
714
715 strcpy(remcomOutBuffer,"OK");
716 }
717 break;
718 case 'H':
719 /* don't do anything, yet, just acknowledge */
720 hexToInt(&ptr, &addr);
721 strcpy(remcomOutBuffer,"OK");
722 break;
723
724 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
725 /* Try to read %x,%x. */
726
727 ptr = &remcomInBuffer[1];
728
729 if (hexToInt(&ptr, &addr) && *ptr++ == ','
730 && hexToInt(&ptr, &length)) {
731 if (mem2hex((char *)addr, remcomOutBuffer,
732 length))
733 break;
734 strcpy(remcomOutBuffer, "E03");
735 } else
736 strcpy(remcomOutBuffer, "E01");
737 break;
738
739 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
740 /* Try to read '%x,%x:'. */
741
742 ptr = &remcomInBuffer[1];
743
744 if (hexToInt(&ptr, &addr) && *ptr++ == ','
745 && hexToInt(&ptr, &length)
746 && *ptr++ == ':') {
747 if (hex2mem(ptr, (char *)addr, length))
748 strcpy(remcomOutBuffer, "OK");
749 else
750 strcpy(remcomOutBuffer, "E03");
751 flush_icache_range(addr, addr+length);
752 } else
753 strcpy(remcomOutBuffer, "E02");
754 break;
755
756
757 case 'k': /* kill the program, actually just continue */
758 case 'c': /* cAA..AA Continue; address AA..AA optional */
759 /* try to read optional parameter, pc unchanged if no parm */
760
761 ptr = &remcomInBuffer[1];
762 if (hexToInt(&ptr, &addr))
763 regs->nip = addr;
764
765/* Need to flush the instruction cache here, as we may have deposited a
766 * breakpoint, and the icache probably has no way of knowing that a data ref to
767 * some location may have changed something that is in the instruction cache.
768 */
769 kgdb_flush_cache_all();
770 mtmsr(msr);
771
772 kgdb_interruptible(1);
773 unlock_kernel();
774 kgdb_active = 0;
775 if (kdebug) {
776 printk("remcomInBuffer: %s\n", remcomInBuffer);
777 printk("remcomOutBuffer: %s\n", remcomOutBuffer);
778 }
779 return 1;
780
781 case 's':
782 kgdb_flush_cache_all();
783#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
784 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC);
785 regs->msr |= MSR_DE;
786#else
787 regs->msr |= MSR_SE;
788#endif
789 unlock_kernel();
790 kgdb_active = 0;
791 if (kdebug) {
792 printk("remcomInBuffer: %s\n", remcomInBuffer);
793 printk("remcomOutBuffer: %s\n", remcomOutBuffer);
794 }
795 return 1;
796
797 case 'r': /* Reset (if user process..exit ???)*/
798 panic("kgdb reset.");
799 break;
800 } /* switch */
801 if (remcomOutBuffer[0] && kdebug) {
802 printk("remcomInBuffer: %s\n", remcomInBuffer);
803 printk("remcomOutBuffer: %s\n", remcomOutBuffer);
804 }
805 /* reply to the request */
806 putpacket(remcomOutBuffer);
807 } /* while(1) */
808}
809
810/* This function will generate a breakpoint exception. It is used at the
811 beginning of a program to sync up with a debugger and can be used
812 otherwise as a quick means to stop program execution and "break" into
813 the debugger. */
814
815void
816breakpoint(void)
817{
818 if (!initialized) {
819 printk("breakpoint() called b4 kgdb init\n");
820 return;
821 }
822
823 asm(" .globl breakinst \n\
824 breakinst: .long 0x7d821008");
825}
826
827#ifdef CONFIG_KGDB_CONSOLE
828/* Output string in GDB O-packet format if GDB has connected. If nothing
829 output, returns 0 (caller must then handle output). */
830int
831kgdb_output_string (const char* s, unsigned int count)
832{
833 char buffer[512];
834
835 if (!kgdb_started)
836 return 0;
837
838 count = (count <= (sizeof(buffer) / 2 - 2))
839 ? count : (sizeof(buffer) / 2 - 2);
840
841 buffer[0] = 'O';
842 mem2hex (s, &buffer[1], count);
843 putpacket(buffer);
844
845 return 1;
846}
847#endif
848
849static void sysrq_handle_gdb(int key, struct pt_regs *pt_regs,
850 struct tty_struct *tty)
851{
852 printk("Entering GDB stub\n");
853 breakpoint();
854}
855static struct sysrq_key_op sysrq_gdb_op = {
856 .handler = sysrq_handle_gdb,
857 .help_msg = "Gdb",
858 .action_msg = "GDB",
859};
860
861static int gdb_register_sysrq(void)
862{
863 printk("Registering GDB sysrq handler\n");
864 register_sysrq_key('g', &sysrq_gdb_op);
865 return 0;
866}
867module_init(gdb_register_sysrq);