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