blob: 2a7c0727f5c0a1cf16ac19c1132c3dbd5856bbf7 [file] [log] [blame]
Robin Getzf19fd872009-12-21 16:35:48 -05001/*
Bin Menga1875592016-02-05 19:30:11 -08002 * U-Boot - architecture specific kgdb code
Robin Getzf19fd872009-12-21 16:35:48 -05003 *
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
20void 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
38void 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
63int 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 */
105int 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 */
181void 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
352void 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
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200420void kgdb_breakpoint(int argc, char * const argv[])
Robin Getzf19fd872009-12-21 16:35:48 -0500421{
422 asm volatile ("excpt 0x1\n");
423}