1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright (C) 2004 Axis Communications AB
5 * Code for handling break 8, hardware breakpoint, single step, and serial
6 * port exceptions for kernel debugging purposes.
9 #include <hwregs/intr_vect.h>
11 ;; Exported functions.
12 .globl kgdb_handle_exception
14 kgdb_handle_exception:
16 ;; Create a register image of the caller.
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.
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
30 move.d $r0, [$acr] ; Save R0 (start of register struct)
32 move.d $r1, [$acr] ; Save R1
34 move.d $r2, [$acr] ; Save R2
36 move.d $r3, [$acr] ; Save R3
38 move.d $r4, [$acr] ; Save R4
40 move.d $r5, [$acr] ; Save R5
42 move.d $r6, [$acr] ; Save R6
44 move.d $r7, [$acr] ; Save R7
46 move.d $r8, [$acr] ; Save R8
48 move.d $r9, [$acr] ; Save R9
50 move.d $r10, [$acr] ; Save R10
52 move.d $r11, [$acr] ; Save R11
54 move.d $r12, [$acr] ; Save R12
56 move.d $r13, [$acr] ; Save R13
58 move.d $sp, [$acr] ; Save SP (R14)
61 ;; The ACR register is already saved on the stack, so pop it from there.
99 ;; Skip the pseudo-PC.
102 ;; Save the support registers in bank 0 - 3.
103 clear.d $r1 ; Bank counter
151 ;; Nothing in S13 - S15, bank 0
159 ;; Bank 1 and bank 2 have the same layout, hence the loop.
188 ;; Nothing in S7 - S15, bank 1 and 2
263 ;; Nothing in S15, bank 3
267 ;; Check what got us here: get IDX field of EXS.
271 #if defined(CONFIG_ETRAX_KGDB_PORT0)
272 cmp.d SER0_INTR_VECT, $r10 ; IRQ for serial port 0
275 #elif defined(CONFIG_ETRAX_KGDB_PORT1)
276 cmp.d SER1_INTR_VECT, $r10 ; IRQ for serial port 1
279 #elif defined(CONFIG_ETRAX_KGDB_PORT2)
280 cmp.d SER2_INTR_VECT, $r10 ; IRQ for serial port 2
283 #elif defined(CONFIG_ETRAX_KGDB_PORT3)
284 cmp.d SER3_INTR_VECT, $r10 ; IRQ for serial port 3
288 ;; Multiple interrupt must be due to serial break.
289 cmp.d 0x30, $r10 ; Multiple interrupt
292 ;; Neither of those? Then it's a sigtrap.
294 moveq 5, $r10 ; Set SIGTRAP (delay slot)
297 ;; Serial interrupt; get character
300 cmp.b 3, $r10 ; \003 (Ctrl-C)?
301 bne return ; No, get out of here
303 moveq 2, $r10 ; Set SIGINT
306 ;; Handle the communication
309 move.d internal_stack+1020, $sp ; Use the internal stack which grows upwards
310 jsr handle_exception ; Interactive routine
314 ;; Return to the caller
318 ;; First of all, write the support registers.
319 clear.d $r1 ; Bank counter
346 ;; Nothing in S6 - S7, bank 0.
366 ;; Nothing in S13 - S15, bank 0
371 ;; Bank 1 and bank 2 have the same layout, hence the loop.
388 ;; S3 (MM_CAUSE) is read-only.
395 ;; FIXME: Actually write S5/S6? (Affects MM_CAUSE.)
399 ;; Nothing in S7 - S15, bank 1 and 2
466 ;; Nothing in S15, bank 3
469 ;; Now, move on to the regular register restoration process.
471 move.d reg, $acr ; Reset ACR to point at the beginning of the register image
472 move.d [$acr], $r0 ; Restore R0
474 move.d [$acr], $r1 ; Restore R1
476 move.d [$acr], $r2 ; Restore R2
478 move.d [$acr], $r3 ; Restore R3
480 move.d [$acr], $r4 ; Restore R4
482 move.d [$acr], $r5 ; Restore R5
484 move.d [$acr], $r6 ; Restore R6
486 move.d [$acr], $r7 ; Restore R7
488 move.d [$acr], $r8 ; Restore R8
490 move.d [$acr], $r9 ; Restore R9
492 move.d [$acr], $r10 ; Restore R10
494 move.d [$acr], $r11 ; Restore R11
496 move.d [$acr], $r12 ; Restore R12
498 move.d [$acr], $r13 ; Restore R13
501 ;; We restore all registers, even though some of them probably haven't changed.
505 move.d [$acr], $sp ; Restore SP (R14)
507 ;; ACR cannot be restored just yet.
513 move [$acr], $pid ; Restore PID
515 move [$acr], $srs ; Restore SRS
524 move [$acr], $exs ; Restore EXS.
526 move [$acr], $eda ; Restore EDA.
528 move [$acr], $mof ; Restore MOF.
533 move [$acr], $ebp ; Restore EBP.
535 move [$acr], $erp ; Restore ERP.
537 move [$acr], $srp ; Restore SRP.
539 move [$acr], $nrp ; Restore NRP.
541 move [$acr], $ccs ; Restore CCS like an ordinary register.
543 move [$acr], $usp ; Restore USP
545 move [$acr], $spc ; Restore SPC
546 ; No restoration of pseudo-PC of course.
548 move.d reg, $acr ; Reset ACR to point at the beginning of the register image
550 move.d [$acr], $acr ; Finally, restore ACR.
551 rete ; Same as jump ERP