blob: f3a47605902aa067ac0dec641832d0131f84a129 [file] [log] [blame]
Kyle Swenson8d8f6542021-03-15 11:02:55 -06001/*
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 <hwregs/intr_vect.h>
9
10 ;; Exported functions.
11 .globl kgdb_handle_exception
12
13kgdb_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
1601:
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
295sigint:
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;;
307handle_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;;
315return:
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
3722:
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