]>
Commit | Line | Data |
---|---|---|
f19fd87e | 1 | /* |
a187559e | 2 | * U-Boot - architecture specific kgdb code |
f19fd87e RG |
3 | * |
4 | * Copyright 2009 Analog Devices Inc. | |
5 | * | |
6 | * Licensed under the GPL-2 or later. | |
7 | */ | |
8 | ||
9 | #include <common.h> | |
10 | #include <command.h> | |
11 | ||
12 | #include <kgdb.h> | |
13 | #include <asm/processor.h> | |
14 | #include <asm/mach-common/bits/core.h> | |
15 | #include "kgdb.h" | |
16 | #include <asm/deferred.h> | |
17 | #include <asm/traps.h> | |
18 | #include <asm/signal.h> | |
19 | ||
20 | void kgdb_enter(struct pt_regs *regs, kgdb_data *kdp) | |
21 | { | |
22 | /* disable interrupts */ | |
23 | disable_interrupts(); | |
24 | ||
25 | /* reply to host that an exception has occurred */ | |
26 | kdp->sigval = kgdb_trap(regs); | |
27 | ||
28 | /* send the PC and the Stack Pointer */ | |
29 | kdp->nregs = 2; | |
30 | kdp->regs[0].num = BFIN_PC; | |
31 | kdp->regs[0].val = regs->pc; | |
32 | ||
33 | kdp->regs[1].num = BFIN_SP; | |
34 | kdp->regs[1].val = (unsigned long)regs; | |
35 | ||
36 | } | |
37 | ||
38 | void kgdb_exit(struct pt_regs *regs, kgdb_data *kdp) | |
39 | { | |
40 | if (kdp->extype & KGDBEXIT_WITHADDR) | |
41 | printf("KGDBEXIT_WITHADDR\n"); | |
42 | ||
43 | switch (kdp->extype & KGDBEXIT_TYPEMASK) { | |
44 | case KGDBEXIT_KILL: | |
45 | printf("KGDBEXIT_KILL:\n"); | |
46 | break; | |
47 | case KGDBEXIT_CONTINUE: | |
48 | /* Make sure the supervisor single step bit is clear */ | |
49 | regs->syscfg &= ~1; | |
50 | break; | |
51 | case KGDBEXIT_SINGLE: | |
52 | /* set the supervisor single step bit */ | |
53 | regs->syscfg |= 1; | |
54 | break; | |
55 | default: | |
56 | printf("KGDBEXIT : %d\n", kdp->extype); | |
57 | } | |
58 | ||
59 | /* enable interrupts */ | |
60 | enable_interrupts(); | |
61 | } | |
62 | ||
63 | int kgdb_trap(struct pt_regs *regs) | |
64 | { | |
65 | /* ipend doesn't get filled in properly */ | |
66 | switch (regs->seqstat & EXCAUSE) { | |
67 | case VEC_EXCPT01: | |
68 | return SIGTRAP; | |
69 | case VEC_EXCPT03: | |
70 | return SIGSEGV; | |
71 | case VEC_EXCPT02: | |
72 | return SIGTRAP; | |
73 | case VEC_EXCPT04 ... VEC_EXCPT15: | |
74 | return SIGILL; | |
75 | case VEC_STEP: | |
76 | return SIGTRAP; | |
77 | case VEC_OVFLOW: | |
78 | return SIGTRAP; | |
79 | case VEC_UNDEF_I: | |
80 | return SIGILL; | |
81 | case VEC_ILGAL_I: | |
82 | return SIGILL; | |
83 | case VEC_CPLB_VL: | |
84 | return SIGSEGV; | |
85 | case VEC_MISALI_D: | |
86 | return SIGBUS; | |
87 | case VEC_UNCOV: | |
88 | return SIGILL; | |
89 | case VEC_CPLB_MHIT: | |
90 | return SIGSEGV; | |
91 | case VEC_MISALI_I: | |
92 | return SIGBUS; | |
93 | case VEC_CPLB_I_VL: | |
94 | return SIGBUS; | |
95 | case VEC_CPLB_I_MHIT: | |
96 | return SIGSEGV; | |
97 | default: | |
98 | return SIGBUS; | |
99 | } | |
100 | } | |
101 | ||
102 | /* | |
103 | * getregs - gets the pt_regs, and gives them to kgdb's buffer | |
104 | */ | |
105 | int kgdb_getregs(struct pt_regs *regs, char *buf, int max) | |
106 | { | |
107 | unsigned long *gdb_regs = (unsigned long *)buf; | |
108 | ||
109 | if (max < NUMREGBYTES) | |
110 | kgdb_error(KGDBERR_NOSPACE); | |
111 | ||
112 | if ((unsigned long)gdb_regs & 3) | |
113 | kgdb_error(KGDBERR_ALIGNFAULT); | |
114 | ||
115 | gdb_regs[BFIN_R0] = regs->r0; | |
116 | gdb_regs[BFIN_R1] = regs->r1; | |
117 | gdb_regs[BFIN_R2] = regs->r2; | |
118 | gdb_regs[BFIN_R3] = regs->r3; | |
119 | gdb_regs[BFIN_R4] = regs->r4; | |
120 | gdb_regs[BFIN_R5] = regs->r5; | |
121 | gdb_regs[BFIN_R6] = regs->r6; | |
122 | gdb_regs[BFIN_R7] = regs->r7; | |
123 | gdb_regs[BFIN_P0] = regs->p0; | |
124 | gdb_regs[BFIN_P1] = regs->p1; | |
125 | gdb_regs[BFIN_P2] = regs->p2; | |
126 | gdb_regs[BFIN_P3] = regs->p3; | |
127 | gdb_regs[BFIN_P4] = regs->p4; | |
128 | gdb_regs[BFIN_P5] = regs->p5; | |
129 | gdb_regs[BFIN_SP] = (unsigned long)regs; | |
130 | gdb_regs[BFIN_FP] = regs->fp; | |
131 | gdb_regs[BFIN_I0] = regs->i0; | |
132 | gdb_regs[BFIN_I1] = regs->i1; | |
133 | gdb_regs[BFIN_I2] = regs->i2; | |
134 | gdb_regs[BFIN_I3] = regs->i3; | |
135 | gdb_regs[BFIN_M0] = regs->m0; | |
136 | gdb_regs[BFIN_M1] = regs->m1; | |
137 | gdb_regs[BFIN_M2] = regs->m2; | |
138 | gdb_regs[BFIN_M3] = regs->m3; | |
139 | gdb_regs[BFIN_B0] = regs->b0; | |
140 | gdb_regs[BFIN_B1] = regs->b1; | |
141 | gdb_regs[BFIN_B2] = regs->b2; | |
142 | gdb_regs[BFIN_B3] = regs->b3; | |
143 | gdb_regs[BFIN_L0] = regs->l0; | |
144 | gdb_regs[BFIN_L1] = regs->l1; | |
145 | gdb_regs[BFIN_L2] = regs->l2; | |
146 | gdb_regs[BFIN_L3] = regs->l3; | |
147 | gdb_regs[BFIN_A0_DOT_X] = regs->a0x; | |
148 | gdb_regs[BFIN_A0_DOT_W] = regs->a0w; | |
149 | gdb_regs[BFIN_A1_DOT_X] = regs->a1x; | |
150 | gdb_regs[BFIN_A1_DOT_W] = regs->a1w; | |
151 | gdb_regs[BFIN_ASTAT] = regs->astat; | |
152 | gdb_regs[BFIN_RETS] = regs->rets; | |
153 | gdb_regs[BFIN_LC0] = regs->lc0; | |
154 | gdb_regs[BFIN_LT0] = regs->lt0; | |
155 | gdb_regs[BFIN_LB0] = regs->lb0; | |
156 | gdb_regs[BFIN_LC1] = regs->lc1; | |
157 | gdb_regs[BFIN_LT1] = regs->lt1; | |
158 | gdb_regs[BFIN_LB1] = regs->lb1; | |
159 | gdb_regs[BFIN_CYCLES] = 0; | |
160 | gdb_regs[BFIN_CYCLES2] = 0; | |
161 | gdb_regs[BFIN_USP] = regs->usp; | |
162 | gdb_regs[BFIN_SEQSTAT] = regs->seqstat; | |
163 | gdb_regs[BFIN_SYSCFG] = regs->syscfg; | |
164 | gdb_regs[BFIN_RETI] = regs->pc; | |
165 | gdb_regs[BFIN_RETX] = regs->retx; | |
166 | gdb_regs[BFIN_RETN] = regs->retn; | |
167 | gdb_regs[BFIN_RETE] = regs->rete; | |
168 | gdb_regs[BFIN_PC] = regs->pc; | |
169 | gdb_regs[BFIN_CC] = 0; | |
170 | gdb_regs[BFIN_EXTRA1] = 0; | |
171 | gdb_regs[BFIN_EXTRA2] = 0; | |
172 | gdb_regs[BFIN_EXTRA3] = 0; | |
173 | gdb_regs[BFIN_IPEND] = regs->ipend; | |
174 | ||
175 | return NUMREGBYTES; | |
176 | } | |
177 | ||
178 | /* | |
179 | * putreg - put kgdb's reg (regno) into the pt_regs | |
180 | */ | |
181 | void kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length) | |
182 | { | |
183 | unsigned long *ptr = (unsigned long *)buf; | |
184 | ||
185 | if (regno < 0 || regno > BFIN_NUM_REGS) | |
186 | kgdb_error(KGDBERR_BADPARAMS); | |
187 | ||
188 | if (length < 4) | |
189 | kgdb_error(KGDBERR_NOSPACE); | |
190 | ||
191 | if ((unsigned long)ptr & 3) | |
192 | kgdb_error(KGDBERR_ALIGNFAULT); | |
193 | ||
194 | switch (regno) { | |
195 | case BFIN_R0: | |
196 | regs->r0 = *ptr; | |
197 | break; | |
198 | case BFIN_R1: | |
199 | regs->r1 = *ptr; | |
200 | break; | |
201 | case BFIN_R2: | |
202 | regs->r2 = *ptr; | |
203 | break; | |
204 | case BFIN_R3: | |
205 | regs->r3 = *ptr; | |
206 | break; | |
207 | case BFIN_R4: | |
208 | regs->r4 = *ptr; | |
209 | break; | |
210 | case BFIN_R5: | |
211 | regs->r5 = *ptr; | |
212 | break; | |
213 | case BFIN_R6: | |
214 | regs->r6 = *ptr; | |
215 | break; | |
216 | case BFIN_R7: | |
217 | regs->r7 = *ptr; | |
218 | break; | |
219 | case BFIN_P0: | |
220 | regs->p0 = *ptr; | |
221 | break; | |
222 | case BFIN_P1: | |
223 | regs->p1 = *ptr; | |
224 | break; | |
225 | case BFIN_P2: | |
226 | regs->p2 = *ptr; | |
227 | break; | |
228 | case BFIN_P3: | |
229 | regs->p3 = *ptr; | |
230 | break; | |
231 | case BFIN_P4: | |
232 | regs->p4 = *ptr; | |
233 | break; | |
234 | case BFIN_P5: | |
235 | regs->p5 = *ptr; | |
236 | break; | |
237 | case BFIN_SP: | |
238 | regs->reserved = *ptr; | |
239 | break; | |
240 | case BFIN_FP: | |
241 | regs->fp = *ptr; | |
242 | break; | |
243 | case BFIN_I0: | |
244 | regs->i0 = *ptr; | |
245 | break; | |
246 | case BFIN_I1: | |
247 | regs->i1 = *ptr; | |
248 | break; | |
249 | case BFIN_I2: | |
250 | regs->i2 = *ptr; | |
251 | break; | |
252 | case BFIN_I3: | |
253 | regs->i3 = *ptr; | |
254 | break; | |
255 | case BFIN_M0: | |
256 | regs->m0 = *ptr; | |
257 | break; | |
258 | case BFIN_M1: | |
259 | regs->m1 = *ptr; | |
260 | break; | |
261 | case BFIN_M2: | |
262 | regs->m2 = *ptr; | |
263 | break; | |
264 | case BFIN_M3: | |
265 | regs->m3 = *ptr; | |
266 | break; | |
267 | case BFIN_B0: | |
268 | regs->b0 = *ptr; | |
269 | break; | |
270 | case BFIN_B1: | |
271 | regs->b1 = *ptr; | |
272 | break; | |
273 | case BFIN_B2: | |
274 | regs->b2 = *ptr; | |
275 | break; | |
276 | case BFIN_B3: | |
277 | regs->b3 = *ptr; | |
278 | break; | |
279 | case BFIN_L0: | |
280 | regs->l0 = *ptr; | |
281 | break; | |
282 | case BFIN_L1: | |
283 | regs->l1 = *ptr; | |
284 | break; | |
285 | case BFIN_L2: | |
286 | regs->l2 = *ptr; | |
287 | break; | |
288 | case BFIN_L3: | |
289 | regs->l3 = *ptr; | |
290 | break; | |
291 | case BFIN_A0_DOT_X: | |
292 | regs->a0x = *ptr; | |
293 | break; | |
294 | case BFIN_A0_DOT_W: | |
295 | regs->a0w = *ptr; | |
296 | break; | |
297 | case BFIN_A1_DOT_X: | |
298 | regs->a1x = *ptr; | |
299 | break; | |
300 | case BFIN_A1_DOT_W: | |
301 | regs->a1w = *ptr; | |
302 | break; | |
303 | case BFIN_ASTAT: | |
304 | regs->astat = *ptr; | |
305 | break; | |
306 | case BFIN_RETS: | |
307 | regs->rets = *ptr; | |
308 | break; | |
309 | case BFIN_LC0: | |
310 | regs->lc0 = *ptr; | |
311 | break; | |
312 | case BFIN_LT0: | |
313 | regs->lt0 = *ptr; | |
314 | break; | |
315 | case BFIN_LB0: | |
316 | regs->lb0 = *ptr; | |
317 | break; | |
318 | case BFIN_LC1: | |
319 | regs->lc1 = *ptr; | |
320 | break; | |
321 | case BFIN_LT1: | |
322 | regs->lt1 = *ptr; | |
323 | break; | |
324 | case BFIN_LB1: | |
325 | regs->lb1 = *ptr; | |
326 | break; | |
327 | /* | |
328 | BFIN_CYCLES, | |
329 | BFIN_CYCLES2, | |
330 | BFIN_USP, | |
331 | BFIN_SEQSTAT, | |
332 | BFIN_SYSCFG, | |
333 | */ | |
334 | case BFIN_RETX: | |
335 | regs->retx = *ptr; | |
336 | break; | |
337 | case BFIN_RETN: | |
338 | regs->retn = *ptr; | |
339 | break; | |
340 | case BFIN_RETE: | |
341 | regs->rete = *ptr; | |
342 | break; | |
343 | case BFIN_PC: | |
344 | regs->pc = *ptr; | |
345 | break; | |
346 | ||
347 | default: | |
348 | kgdb_error(KGDBERR_BADPARAMS); | |
349 | } | |
350 | } | |
351 | ||
352 | void kgdb_putregs(struct pt_regs *regs, char *buf, int length) | |
353 | { | |
354 | unsigned long *gdb_regs = (unsigned long *)buf; | |
355 | ||
356 | if (length != BFIN_NUM_REGS) | |
357 | kgdb_error(KGDBERR_NOSPACE); | |
358 | ||
359 | if ((unsigned long)gdb_regs & 3) | |
360 | kgdb_error(KGDBERR_ALIGNFAULT); | |
361 | ||
362 | regs->r0 = gdb_regs[BFIN_R0]; | |
363 | regs->r1 = gdb_regs[BFIN_R1]; | |
364 | regs->r2 = gdb_regs[BFIN_R2]; | |
365 | regs->r3 = gdb_regs[BFIN_R3]; | |
366 | regs->r4 = gdb_regs[BFIN_R4]; | |
367 | regs->r5 = gdb_regs[BFIN_R5]; | |
368 | regs->r6 = gdb_regs[BFIN_R6]; | |
369 | regs->r7 = gdb_regs[BFIN_R7]; | |
370 | regs->p0 = gdb_regs[BFIN_P0]; | |
371 | regs->p1 = gdb_regs[BFIN_P1]; | |
372 | regs->p2 = gdb_regs[BFIN_P2]; | |
373 | regs->p3 = gdb_regs[BFIN_P3]; | |
374 | regs->p4 = gdb_regs[BFIN_P4]; | |
375 | regs->p5 = gdb_regs[BFIN_P5]; | |
376 | regs->fp = gdb_regs[BFIN_FP]; | |
377 | /* regs->sp = gdb_regs[BFIN_ ]; */ | |
378 | regs->i0 = gdb_regs[BFIN_I0]; | |
379 | regs->i1 = gdb_regs[BFIN_I1]; | |
380 | regs->i2 = gdb_regs[BFIN_I2]; | |
381 | regs->i3 = gdb_regs[BFIN_I3]; | |
382 | regs->m0 = gdb_regs[BFIN_M0]; | |
383 | regs->m1 = gdb_regs[BFIN_M1]; | |
384 | regs->m2 = gdb_regs[BFIN_M2]; | |
385 | regs->m3 = gdb_regs[BFIN_M3]; | |
386 | regs->b0 = gdb_regs[BFIN_B0]; | |
387 | regs->b1 = gdb_regs[BFIN_B1]; | |
388 | regs->b2 = gdb_regs[BFIN_B2]; | |
389 | regs->b3 = gdb_regs[BFIN_B3]; | |
390 | regs->l0 = gdb_regs[BFIN_L0]; | |
391 | regs->l1 = gdb_regs[BFIN_L1]; | |
392 | regs->l2 = gdb_regs[BFIN_L2]; | |
393 | regs->l3 = gdb_regs[BFIN_L3]; | |
394 | regs->a0x = gdb_regs[BFIN_A0_DOT_X]; | |
395 | regs->a0w = gdb_regs[BFIN_A0_DOT_W]; | |
396 | regs->a1x = gdb_regs[BFIN_A1_DOT_X]; | |
397 | regs->a1w = gdb_regs[BFIN_A1_DOT_W]; | |
398 | regs->rets = gdb_regs[BFIN_RETS]; | |
399 | regs->lc0 = gdb_regs[BFIN_LC0]; | |
400 | regs->lt0 = gdb_regs[BFIN_LT0]; | |
401 | regs->lb0 = gdb_regs[BFIN_LB0]; | |
402 | regs->lc1 = gdb_regs[BFIN_LC1]; | |
403 | regs->lt1 = gdb_regs[BFIN_LT1]; | |
404 | regs->lb1 = gdb_regs[BFIN_LB1]; | |
405 | regs->usp = gdb_regs[BFIN_USP]; | |
406 | regs->syscfg = gdb_regs[BFIN_SYSCFG]; | |
407 | regs->retx = gdb_regs[BFIN_PC]; | |
408 | regs->retn = gdb_regs[BFIN_RETN]; | |
409 | regs->rete = gdb_regs[BFIN_RETE]; | |
410 | regs->pc = gdb_regs[BFIN_PC]; | |
411 | ||
412 | #if 0 /* can't change these */ | |
413 | regs->astat = gdb_regs[BFIN_ASTAT]; | |
414 | regs->seqstat = gdb_regs[BFIN_SEQSTAT]; | |
415 | regs->ipend = gdb_regs[BFIN_IPEND]; | |
416 | #endif | |
417 | ||
418 | } | |
419 | ||
54841ab5 | 420 | void kgdb_breakpoint(int argc, char * const argv[]) |
f19fd87e RG |
421 | { |
422 | asm volatile ("excpt 0x1\n"); | |
423 | } |