1 #include <common.h>
2 #include <command.h>
3 #include <kgdb.h>
4 #include <asm/signal.h>
5 #include <asm/processor.h>
7 #define PC_REGNUM 64
8 #define SP_REGNUM 1
10 void breakinst(void);
12 int
13 kgdb_setjmp(long *buf)
14 {
15 asm ("mflr 0; stw 0,0(%0);"
16 "stw 1,4(%0); stw 2,8(%0);"
17 "mfcr 0; stw 0,12(%0);"
18 "stmw 13,16(%0)"
19 : : "r" (buf));
20 /* XXX should save fp regs as well */
21 return 0;
22 }
24 void
25 kgdb_longjmp(long *buf, int val)
26 {
27 if (val == 0)
28 val = 1;
29 asm ("lmw 13,16(%0);"
30 "lwz 0,12(%0); mtcrf 0x38,0;"
31 "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
32 "mtlr 0; mr 3,%1"
33 : : "r" (buf), "r" (val));
34 }
36 static inline unsigned long
37 get_msr(void)
38 {
39 unsigned long msr;
40 asm volatile("mfmsr %0" : "=r" (msr):);
41 return msr;
42 }
44 static inline void
45 set_msr(unsigned long msr)
46 {
47 asm volatile("mtmsr %0" : : "r" (msr));
48 }
50 /* Convert the SPARC hardware trap type code to a unix signal number. */
51 /*
52 * This table contains the mapping between PowerPC hardware trap types, and
53 * signals, which are primarily what GDB understands.
54 */
55 static struct hard_trap_info
56 {
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 */
74 };
76 static int
77 computeSignal(unsigned int tt)
78 {
79 struct hard_trap_info *ht;
81 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
82 if (ht->tt == tt)
83 return ht->signo;
85 return SIGHUP; /* default for things we don't know about */
86 }
88 void
89 kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
90 {
91 unsigned long msr;
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 */
98 regs->nip += 4;
99 }
100 regs->msr &= ~MSR_SE;
102 /* reply to host that an exception has occurred */
103 kdp->sigval = computeSignal(regs->trap);
105 kdp->nregs = 2;
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];
112 }
114 void
115 kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
116 {
117 unsigned long msr = kdp->private[0];
119 if (kdp->extype & KGDBEXIT_WITHADDR)
120 regs->nip = kdp->exaddr;
122 switch (kdp->extype & KGDBEXIT_TYPEMASK) {
124 case KGDBEXIT_KILL:
125 case KGDBEXIT_CONTINUE:
126 set_msr(msr);
127 break;
129 case KGDBEXIT_SINGLE:
130 regs->msr |= MSR_SE;
131 #if 0
132 set_msr(msr | MSR_SE);
133 #endif
134 break;
135 }
136 }
138 int
139 kgdb_trap(struct pt_regs *regs)
140 {
141 return (regs->trap);
142 }
144 /* return the value of the CPU registers.
145 * some of them are non-PowerPC names :(
146 * they are stored in gdb like:
147 * struct {
148 * u32 gpr[32];
149 * f64 fpr[32];
150 * u32 pc, ps, cnd, lr; (ps=msr)
151 * u32 cnt, xer, mq;
152 * }
153 */
155 #define SPACE_REQUIRED ((32*4)+(32*8)+(6*4))
157 #ifdef CONFIG_8260
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); }
169 #endif
171 int
172 kgdb_getregs(struct pt_regs *regs, char *buf, int max)
173 {
174 int i;
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 */
188 #ifdef CONFIG_8260
189 STFDM(ptr);
190 ptr += 32*2;
191 #else
192 for (i = 0; i < 32; i++) {
193 *ptr++ = 0;
194 *ptr++ = 0;
195 }
196 #endif
198 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
199 *ptr++ = regs->nip;
200 *ptr++ = regs->msr;
201 *ptr++ = regs->ccr;
202 *ptr++ = regs->link;
203 *ptr++ = regs->ctr;
204 *ptr++ = regs->xer;
206 return (SPACE_REQUIRED);
207 }
209 /* set the value of the CPU registers */
211 #ifdef CONFIG_8260
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); }
225 #endif
227 void
228 kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
229 {
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) {
235 if (length < 8)
236 kgdb_error(KGDBERR_NOSPACE);
237 }
238 else {
239 if (length < 4)
240 kgdb_error(KGDBERR_NOSPACE);
241 }
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) {
250 #ifdef CONFIG_8260
251 #define caseF(n) \
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)
259 #undef caseF
260 #endif
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;
269 default:
270 kgdb_error(KGDBERR_BADPARAMS);
271 }
272 }
274 void
275 kgdb_putregs(struct pt_regs *regs, char *buf, int length)
276 {
277 int i;
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);
286 /*
287 * If the stack pointer has moved, you should pray.
288 * (cause only god can help you).
289 */
291 /* General Purpose Regs */
292 for (i = 0; i < 32; i++)
293 regs->gpr[i] = *ptr++;
295 /* Floating Point Regs */
296 #ifdef CONFIG_8260
297 LFDM(ptr);
298 #endif
299 ptr += 32*2;
301 /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
302 regs->nip = *ptr++;
303 regs->msr = *ptr++;
304 regs->ccr = *ptr++;
305 regs->link = *ptr++;
306 regs->ctr = *ptr++;
307 regs->xer = *ptr++;
308 }
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
313 the debugger. */
315 void
316 kgdb_breakpoint(int argc, char *argv[])
317 {
318 asm(" .globl breakinst\n\
319 breakinst: .long 0x7d821008\n\
320 ");
321 }