4 #include <asm/signal.h>
5 #include <asm/processor.h>
13 kgdb_setjmp(long *buf)
15 asm ("mflr 0; stw 0,0(%0);"
16 "stw 1,4(%0); stw 2,8(%0);"
17 "mfcr 0; stw 0,12(%0);"
20 /* XXX should save fp regs as well */
25 kgdb_longjmp(long *buf, int val)
30 "lwz 0,12(%0); mtcrf 0x38,0;"
31 "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
33 : : "r" (buf), "r" (val));
36 static inline unsigned long
40 asm volatile("mfmsr %0" : "=r" (msr):);
45 set_msr(unsigned long msr)
47 asm volatile("mtmsr %0" : : "r" (msr));
50 /* Convert the SPARC hardware trap type code to a unix signal number. */
52 * This table contains the mapping between PowerPC hardware trap types, and
53 * signals, which are primarily what GDB understands.
55 static struct hard_trap_info
57 unsigned int tt; /* Trap type code for powerpc */
58 unsigned char signo; /* Signal that we map this trap into */
59 } hard_trap_info[] = {
60 { 0x200, SIGSEGV }, /* machine check */
61 { 0x300, SIGSEGV }, /* address error (store) */
62 { 0x400, SIGBUS }, /* instruction bus error */
63 { 0x500, SIGINT }, /* interrupt */
64 { 0x600, SIGBUS }, /* alingment */
65 { 0x700, SIGTRAP }, /* breakpoint trap */
66 { 0x800, SIGFPE }, /* fpu unavail */
67 { 0x900, SIGALRM }, /* decrementer */
68 { 0xa00, SIGILL }, /* reserved */
69 { 0xb00, SIGILL }, /* reserved */
70 { 0xc00, SIGCHLD }, /* syscall */
71 { 0xd00, SIGTRAP }, /* single-step/watch */
72 { 0xe00, SIGFPE }, /* fp assist */
73 { 0, 0} /* Must be last */
77 computeSignal(unsigned int tt)
79 struct hard_trap_info *ht;
81 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
85 return SIGHUP; /* default for things we don't know about */
89 kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
93 kdp->private[0] = msr = get_msr();
94 set_msr(msr & ~MSR_EE); /* disable interrupts */
96 if (regs->nip == (unsigned long)breakinst) {
97 /* Skip over breakpoint trap insn */
100 regs->msr &= ~MSR_SE;
102 /* reply to host that an exception has occurred */
103 kdp->sigval = computeSignal(regs->trap);
107 kdp->regs[0].num = PC_REGNUM;
108 kdp->regs[0].val = regs->nip;
110 kdp->regs[1].num = SP_REGNUM;
111 kdp->regs[1].val = regs->gpr[SP_REGNUM];
115 kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
117 unsigned long msr = kdp->private[0];
119 if (kdp->extype & KGDBEXIT_WITHADDR)
120 regs->nip = kdp->exaddr;
122 switch (kdp->extype & KGDBEXIT_TYPEMASK) {
125 case KGDBEXIT_CONTINUE:
129 case KGDBEXIT_SINGLE:
132 set_msr(msr | MSR_SE);
139 kgdb_trap(struct pt_regs *regs)
144 /* return the value of the CPU registers.
145 * some of them are non-PowerPC names :(
146 * they are stored in gdb like:
150 * u32 pc, ps, cnd, lr; (ps=msr)
155 #define SPACE_REQUIRED ((32*4)+(32*8)+(6*4))
158 /* store floating double indexed */
159 #define STFDI(n,p) __asm__ __volatile__ ("stfd " #n ",%0" : "=o"(p[2*n]))
160 /* store floating double multiple */
161 #define STFDM(p) { STFDI( 0,p); STFDI( 1,p); STFDI( 2,p); STFDI( 3,p); \
162 STFDI( 4,p); STFDI( 5,p); STFDI( 6,p); STFDI( 7,p); \
163 STFDI( 8,p); STFDI( 9,p); STFDI(10,p); STFDI(11,p); \
164 STFDI(12,p); STFDI(13,p); STFDI(14,p); STFDI(15,p); \
165 STFDI(16,p); STFDI(17,p); STFDI(18,p); STFDI(19,p); \
166 STFDI(20,p); STFDI(21,p); STFDI(22,p); STFDI(23,p); \
167 STFDI(24,p); STFDI(25,p); STFDI(26,p); STFDI(27,p); \
168 STFDI(28,p); STFDI(29,p); STFDI(30,p); STFDI(31,p); }
172 kgdb_getregs(struct pt_regs *regs, char *buf, int max)
175 unsigned long *ptr = (unsigned long *)buf;
177 if (max < SPACE_REQUIRED)
178 kgdb_error(KGDBERR_NOSPACE);
180 if ((unsigned long)ptr & 3)
181 kgdb_error(KGDBERR_ALIGNFAULT);
183 /* General Purpose Regs */
184 for (i = 0; i < 32; i++)
185 *ptr++ = regs->gpr[i];
187 /* Floating Point Regs */
192 for (i = 0; i < 32; i++) {
198 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
206 return (SPACE_REQUIRED);
209 /* set the value of the CPU registers */
212 /* load floating double */
213 #define LFD(n,v) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"(v))
214 /* load floating double indexed */
215 #define LFDI(n,p) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"((p)[2*n]))
216 /* load floating double multiple */
217 #define LFDM(p) { LFDI( 0,p); LFDI( 1,p); LFDI( 2,p); LFDI( 3,p); \
218 LFDI( 4,p); LFDI( 5,p); LFDI( 6,p); LFDI( 7,p); \
219 LFDI( 8,p); LFDI( 9,p); LFDI(10,p); LFDI(11,p); \
220 LFDI(12,p); LFDI(13,p); LFDI(14,p); LFDI(15,p); \
221 LFDI(16,p); LFDI(17,p); LFDI(18,p); LFDI(19,p); \
222 LFDI(20,p); LFDI(21,p); LFDI(22,p); LFDI(23,p); \
223 LFDI(24,p); LFDI(25,p); LFDI(26,p); LFDI(27,p); \
224 LFDI(28,p); LFDI(29,p); LFDI(30,p); LFDI(31,p); }
228 kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
230 unsigned long *ptr = (unsigned long *)buf;
232 if (regno < 0 || regno >= 70)
233 kgdb_error(KGDBERR_BADPARAMS);
234 else if (regno >= 32 && regno < 64) {
236 kgdb_error(KGDBERR_NOSPACE);
240 kgdb_error(KGDBERR_NOSPACE);
243 if ((unsigned long)ptr & 3)
244 kgdb_error(KGDBERR_ALIGNFAULT);
246 if (regno >= 0 && regno < 32)
247 regs->gpr[regno] = *ptr;
248 else switch (regno) {
252 case (n) + 32: LFD(n, *ptr); break;
254 caseF( 0) caseF( 1) caseF( 2) caseF( 3) caseF( 4) caseF( 5) caseF( 6) caseF( 7)
255 caseF( 8) caseF( 9) caseF(10) caseF(11) caseF(12) caseF(13) caseF(14) caseF(15)
256 caseF(16) caseF(17) caseF(18) caseF(19) caseF(20) caseF(21) caseF(22) caseF(23)
257 caseF(24) caseF(25) caseF(26) caseF(27) caseF(28) caseF(29) caseF(30) caseF(31)
262 case 64: regs->nip = *ptr; break;
263 case 65: regs->msr = *ptr; break;
264 case 66: regs->ccr = *ptr; break;
265 case 67: regs->link = *ptr; break;
266 case 68: regs->ctr = *ptr; break;
267 case 69: regs->ctr = *ptr; break;
270 kgdb_error(KGDBERR_BADPARAMS);
275 kgdb_putregs(struct pt_regs *regs, char *buf, int length)
278 unsigned long *ptr = (unsigned long *)buf;
280 if (length < SPACE_REQUIRED)
281 kgdb_error(KGDBERR_NOSPACE);
283 if ((unsigned long)ptr & 3)
284 kgdb_error(KGDBERR_ALIGNFAULT);
287 * If the stack pointer has moved, you should pray.
288 * (cause only god can help you).
291 /* General Purpose Regs */
292 for (i = 0; i < 32; i++)
293 regs->gpr[i] = *ptr++;
295 /* Floating Point Regs */
301 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
310 /* This function will generate a breakpoint exception. It is used at the
311 beginning of a program to sync up with a debugger and can be used
312 otherwise as a quick means to stop program execution and "break" into
316 kgdb_breakpoint(int argc, char *argv[])
318 asm(" .globl breakinst\n\
319 breakinst: .long 0x7d821008\n\