Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
51533b61 MS |
2 | /* |
3 | * Copyright (C) 2004 Axis Communications AB | |
4 | * | |
5 | * Code for handling break 8, hardware breakpoint, single step, and serial | |
6 | * port exceptions for kernel debugging purposes. | |
7 | */ | |
8 | ||
e336285d | 9 | #include <hwregs/intr_vect.h> |
51533b61 MS |
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 |