4 #if (CONFIG_COMMANDS & CFG_CMD_KGDB)
7 #include <asm/signal.h>
8 #include <asm/processor.h>
16 kgdb_setjmp(long *buf)
18 asm ("mflr 0; stw 0,0(%0);"
19 "stw 1,4(%0); stw 2,8(%0);"
20 "mfcr 0; stw 0,12(%0);"
23 /* XXX should save fp regs as well */
28 kgdb_longjmp(long *buf, int val)
33 "lwz 0,12(%0); mtcrf 0x38,0;"
34 "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
36 : : "r" (buf), "r" (val));
39 static inline unsigned long
43 asm volatile("mfmsr %0" : "=r" (msr):);
48 set_msr(unsigned long msr)
50 asm volatile("mtmsr %0" : : "r" (msr));
53 /* Convert the SPARC hardware trap type code to a unix signal number. */
55 * This table contains the mapping between PowerPC hardware trap types, and
56 * signals, which are primarily what GDB understands.
58 static struct hard_trap_info
60 unsigned int tt; /* Trap type code for powerpc */
61 unsigned char signo; /* Signal that we map this trap into */
62 } hard_trap_info[] = {
63 { 0x200, SIGSEGV }, /* machine check */
64 { 0x300, SIGSEGV }, /* address error (store) */
65 { 0x400, SIGBUS }, /* instruction bus error */
66 { 0x500, SIGINT }, /* interrupt */
67 { 0x600, SIGBUS }, /* alingment */
68 { 0x700, SIGTRAP }, /* breakpoint trap */
69 { 0x800, SIGFPE }, /* fpu unavail */
70 { 0x900, SIGALRM }, /* decrementer */
71 { 0xa00, SIGILL }, /* reserved */
72 { 0xb00, SIGILL }, /* reserved */
73 { 0xc00, SIGCHLD }, /* syscall */
74 { 0xd00, SIGTRAP }, /* single-step/watch */
75 { 0xe00, SIGFPE }, /* fp assist */
76 { 0, 0} /* Must be last */
80 computeSignal(unsigned int tt)
82 struct hard_trap_info *ht;
84 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
88 return SIGHUP; /* default for things we don't know about */
92 kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
96 kdp->private[0] = msr = get_msr();
97 set_msr(msr & ~MSR_EE); /* disable interrupts */
99 if (regs->nip == (unsigned long)breakinst) {
100 /* Skip over breakpoint trap insn */
103 regs->msr &= ~MSR_SE;
105 /* reply to host that an exception has occurred */
106 kdp->sigval = computeSignal(regs->trap);
110 kdp->regs[0].num = PC_REGNUM;
111 kdp->regs[0].val = regs->nip;
113 kdp->regs[1].num = SP_REGNUM;
114 kdp->regs[1].val = regs->gpr[SP_REGNUM];
118 kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
120 unsigned long msr = kdp->private[0];
122 if (kdp->extype & KGDBEXIT_WITHADDR)
123 regs->nip = kdp->exaddr;
125 switch (kdp->extype & KGDBEXIT_TYPEMASK) {
128 case KGDBEXIT_CONTINUE:
132 case KGDBEXIT_SINGLE:
135 set_msr(msr | MSR_SE);
142 kgdb_trap(struct pt_regs *regs)
147 /* return the value of the CPU registers.
148 * some of them are non-PowerPC names :(
149 * they are stored in gdb like:
153 * u32 pc, ps, cnd, lr; (ps=msr)
158 #define SPACE_REQUIRED ((32*4)+(32*8)+(6*4))
161 /* store floating double indexed */
162 #define STFDI(n,p) __asm__ __volatile__ ("stfd " #n ",%0" : "=o"(p[2*n]))
163 /* store floating double multiple */
164 #define STFDM(p) { STFDI( 0,p); STFDI( 1,p); STFDI( 2,p); STFDI( 3,p); \
165 STFDI( 4,p); STFDI( 5,p); STFDI( 6,p); STFDI( 7,p); \
166 STFDI( 8,p); STFDI( 9,p); STFDI(10,p); STFDI(11,p); \
167 STFDI(12,p); STFDI(13,p); STFDI(14,p); STFDI(15,p); \
168 STFDI(16,p); STFDI(17,p); STFDI(18,p); STFDI(19,p); \
169 STFDI(20,p); STFDI(21,p); STFDI(22,p); STFDI(23,p); \
170 STFDI(24,p); STFDI(25,p); STFDI(26,p); STFDI(27,p); \
171 STFDI(28,p); STFDI(29,p); STFDI(30,p); STFDI(31,p); }
175 kgdb_getregs(struct pt_regs *regs, char *buf, int max)
178 unsigned long *ptr = (unsigned long *)buf;
180 if (max < SPACE_REQUIRED)
181 kgdb_error(KGDBERR_NOSPACE);
183 if ((unsigned long)ptr & 3)
184 kgdb_error(KGDBERR_ALIGNFAULT);
186 /* General Purpose Regs */
187 for (i = 0; i < 32; i++)
188 *ptr++ = regs->gpr[i];
190 /* Floating Point Regs */
195 for (i = 0; i < 32; i++) {
201 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
209 return (SPACE_REQUIRED);
212 /* set the value of the CPU registers */
215 /* load floating double */
216 #define LFD(n,v) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"(v))
217 /* load floating double indexed */
218 #define LFDI(n,p) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"((p)[2*n]))
219 /* load floating double multiple */
220 #define LFDM(p) { LFDI( 0,p); LFDI( 1,p); LFDI( 2,p); LFDI( 3,p); \
221 LFDI( 4,p); LFDI( 5,p); LFDI( 6,p); LFDI( 7,p); \
222 LFDI( 8,p); LFDI( 9,p); LFDI(10,p); LFDI(11,p); \
223 LFDI(12,p); LFDI(13,p); LFDI(14,p); LFDI(15,p); \
224 LFDI(16,p); LFDI(17,p); LFDI(18,p); LFDI(19,p); \
225 LFDI(20,p); LFDI(21,p); LFDI(22,p); LFDI(23,p); \
226 LFDI(24,p); LFDI(25,p); LFDI(26,p); LFDI(27,p); \
227 LFDI(28,p); LFDI(29,p); LFDI(30,p); LFDI(31,p); }
231 kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
233 unsigned long *ptr = (unsigned long *)buf;
235 if (regno < 0 || regno >= 70)
236 kgdb_error(KGDBERR_BADPARAMS);
237 else if (regno >= 32 && regno < 64) {
239 kgdb_error(KGDBERR_NOSPACE);
243 kgdb_error(KGDBERR_NOSPACE);
246 if ((unsigned long)ptr & 3)
247 kgdb_error(KGDBERR_ALIGNFAULT);
249 if (regno >= 0 && regno < 32)
250 regs->gpr[regno] = *ptr;
251 else switch (regno) {
255 case (n) + 32: LFD(n, *ptr); break;
257 caseF( 0) caseF( 1) caseF( 2) caseF( 3) caseF( 4) caseF( 5) caseF( 6) caseF( 7)
258 caseF( 8) caseF( 9) caseF(10) caseF(11) caseF(12) caseF(13) caseF(14) caseF(15)
259 caseF(16) caseF(17) caseF(18) caseF(19) caseF(20) caseF(21) caseF(22) caseF(23)
260 caseF(24) caseF(25) caseF(26) caseF(27) caseF(28) caseF(29) caseF(30) caseF(31)
265 case 64: regs->nip = *ptr; break;
266 case 65: regs->msr = *ptr; break;
267 case 66: regs->ccr = *ptr; break;
268 case 67: regs->link = *ptr; break;
269 case 68: regs->ctr = *ptr; break;
270 case 69: regs->ctr = *ptr; break;
273 kgdb_error(KGDBERR_BADPARAMS);
278 kgdb_putregs(struct pt_regs *regs, char *buf, int length)
281 unsigned long *ptr = (unsigned long *)buf;
283 if (length < SPACE_REQUIRED)
284 kgdb_error(KGDBERR_NOSPACE);
286 if ((unsigned long)ptr & 3)
287 kgdb_error(KGDBERR_ALIGNFAULT);
290 * If the stack pointer has moved, you should pray.
291 * (cause only god can help you).
294 /* General Purpose Regs */
295 for (i = 0; i < 32; i++)
296 regs->gpr[i] = *ptr++;
298 /* Floating Point Regs */
304 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
313 /* This function will generate a breakpoint exception. It is used at the
314 beginning of a program to sync up with a debugger and can be used
315 otherwise as a quick means to stop program execution and "break" into
319 kgdb_breakpoint(int argc, char *argv[])
321 asm(" .globl breakinst\n\
322 breakinst: .long 0x7d821008\n\
326 #endif /* CFG_CMD_KGDB */