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 <asm/arch/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
552