4 #include <asm/signal.h>
5 #include <asm/processor.h>
13 kgdb_setjmp(long *buf)
17 asm volatile("mflr %0; stw %0,0(%1);"
18 "stw %%r1,4(%1); stw %%r2,8(%1);"
19 "mfcr %0; stw %0,12(%1);"
21 : "=&r"(temp) : "r" (buf));
22 /* XXX should save fp regs as well */
27 kgdb_longjmp(long *buf, int val)
34 asm volatile("lmw %%r13,16(%1);"
35 "lwz %0,12(%1); mtcrf 0x38,%0;"
36 "lwz %0,0(%1); lwz %%r1,4(%1); lwz %%r2,8(%1);"
38 : "=&r"(temp) : "r" (buf), "r" (val));
41 static inline unsigned long
45 asm volatile("mfmsr %0" : "=r" (msr):);
50 set_msr(unsigned long msr)
52 asm volatile("mtmsr %0" : : "r" (msr));
55 /* Convert the SPARC hardware trap type code to a unix signal number. */
57 * This table contains the mapping between PowerPC hardware trap types, and
58 * signals, which are primarily what GDB understands.
60 static struct hard_trap_info
62 unsigned int tt; /* Trap type code for powerpc */
63 unsigned char signo; /* Signal that we map this trap into */
64 } hard_trap_info[] = {
65 { 0x200, SIGSEGV }, /* machine check */
66 { 0x300, SIGSEGV }, /* address error (store) */
67 { 0x400, SIGBUS }, /* instruction bus error */
68 { 0x500, SIGINT }, /* interrupt */
69 { 0x600, SIGBUS }, /* alingment */
70 { 0x700, SIGTRAP }, /* breakpoint trap */
71 { 0x800, SIGFPE }, /* fpu unavail */
72 { 0x900, SIGALRM }, /* decrementer */
73 { 0xa00, SIGILL }, /* reserved */
74 { 0xb00, SIGILL }, /* reserved */
75 { 0xc00, SIGCHLD }, /* syscall */
76 { 0xd00, SIGTRAP }, /* single-step/watch */
77 { 0xe00, SIGFPE }, /* fp assist */
78 { 0, 0} /* Must be last */
82 computeSignal(unsigned int tt)
84 struct hard_trap_info *ht;
86 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
90 return SIGHUP; /* default for things we don't know about */
94 kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
98 kdp->private[0] = msr = get_msr();
99 set_msr(msr & ~MSR_EE); /* disable interrupts */
101 if (regs->nip == (unsigned long)breakinst) {
102 /* Skip over breakpoint trap insn */
105 regs->msr &= ~MSR_SE;
107 /* reply to host that an exception has occurred */
108 kdp->sigval = computeSignal(regs->trap);
112 kdp->regs[0].num = PC_REGNUM;
113 kdp->regs[0].val = regs->nip;
115 kdp->regs[1].num = SP_REGNUM;
116 kdp->regs[1].val = regs->gpr[SP_REGNUM];
120 kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
122 unsigned long msr = kdp->private[0];
124 if (kdp->extype & KGDBEXIT_WITHADDR)
125 regs->nip = kdp->exaddr;
127 switch (kdp->extype & KGDBEXIT_TYPEMASK) {
130 case KGDBEXIT_CONTINUE:
134 case KGDBEXIT_SINGLE:
137 set_msr(msr | MSR_SE);
144 kgdb_trap(struct pt_regs *regs)
149 /* return the value of the CPU registers.
150 * some of them are non-PowerPC names :(
151 * they are stored in gdb like:
155 * u32 pc, ps, cnd, lr; (ps=msr)
160 #define SPACE_REQUIRED ((32*4)+(32*8)+(6*4))
162 #ifdef CONFIG_MPC8260
163 /* store floating double indexed */
164 #define STFDI(n,p) __asm__ __volatile__ ("stfd " #n ",%0" : "=o"(p[2*n]))
165 /* store floating double multiple */
166 #define STFDM(p) { STFDI( 0,p); STFDI( 1,p); STFDI( 2,p); STFDI( 3,p); \
167 STFDI( 4,p); STFDI( 5,p); STFDI( 6,p); STFDI( 7,p); \
168 STFDI( 8,p); STFDI( 9,p); STFDI(10,p); STFDI(11,p); \
169 STFDI(12,p); STFDI(13,p); STFDI(14,p); STFDI(15,p); \
170 STFDI(16,p); STFDI(17,p); STFDI(18,p); STFDI(19,p); \
171 STFDI(20,p); STFDI(21,p); STFDI(22,p); STFDI(23,p); \
172 STFDI(24,p); STFDI(25,p); STFDI(26,p); STFDI(27,p); \
173 STFDI(28,p); STFDI(29,p); STFDI(30,p); STFDI(31,p); }
177 kgdb_getregs(struct pt_regs *regs, char *buf, int max)
180 unsigned long *ptr = (unsigned long *)buf;
182 if (max < SPACE_REQUIRED)
183 kgdb_error(KGDBERR_NOSPACE);
185 if ((unsigned long)ptr & 3)
186 kgdb_error(KGDBERR_ALIGNFAULT);
188 /* General Purpose Regs */
189 for (i = 0; i < 32; i++)
190 *ptr++ = regs->gpr[i];
192 /* Floating Point Regs */
193 #ifdef CONFIG_MPC8260
197 for (i = 0; i < 32; i++) {
203 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
211 return (SPACE_REQUIRED);
214 /* set the value of the CPU registers */
216 #ifdef CONFIG_MPC8260
217 /* load floating double */
218 #define LFD(n,v) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"(v))
219 /* load floating double indexed */
220 #define LFDI(n,p) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"((p)[2*n]))
221 /* load floating double multiple */
222 #define LFDM(p) { LFDI( 0,p); LFDI( 1,p); LFDI( 2,p); LFDI( 3,p); \
223 LFDI( 4,p); LFDI( 5,p); LFDI( 6,p); LFDI( 7,p); \
224 LFDI( 8,p); LFDI( 9,p); LFDI(10,p); LFDI(11,p); \
225 LFDI(12,p); LFDI(13,p); LFDI(14,p); LFDI(15,p); \
226 LFDI(16,p); LFDI(17,p); LFDI(18,p); LFDI(19,p); \
227 LFDI(20,p); LFDI(21,p); LFDI(22,p); LFDI(23,p); \
228 LFDI(24,p); LFDI(25,p); LFDI(26,p); LFDI(27,p); \
229 LFDI(28,p); LFDI(29,p); LFDI(30,p); LFDI(31,p); }
233 kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
235 unsigned long *ptr = (unsigned long *)buf;
237 if (regno < 0 || regno >= 70)
238 kgdb_error(KGDBERR_BADPARAMS);
239 else if (regno >= 32 && regno < 64) {
241 kgdb_error(KGDBERR_NOSPACE);
245 kgdb_error(KGDBERR_NOSPACE);
248 if ((unsigned long)ptr & 3)
249 kgdb_error(KGDBERR_ALIGNFAULT);
251 if (regno >= 0 && regno < 32)
252 regs->gpr[regno] = *ptr;
253 else switch (regno) {
255 #ifdef CONFIG_MPC8260
257 case (n) + 32: LFD(n, *ptr); break;
259 caseF( 0) caseF( 1) caseF( 2) caseF( 3) caseF( 4) caseF( 5) caseF( 6) caseF( 7)
260 caseF( 8) caseF( 9) caseF(10) caseF(11) caseF(12) caseF(13) caseF(14) caseF(15)
261 caseF(16) caseF(17) caseF(18) caseF(19) caseF(20) caseF(21) caseF(22) caseF(23)
262 caseF(24) caseF(25) caseF(26) caseF(27) caseF(28) caseF(29) caseF(30) caseF(31)
267 case 64: regs->nip = *ptr; break;
268 case 65: regs->msr = *ptr; break;
269 case 66: regs->ccr = *ptr; break;
270 case 67: regs->link = *ptr; break;
271 case 68: regs->ctr = *ptr; break;
272 case 69: regs->ctr = *ptr; break;
275 kgdb_error(KGDBERR_BADPARAMS);
280 kgdb_putregs(struct pt_regs *regs, char *buf, int length)
283 unsigned long *ptr = (unsigned long *)buf;
285 if (length < SPACE_REQUIRED)
286 kgdb_error(KGDBERR_NOSPACE);
288 if ((unsigned long)ptr & 3)
289 kgdb_error(KGDBERR_ALIGNFAULT);
292 * If the stack pointer has moved, you should pray.
293 * (cause only god can help you).
296 /* General Purpose Regs */
297 for (i = 0; i < 32; i++)
298 regs->gpr[i] = *ptr++;
300 /* Floating Point Regs */
301 #ifdef CONFIG_MPC8260
306 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
315 /* This function will generate a breakpoint exception. It is used at the
316 beginning of a program to sync up with a debugger and can be used
317 otherwise as a quick means to stop program execution and "break" into
321 kgdb_breakpoint(int argc, char * const argv[])
323 asm(" .globl breakinst\n\
324 breakinst: .long 0x7d821008\n\