diff options
Diffstat (limited to 'arch/cris/arch-v32/kernel/kgdb_asm.S')
-rw-r--r-- | arch/cris/arch-v32/kernel/kgdb_asm.S | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/arch/cris/arch-v32/kernel/kgdb_asm.S b/arch/cris/arch-v32/kernel/kgdb_asm.S new file mode 100644 index 000000000000..b350dd279ed2 --- /dev/null +++ b/arch/cris/arch-v32/kernel/kgdb_asm.S | |||
@@ -0,0 +1,552 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 Axis Communications AB | ||
3 | * | ||
4 | * Code for handling break 8, hardware breakpoint, single step, and serial | ||
5 | * port exceptions for kernel debugging purposes. | ||
6 | */ | ||
7 | |||
8 | #include <linux/config.h> | ||
9 | #include <asm/arch/hwregs/intr_vect.h> | ||
10 | |||
11 | ;; Exported functions. | ||
12 | .globl kgdb_handle_exception | ||
13 | |||
14 | kgdb_handle_exception: | ||
15 | |||
16 | ;; Create a register image of the caller. | ||
17 | ;; | ||
18 | ;; First of all, save the ACR on the stack since we need it for address calculations. | ||
19 | ;; We put it into the register struct later. | ||
20 | |||
21 | subq 4, $sp | ||
22 | move.d $acr, [$sp] | ||
23 | |||
24 | ;; Now we are free to use ACR all we want. | ||
25 | ;; If we were running this handler with interrupts on, we would have to be careful | ||
26 | ;; to save and restore CCS manually, but since we aren't we treat it like every other | ||
27 | ;; register. | ||
28 | |||
29 | move.d reg, $acr | ||
30 | move.d $r0, [$acr] ; Save R0 (start of register struct) | ||
31 | addq 4, $acr | ||
32 | move.d $r1, [$acr] ; Save R1 | ||
33 | addq 4, $acr | ||
34 | move.d $r2, [$acr] ; Save R2 | ||
35 | addq 4, $acr | ||
36 | move.d $r3, [$acr] ; Save R3 | ||
37 | addq 4, $acr | ||
38 | move.d $r4, [$acr] ; Save R4 | ||
39 | addq 4, $acr | ||
40 | move.d $r5, [$acr] ; Save R5 | ||
41 | addq 4, $acr | ||
42 | move.d $r6, [$acr] ; Save R6 | ||
43 | addq 4, $acr | ||
44 | move.d $r7, [$acr] ; Save R7 | ||
45 | addq 4, $acr | ||
46 | move.d $r8, [$acr] ; Save R8 | ||
47 | addq 4, $acr | ||
48 | move.d $r9, [$acr] ; Save R9 | ||
49 | addq 4, $acr | ||
50 | move.d $r10, [$acr] ; Save R10 | ||
51 | addq 4, $acr | ||
52 | move.d $r11, [$acr] ; Save R11 | ||
53 | addq 4, $acr | ||
54 | move.d $r12, [$acr] ; Save R12 | ||
55 | addq 4, $acr | ||
56 | move.d $r13, [$acr] ; Save R13 | ||
57 | addq 4, $acr | ||
58 | move.d $sp, [$acr] ; Save SP (R14) | ||
59 | addq 4, $acr | ||
60 | |||
61 | ;; The ACR register is already saved on the stack, so pop it from there. | ||
62 | move.d [$sp],$r0 | ||
63 | move.d $r0, [$acr] | ||
64 | addq 4, $acr | ||
65 | |||
66 | move $bz, [$acr] | ||
67 | addq 1, $acr | ||
68 | move $vr, [$acr] | ||
69 | addq 1, $acr | ||
70 | move $pid, [$acr] | ||
71 | addq 4, $acr | ||
72 | move $srs, [$acr] | ||
73 | addq 1, $acr | ||
74 | move $wz, [$acr] | ||
75 | addq 2, $acr | ||
76 | move $exs, [$acr] | ||
77 | addq 4, $acr | ||
78 | move $eda, [$acr] | ||
79 | addq 4, $acr | ||
80 | move $mof, [$acr] | ||
81 | addq 4, $acr | ||
82 | move $dz, [$acr] | ||
83 | addq 4, $acr | ||
84 | move $ebp, [$acr] | ||
85 | addq 4, $acr | ||
86 | move $erp, [$acr] | ||
87 | addq 4, $acr | ||
88 | move $srp, [$acr] | ||
89 | addq 4, $acr | ||
90 | move $nrp, [$acr] | ||
91 | addq 4, $acr | ||
92 | move $ccs, [$acr] | ||
93 | addq 4, $acr | ||
94 | move $usp, [$acr] | ||
95 | addq 4, $acr | ||
96 | move $spc, [$acr] | ||
97 | addq 4, $acr | ||
98 | |||
99 | ;; Skip the pseudo-PC. | ||
100 | addq 4, $acr | ||
101 | |||
102 | ;; Save the support registers in bank 0 - 3. | ||
103 | clear.d $r1 ; Bank counter | ||
104 | move.d sreg, $acr | ||
105 | |||
106 | ;; Bank 0 | ||
107 | move $r1, $srs | ||
108 | nop | ||
109 | nop | ||
110 | nop | ||
111 | move $s0, $r0 | ||
112 | move.d $r0, [$acr] | ||
113 | addq 4, $acr | ||
114 | move $s1, $r0 | ||
115 | move.d $r0, [$acr] | ||
116 | addq 4, $acr | ||
117 | move $s2, $r0 | ||
118 | move.d $r0, [$acr] | ||
119 | addq 4, $acr | ||
120 | move $s3, $r0 | ||
121 | move.d $r0, [$acr] | ||
122 | addq 4, $acr | ||
123 | move $s4, $r0 | ||
124 | move.d $r0, [$acr] | ||
125 | addq 4, $acr | ||
126 | move $s5, $r0 | ||
127 | move.d $r0, [$acr] | ||
128 | addq 4, $acr | ||
129 | move $s6, $r0 | ||
130 | move.d $r0, [$acr] | ||
131 | addq 4, $acr | ||
132 | move $s7, $r0 | ||
133 | move.d $r0, [$acr] | ||
134 | addq 4, $acr | ||
135 | move $s8, $r0 | ||
136 | move.d $r0, [$acr] | ||
137 | addq 4, $acr | ||
138 | move $s9, $r0 | ||
139 | move.d $r0, [$acr] | ||
140 | addq 4, $acr | ||
141 | move $s10, $r0 | ||
142 | move.d $r0, [$acr] | ||
143 | addq 4, $acr | ||
144 | move $s11, $r0 | ||
145 | move.d $r0, [$acr] | ||
146 | addq 4, $acr | ||
147 | move $s12, $r0 | ||
148 | move.d $r0, [$acr] | ||
149 | addq 4, $acr | ||
150 | |||
151 | ;; Nothing in S13 - S15, bank 0 | ||
152 | clear.d [$acr] | ||
153 | addq 4, $acr | ||
154 | clear.d [$acr] | ||
155 | addq 4, $acr | ||
156 | clear.d [$acr] | ||
157 | addq 4, $acr | ||
158 | |||
159 | ;; Bank 1 and bank 2 have the same layout, hence the loop. | ||
160 | addq 1, $r1 | ||
161 | 1: | ||
162 | move $r1, $srs | ||
163 | nop | ||
164 | nop | ||
165 | nop | ||
166 | move $s0, $r0 | ||
167 | move.d $r0, [$acr] | ||
168 | addq 4, $acr | ||
169 | move $s1, $r0 | ||
170 | move.d $r0, [$acr] | ||
171 | addq 4, $acr | ||
172 | move $s2, $r0 | ||
173 | move.d $r0, [$acr] | ||
174 | addq 4, $acr | ||
175 | move $s3, $r0 | ||
176 | move.d $r0, [$acr] | ||
177 | addq 4, $acr | ||
178 | move $s4, $r0 | ||
179 | move.d $r0, [$acr] | ||
180 | addq 4, $acr | ||
181 | move $s5, $r0 | ||
182 | move.d $r0, [$acr] | ||
183 | addq 4, $acr | ||
184 | move $s6, $r0 | ||
185 | move.d $r0, [$acr] | ||
186 | addq 4, $acr | ||
187 | |||
188 | ;; Nothing in S7 - S15, bank 1 and 2 | ||
189 | clear.d [$acr] | ||
190 | addq 4, $acr | ||
191 | clear.d [$acr] | ||
192 | addq 4, $acr | ||
193 | clear.d [$acr] | ||
194 | addq 4, $acr | ||
195 | clear.d [$acr] | ||
196 | addq 4, $acr | ||
197 | clear.d [$acr] | ||
198 | addq 4, $acr | ||
199 | clear.d [$acr] | ||
200 | addq 4, $acr | ||
201 | clear.d [$acr] | ||
202 | addq 4, $acr | ||
203 | clear.d [$acr] | ||
204 | addq 4, $acr | ||
205 | clear.d [$acr] | ||
206 | addq 4, $acr | ||
207 | |||
208 | addq 1, $r1 | ||
209 | cmpq 3, $r1 | ||
210 | bne 1b | ||
211 | nop | ||
212 | |||
213 | ;; Bank 3 | ||
214 | move $r1, $srs | ||
215 | nop | ||
216 | nop | ||
217 | nop | ||
218 | move $s0, $r0 | ||
219 | move.d $r0, [$acr] | ||
220 | addq 4, $acr | ||
221 | move $s1, $r0 | ||
222 | move.d $r0, [$acr] | ||
223 | addq 4, $acr | ||
224 | move $s2, $r0 | ||
225 | move.d $r0, [$acr] | ||
226 | addq 4, $acr | ||
227 | move $s3, $r0 | ||
228 | move.d $r0, [$acr] | ||
229 | addq 4, $acr | ||
230 | move $s4, $r0 | ||
231 | move.d $r0, [$acr] | ||
232 | addq 4, $acr | ||
233 | move $s5, $r0 | ||
234 | move.d $r0, [$acr] | ||
235 | addq 4, $acr | ||
236 | move $s6, $r0 | ||
237 | move.d $r0, [$acr] | ||
238 | addq 4, $acr | ||
239 | move $s7, $r0 | ||
240 | move.d $r0, [$acr] | ||
241 | addq 4, $acr | ||
242 | move $s8, $r0 | ||
243 | move.d $r0, [$acr] | ||
244 | addq 4, $acr | ||
245 | move $s9, $r0 | ||
246 | move.d $r0, [$acr] | ||
247 | addq 4, $acr | ||
248 | move $s10, $r0 | ||
249 | move.d $r0, [$acr] | ||
250 | addq 4, $acr | ||
251 | move $s11, $r0 | ||
252 | move.d $r0, [$acr] | ||
253 | addq 4, $acr | ||
254 | move $s12, $r0 | ||
255 | move.d $r0, [$acr] | ||
256 | addq 4, $acr | ||
257 | move $s13, $r0 | ||
258 | move.d $r0, [$acr] | ||
259 | addq 4, $acr | ||
260 | move $s14, $r0 | ||
261 | move.d $r0, [$acr] | ||
262 | addq 4, $acr | ||
263 | ;; Nothing in S15, bank 3 | ||
264 | clear.d [$acr] | ||
265 | addq 4, $acr | ||
266 | |||
267 | ;; Check what got us here: get IDX field of EXS. | ||
268 | move $exs, $r10 | ||
269 | and.d 0xff00, $r10 | ||
270 | lsrq 8, $r10 | ||
271 | #if defined(CONFIG_ETRAX_KGDB_PORT0) | ||
272 | cmp.d SER0_INTR_VECT, $r10 ; IRQ for serial port 0 | ||
273 | beq sigint | ||
274 | nop | ||
275 | #elif defined(CONFIG_ETRAX_KGDB_PORT1) | ||
276 | cmp.d SER1_INTR_VECT, $r10 ; IRQ for serial port 1 | ||
277 | beq sigint | ||
278 | nop | ||
279 | #elif defined(CONFIG_ETRAX_KGDB_PORT2) | ||
280 | cmp.d SER2_INTR_VECT, $r10 ; IRQ for serial port 2 | ||
281 | beq sigint | ||
282 | nop | ||
283 | #elif defined(CONFIG_ETRAX_KGDB_PORT3) | ||
284 | cmp.d SER3_INTR_VECT, $r10 ; IRQ for serial port 3 | ||
285 | beq sigint | ||
286 | nop | ||
287 | #endif | ||
288 | ;; Multiple interrupt must be due to serial break. | ||
289 | cmp.d 0x30, $r10 ; Multiple interrupt | ||
290 | beq sigint | ||
291 | nop | ||
292 | ;; Neither of those? Then it's a sigtrap. | ||
293 | ba handle_comm | ||
294 | moveq 5, $r10 ; Set SIGTRAP (delay slot) | ||
295 | |||
296 | sigint: | ||
297 | ;; Serial interrupt; get character | ||
298 | jsr getDebugChar | ||
299 | nop ; Delay slot | ||
300 | cmp.b 3, $r10 ; \003 (Ctrl-C)? | ||
301 | bne return ; No, get out of here | ||
302 | nop | ||
303 | moveq 2, $r10 ; Set SIGINT | ||
304 | |||
305 | ;; | ||
306 | ;; Handle the communication | ||
307 | ;; | ||
308 | handle_comm: | ||
309 | move.d internal_stack+1020, $sp ; Use the internal stack which grows upwards | ||
310 | jsr handle_exception ; Interactive routine | ||
311 | nop | ||
312 | |||
313 | ;; | ||
314 | ;; Return to the caller | ||
315 | ;; | ||
316 | return: | ||
317 | |||
318 | ;; First of all, write the support registers. | ||
319 | clear.d $r1 ; Bank counter | ||
320 | move.d sreg, $acr | ||
321 | |||
322 | ;; Bank 0 | ||
323 | move $r1, $srs | ||
324 | nop | ||
325 | nop | ||
326 | nop | ||
327 | move.d [$acr], $r0 | ||
328 | move $r0, $s0 | ||
329 | addq 4, $acr | ||
330 | move.d [$acr], $r0 | ||
331 | move $r0, $s1 | ||
332 | addq 4, $acr | ||
333 | move.d [$acr], $r0 | ||
334 | move $r0, $s2 | ||
335 | addq 4, $acr | ||
336 | move.d [$acr], $r0 | ||
337 | move $r0, $s3 | ||
338 | addq 4, $acr | ||
339 | move.d [$acr], $r0 | ||
340 | move $r0, $s4 | ||
341 | addq 4, $acr | ||
342 | move.d [$acr], $r0 | ||
343 | move $r0, $s5 | ||
344 | addq 4, $acr | ||
345 | |||
346 | ;; Nothing in S6 - S7, bank 0. | ||
347 | addq 4, $acr | ||
348 | addq 4, $acr | ||
349 | |||
350 | move.d [$acr], $r0 | ||
351 | move $r0, $s8 | ||
352 | addq 4, $acr | ||
353 | move.d [$acr], $r0 | ||
354 | move $r0, $s9 | ||
355 | addq 4, $acr | ||
356 | move.d [$acr], $r0 | ||
357 | move $r0, $s10 | ||
358 | addq 4, $acr | ||
359 | move.d [$acr], $r0 | ||
360 | move $r0, $s11 | ||
361 | addq 4, $acr | ||
362 | move.d [$acr], $r0 | ||
363 | move $r0, $s12 | ||
364 | addq 4, $acr | ||
365 | |||
366 | ;; Nothing in S13 - S15, bank 0 | ||
367 | addq 4, $acr | ||
368 | addq 4, $acr | ||
369 | addq 4, $acr | ||
370 | |||
371 | ;; Bank 1 and bank 2 have the same layout, hence the loop. | ||
372 | addq 1, $r1 | ||
373 | 2: | ||
374 | move $r1, $srs | ||
375 | nop | ||
376 | nop | ||
377 | nop | ||
378 | move.d [$acr], $r0 | ||
379 | move $r0, $s0 | ||
380 | addq 4, $acr | ||
381 | move.d [$acr], $r0 | ||
382 | move $r0, $s1 | ||
383 | addq 4, $acr | ||
384 | move.d [$acr], $r0 | ||
385 | move $r0, $s2 | ||
386 | addq 4, $acr | ||
387 | |||
388 | ;; S3 (MM_CAUSE) is read-only. | ||
389 | addq 4, $acr | ||
390 | |||
391 | move.d [$acr], $r0 | ||
392 | move $r0, $s4 | ||
393 | addq 4, $acr | ||
394 | |||
395 | ;; FIXME: Actually write S5/S6? (Affects MM_CAUSE.) | ||
396 | addq 4, $acr | ||
397 | addq 4, $acr | ||
398 | |||
399 | ;; Nothing in S7 - S15, bank 1 and 2 | ||
400 | addq 4, $acr | ||
401 | addq 4, $acr | ||
402 | addq 4, $acr | ||
403 | addq 4, $acr | ||
404 | addq 4, $acr | ||
405 | addq 4, $acr | ||
406 | addq 4, $acr | ||
407 | addq 4, $acr | ||
408 | addq 4, $acr | ||
409 | |||
410 | addq 1, $r1 | ||
411 | cmpq 3, $r1 | ||
412 | bne 2b | ||
413 | nop | ||
414 | |||
415 | ;; Bank 3 | ||
416 | move $r1, $srs | ||
417 | nop | ||
418 | nop | ||
419 | nop | ||
420 | move.d [$acr], $r0 | ||
421 | move $r0, $s0 | ||
422 | addq 4, $acr | ||
423 | move.d [$acr], $r0 | ||
424 | move $r0, $s1 | ||
425 | addq 4, $acr | ||
426 | move.d [$acr], $r0 | ||
427 | move $r0, $s2 | ||
428 | addq 4, $acr | ||
429 | move.d [$acr], $r0 | ||
430 | move $r0, $s3 | ||
431 | addq 4, $acr | ||
432 | move.d [$acr], $r0 | ||
433 | move $r0, $s4 | ||
434 | addq 4, $acr | ||
435 | move.d [$acr], $r0 | ||
436 | move $r0, $s5 | ||
437 | addq 4, $acr | ||
438 | move.d [$acr], $r0 | ||
439 | move $r0, $s6 | ||
440 | addq 4, $acr | ||
441 | move.d [$acr], $r0 | ||
442 | move $r0, $s7 | ||
443 | addq 4, $acr | ||
444 | move.d [$acr], $r0 | ||
445 | move $r0, $s8 | ||
446 | addq 4, $acr | ||
447 | move.d [$acr], $r0 | ||
448 | move $r0, $s9 | ||
449 | addq 4, $acr | ||
450 | move.d [$acr], $r0 | ||
451 | move $r0, $s10 | ||
452 | addq 4, $acr | ||
453 | move.d [$acr], $r0 | ||
454 | move $r0, $s11 | ||
455 | addq 4, $acr | ||
456 | move.d [$acr], $r0 | ||
457 | move $r0, $s12 | ||
458 | addq 4, $acr | ||
459 | move.d [$acr], $r0 | ||
460 | move $r0, $s13 | ||
461 | addq 4, $acr | ||
462 | move.d [$acr], $r0 | ||
463 | move $r0, $s14 | ||
464 | addq 4, $acr | ||
465 | |||
466 | ;; Nothing in S15, bank 3 | ||
467 | addq 4, $acr | ||
468 | |||
469 | ;; Now, move on to the regular register restoration process. | ||
470 | |||
471 | move.d reg, $acr ; Reset ACR to point at the beginning of the register image | ||
472 | move.d [$acr], $r0 ; Restore R0 | ||
473 | addq 4, $acr | ||
474 | move.d [$acr], $r1 ; Restore R1 | ||
475 | addq 4, $acr | ||
476 | move.d [$acr], $r2 ; Restore R2 | ||
477 | addq 4, $acr | ||
478 | move.d [$acr], $r3 ; Restore R3 | ||
479 | addq 4, $acr | ||
480 | move.d [$acr], $r4 ; Restore R4 | ||
481 | addq 4, $acr | ||
482 | move.d [$acr], $r5 ; Restore R5 | ||
483 | addq 4, $acr | ||
484 | move.d [$acr], $r6 ; Restore R6 | ||
485 | addq 4, $acr | ||
486 | move.d [$acr], $r7 ; Restore R7 | ||
487 | addq 4, $acr | ||
488 | move.d [$acr], $r8 ; Restore R8 | ||
489 | addq 4, $acr | ||
490 | move.d [$acr], $r9 ; Restore R9 | ||
491 | addq 4, $acr | ||
492 | move.d [$acr], $r10 ; Restore R10 | ||
493 | addq 4, $acr | ||
494 | move.d [$acr], $r11 ; Restore R11 | ||
495 | addq 4, $acr | ||
496 | move.d [$acr], $r12 ; Restore R12 | ||
497 | addq 4, $acr | ||
498 | move.d [$acr], $r13 ; Restore R13 | ||
499 | |||
500 | ;; | ||
501 | ;; We restore all registers, even though some of them probably haven't changed. | ||
502 | ;; | ||
503 | |||
504 | addq 4, $acr | ||
505 | move.d [$acr], $sp ; Restore SP (R14) | ||
506 | |||
507 | ;; ACR cannot be restored just yet. | ||
508 | addq 8, $acr | ||
509 | |||
510 | ;; Skip BZ, VR. | ||
511 | addq 2, $acr | ||
512 | |||
513 | move [$acr], $pid ; Restore PID | ||
514 | addq 4, $acr | ||
515 | move [$acr], $srs ; Restore SRS | ||
516 | nop | ||
517 | nop | ||
518 | nop | ||
519 | addq 1, $acr | ||
520 | |||
521 | ;; Skip WZ. | ||
522 | addq 2, $acr | ||
523 | |||
524 | move [$acr], $exs ; Restore EXS. | ||
525 | addq 4, $acr | ||
526 | move [$acr], $eda ; Restore EDA. | ||
527 | addq 4, $acr | ||
528 | move [$acr], $mof ; Restore MOF. | ||
529 | |||
530 | ;; Skip DZ. | ||
531 | addq 8, $acr | ||
532 | |||
533 | move [$acr], $ebp ; Restore EBP. | ||
534 | addq 4, $acr | ||
535 | move [$acr], $erp ; Restore ERP. | ||
536 | addq 4, $acr | ||
537 | move [$acr], $srp ; Restore SRP. | ||
538 | addq 4, $acr | ||
539 | move [$acr], $nrp ; Restore NRP. | ||
540 | addq 4, $acr | ||
541 | move [$acr], $ccs ; Restore CCS like an ordinary register. | ||
542 | addq 4, $acr | ||
543 | move [$acr], $usp ; Restore USP | ||
544 | addq 4, $acr | ||
545 | move [$acr], $spc ; Restore SPC | ||
546 | ; No restoration of pseudo-PC of course. | ||
547 | |||
548 | move.d reg, $acr ; Reset ACR to point at the beginning of the register image | ||
549 | add.d 15*4, $acr | ||
550 | move.d [$acr], $acr ; Finally, restore ACR. | ||
551 | rete ; Same as jump ERP | ||
552 | rfe ; Shifts CCS | ||