sh: Add a few missing irqflags tracing markers.
[safe/jmp/linux-2.6] / arch / sh / kernel / cpu / sh3 / entry.S
1 /*
2  * arch/sh/kernel/cpu/sh3/entry.S
3  *
4  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
5  *  Copyright (C) 2003 - 2006  Paul Mundt
6  *
7  * This file is subject to the terms and conditions of the GNU General Public
8  * License.  See the file "COPYING" in the main directory of this archive
9  * for more details.
10  */
11 #include <linux/sys.h>
12 #include <linux/errno.h>
13 #include <linux/linkage.h>
14 #include <asm/asm-offsets.h>
15 #include <asm/thread_info.h>
16 #include <asm/unistd.h>
17 #include <cpu/mmu_context.h>
18 #include <asm/page.h>
19 #include <asm/cache.h>
20
21 ! NOTE:
22 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
23 ! to be jumped is too far, but it causes illegal slot exception.
24
25 /*      
26  * entry.S contains the system-call and fault low-level handling routines.
27  * This also contains the timer-interrupt handler, as well as all interrupts
28  * and faults that can result in a task-switch.
29  *
30  * NOTE: This code handles signal-recognition, which happens every time
31  * after a timer-interrupt and after each system call.
32  *
33  * NOTE: This code uses a convention that instructions in the delay slot
34  * of a transfer-control instruction are indented by an extra space, thus:
35  *
36  *    jmp       @k0         ! control-transfer instruction
37  *     ldc      k1, ssr     ! delay slot
38  *
39  * Stack layout in 'ret_from_syscall':
40  *      ptrace needs to have all regs on the stack.
41  *      if the order here is changed, it needs to be
42  *      updated in ptrace.c and ptrace.h
43  *
44  *      r0
45  *      ...
46  *      r15 = stack pointer
47  *      spc
48  *      pr
49  *      ssr
50  *      gbr
51  *      mach
52  *      macl
53  *      syscall #
54  *
55  */
56 #if defined(CONFIG_KGDB)
57 NMI_VEC = 0x1c0                 ! Must catch early for debounce
58 #endif
59
60 /* Offsets to the stack */
61 OFF_R0  =  0            /* Return value. New ABI also arg4 */
62 OFF_R1  =  4            /* New ABI: arg5 */
63 OFF_R2  =  8            /* New ABI: arg6 */
64 OFF_R3  =  12           /* New ABI: syscall_nr */
65 OFF_R4  =  16           /* New ABI: arg0 */
66 OFF_R5  =  20           /* New ABI: arg1 */
67 OFF_R6  =  24           /* New ABI: arg2 */
68 OFF_R7  =  28           /* New ABI: arg3 */
69 OFF_SP  =  (15*4)
70 OFF_PC  =  (16*4)
71 OFF_SR  =  (16*4+8)
72 OFF_TRA =  (16*4+6*4)
73
74
75 #define k0      r0
76 #define k1      r1
77 #define k2      r2
78 #define k3      r3
79 #define k4      r4
80
81 #define g_imask         r6      /* r6_bank1 */
82 #define k_g_imask       r6_bank /* r6_bank1 */
83 #define current         r7      /* r7_bank1 */
84
85 #include <asm/entry-macros.S>
86         
87 /*
88  * Kernel mode register usage:
89  *      k0      scratch
90  *      k1      scratch
91  *      k2      scratch (Exception code)
92  *      k3      scratch (Return address)
93  *      k4      scratch
94  *      k5      reserved
95  *      k6      Global Interrupt Mask (0--15 << 4)
96  *      k7      CURRENT_THREAD_INFO (pointer to current thread info)
97  */
98
99 !
100 ! TLB Miss / Initial Page write exception handling
101 !                       _and_
102 ! TLB hits, but the access violate the protection.
103 ! It can be valid access, such as stack grow and/or C-O-W.
104 !
105 !
106 ! Find the pmd/pte entry and loadtlb
107 ! If it's not found, cause address error (SEGV)
108 !
109 ! Although this could be written in assembly language (and it'd be faster),
110 ! this first version depends *much* on C implementation.
111 !
112
113 #if defined(CONFIG_MMU)
114         .align  2
115 ENTRY(tlb_miss_load)
116         bra     call_dpf
117          mov    #0, r5
118
119         .align  2
120 ENTRY(tlb_miss_store)
121         bra     call_dpf
122          mov    #1, r5
123
124         .align  2
125 ENTRY(initial_page_write)
126         bra     call_dpf
127          mov    #1, r5
128
129         .align  2
130 ENTRY(tlb_protection_violation_load)
131         bra     call_dpf
132          mov    #0, r5
133
134         .align  2
135 ENTRY(tlb_protection_violation_store)
136         bra     call_dpf
137          mov    #1, r5
138
139 call_dpf:
140         setup_frame_reg
141         mov.l   1f, r0
142         mov     r5, r8
143         mov.l   @r0, r6
144         mov     r6, r9
145         mov.l   2f, r0
146         sts     pr, r10
147         jsr     @r0
148          mov    r15, r4
149         !
150         tst     r0, r0
151         bf/s    0f
152          lds    r10, pr
153         rts
154          nop
155 0:      mov.l   3f, r0
156         mov     r9, r6
157         mov     r8, r5
158         jmp     @r0
159          mov    r15, r4
160
161         .align 2
162 1:      .long   MMU_TEA
163 2:      .long   __do_page_fault
164 3:      .long   do_page_fault
165
166         .align  2
167 ENTRY(address_error_load)
168         bra     call_dae
169          mov    #0,r5           ! writeaccess = 0
170
171         .align  2
172 ENTRY(address_error_store)
173         bra     call_dae
174          mov    #1,r5           ! writeaccess = 1
175
176         .align  2
177 call_dae:
178         mov.l   1f, r0
179         mov.l   @r0, r6         ! address
180         mov.l   2f, r0
181         jmp     @r0
182          mov    r15, r4         ! regs
183
184         .align 2
185 1:      .long   MMU_TEA
186 2:      .long   do_address_error
187 #endif /* CONFIG_MMU */
188
189 #if defined(CONFIG_SH_STANDARD_BIOS)
190         /* Unwind the stack and jmp to the debug entry */
191 ENTRY(sh_bios_handler)
192         mov.l   1f, r8
193         bsr     restore_regs
194          nop
195
196         lds     k2, pr                  ! restore pr
197         mov     k4, r15
198         !
199         mov.l   2f, k0
200         mov.l   @k0, k0
201         jmp     @k0
202          ldc    k3, ssr
203         .align  2
204 1:      .long   0x300000f0
205 2:      .long   gdb_vbr_vector
206 #endif /* CONFIG_SH_STANDARD_BIOS */
207
208 ! restore_regs()
209 ! - restore r0, r1, r2, r3, r4, r5, r6, r7 from the stack
210 ! - switch bank
211 ! - restore r8, r9, r10, r11, r12, r13, r14, r15 from the stack
212 ! - restore spc, pr*, ssr, gbr, mach, macl, skip default tra
213 ! k2 returns original pr
214 ! k3 returns original sr
215 ! k4 returns original stack pointer
216 ! r8 passes SR bitmask, overwritten with restored data on return
217 ! r9 trashed
218 ! BL=0 on entry, on exit BL=1 (depending on r8).
219
220 ENTRY(restore_regs)
221         mov.l   @r15+, r0
222         mov.l   @r15+, r1
223         mov.l   @r15+, r2
224         mov.l   @r15+, r3
225         mov.l   @r15+, r4
226         mov.l   @r15+, r5
227         mov.l   @r15+, r6
228         mov.l   @r15+, r7
229         !
230         stc     sr, r9
231         or      r8, r9
232         ldc     r9, sr
233         !
234         mov.l   @r15+, r8
235         mov.l   @r15+, r9
236         mov.l   @r15+, r10
237         mov.l   @r15+, r11
238         mov.l   @r15+, r12
239         mov.l   @r15+, r13
240         mov.l   @r15+, r14
241         mov.l   @r15+, k4               ! original stack pointer
242         ldc.l   @r15+, spc
243         mov.l   @r15+, k2               ! original PR
244         mov.l   @r15+, k3               ! original SR
245         ldc.l   @r15+, gbr
246         lds.l   @r15+, mach
247         lds.l   @r15+, macl
248         rts
249          add    #4, r15                 ! Skip syscall number
250
251 restore_all:
252         mov.l   7f, r8
253         bsr     restore_regs
254          nop
255
256         lds     k2, pr                  ! restore pr
257         !
258         ! Calculate new SR value
259         mov     k3, k2                  ! original SR value
260         mov     #0xf0, k1
261         extu.b  k1, k1
262         not     k1, k1
263         and     k1, k2                  ! Mask original SR value
264         !
265         mov     k3, k0                  ! Calculate IMASK-bits
266         shlr2   k0
267         and     #0x3c, k0
268         cmp/eq  #0x3c, k0
269         bt/s    6f
270          shll2  k0
271         mov     g_imask, k0
272         !
273 6:      or      k0, k2                  ! Set the IMASK-bits
274         ldc     k2, ssr
275         !
276 #if defined(CONFIG_KGDB)
277         ! Clear in_nmi
278         mov.l   6f, k0
279         mov     #0, k1
280         mov.b   k1, @k0
281 #endif
282         mov     k4, r15
283         rte
284          nop
285
286         .align  2
287 5:      .long   0x00001000      ! DSP
288 #ifdef CONFIG_KGDB
289 6:      .long   in_nmi
290 #endif
291 7:      .long   0x30000000
292
293 ! common exception handler
294 #include "../../entry-common.S"
295         
296 ! Exception Vector Base
297 !
298 !       Should be aligned page boundary.
299 !
300         .balign         4096,0,4096
301 ENTRY(vbr_base)
302         .long   0
303 !
304 ! 0x100: General exception vector
305 !
306         .balign         256,0,256
307 general_exception:
308 #ifndef CONFIG_CPU_SUBTYPE_SHX3
309         bra     handle_exception
310          sts    pr, k3          ! save original pr value in k3
311 #else
312         mov.l   1f, k4
313         mov.l   @k4, k4
314
315         ! Is EXPEVT larger than 0x800?
316         mov     #0x8, k0
317         shll8   k0
318         cmp/hs  k0, k4
319         bf      0f
320
321         ! then add 0x580 (k2 is 0xd80 or 0xda0)
322         mov     #0x58, k0
323         shll2   k0
324         shll2   k0
325         add     k0, k4
326 0:
327         ! Setup stack and save DSP context (k0 contains original r15 on return)
328         bsr     prepare_stack
329          nop
330
331         ! Save registers / Switch to bank 0
332         mov             k4, k2          ! keep vector in k2
333         mov.l   1f, k4          ! SR bits to clear in k4
334         bsr     save_regs       ! needs original pr value in k3
335          nop
336
337         bra     handle_exception_special
338          nop
339
340         .align  2
341 1:      .long   EXPEVT
342 #endif
343
344 ! prepare_stack()
345 ! - roll back gRB
346 ! - switch to kernel stack
347 ! k0 returns original sp (after roll back)
348 ! k1 trashed
349 ! k2 trashed
350
351 prepare_stack:
352 #ifdef CONFIG_GUSA
353         ! Check for roll back gRB (User and Kernel)
354         mov     r15, k0
355         shll    k0
356         bf/s    1f
357          shll   k0
358         bf/s    1f
359          stc    spc, k1
360         stc     r0_bank, k0
361         cmp/hs  k0, k1          ! test k1 (saved PC) >= k0 (saved r0)
362         bt/s    2f
363          stc    r1_bank, k1
364
365         add     #-2, k0
366         add     r15, k0
367         ldc     k0, spc         ! PC = saved r0 + r15 - 2
368 2:      mov     k1, r15         ! SP = r1
369 1:
370 #endif
371         ! Switch to kernel stack if needed
372         stc     ssr, k0         ! Is it from kernel space?
373         shll    k0              ! Check MD bit (bit30) by shifting it into...
374         shll    k0              !       ...the T bit
375         bt/s    1f              ! It's a kernel to kernel transition.
376          mov    r15, k0         ! save original stack to k0
377         /* User space to kernel */
378         mov     #(THREAD_SIZE >> 10), k1
379         shll8   k1              ! k1 := THREAD_SIZE
380         shll2   k1
381         add     current, k1
382         mov     k1, r15         ! change to kernel stack
383         !
384 1:
385         rts
386          nop
387
388 !
389 ! 0x400: Instruction and Data TLB miss exception vector
390 !
391         .balign         1024,0,1024
392 tlb_miss:
393         sts     pr, k3          ! save original pr value in k3
394
395 handle_exception:
396         mova    exception_data, k0
397
398         ! Setup stack and save DSP context (k0 contains original r15 on return)
399         bsr     prepare_stack
400          PREF(k0)
401
402         ! Save registers / Switch to bank 0
403         mov.l   5f, k2          ! vector register address
404         mov.l   1f, k4          ! SR bits to clear in k4
405         bsr     save_regs       ! needs original pr value in k3
406          mov.l  @k2, k2         ! read out vector and keep in k2
407
408 handle_exception_special:
409         ! Setup return address and jump to exception handler
410         mov.l   7f, r9          ! fetch return address
411         stc     r2_bank, r0     ! k2 (vector)
412         mov.l   6f, r10
413         shlr2   r0
414         shlr    r0
415         mov.l   @(r0, r10), r10
416         jmp     @r10
417          lds    r9, pr          ! put return address in pr
418
419         .align  L1_CACHE_SHIFT
420
421 ! save_regs()
422 ! - save default tra, macl, mach, gbr, ssr, pr* and spc on the stack
423 ! - save r15*, r14, r13, r12, r11, r10, r9, r8 on the stack
424 ! - switch bank
425 ! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
426 ! k0 contains original stack pointer*
427 ! k1 trashed
428 ! k3 passes original pr*
429 ! k4 passes SR bitmask
430 ! BL=1 on entry, on exit BL=0.
431
432 ENTRY(save_regs)
433         mov     #-1, r1
434         mov.l   k1, @-r15       ! set TRA (default: -1)
435         sts.l   macl, @-r15
436         sts.l   mach, @-r15
437         stc.l   gbr, @-r15
438         stc.l   ssr, @-r15
439         mov.l   k3, @-r15       ! original pr in k3
440         stc.l   spc, @-r15
441
442         mov.l   k0, @-r15       ! original stack pointer in k0
443         mov.l   r14, @-r15
444         mov.l   r13, @-r15
445         mov.l   r12, @-r15
446         mov.l   r11, @-r15
447         mov.l   r10, @-r15
448         mov.l   r9, @-r15
449         mov.l   r8, @-r15
450
451         mov.l   0f, k3          ! SR bits to set in k3
452
453         ! fall-through
454
455 ! save_low_regs()
456 ! - modify SR for bank switch
457 ! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
458 ! k3 passes bits to set in SR
459 ! k4 passes bits to clear in SR
460
461 ENTRY(save_low_regs)
462         stc     sr, r8
463         or      k3, r8
464         and     k4, r8
465         ldc     r8, sr
466
467         mov.l   r7, @-r15
468         mov.l   r6, @-r15
469         mov.l   r5, @-r15
470         mov.l   r4, @-r15
471         mov.l   r3, @-r15
472         mov.l   r2, @-r15
473         mov.l   r1, @-r15
474         rts
475          mov.l  r0, @-r15
476
477 !
478 ! 0x600: Interrupt / NMI vector
479 !
480         .balign         512,0,512
481 ENTRY(handle_interrupt)
482 #if defined(CONFIG_KGDB)
483         mov.l   2f, k2
484         ! Debounce (filter nested NMI)
485         mov.l   @k2, k0
486         mov.l   9f, k1
487         cmp/eq  k1, k0
488         bf      11f
489         mov.l   10f, k1
490         tas.b   @k1
491         bt      11f
492         rte
493          nop
494         .align  2
495 9:      .long   NMI_VEC
496 10:     .long   in_nmi
497 11:
498 #endif /* defined(CONFIG_KGDB) */
499         sts     pr, k3          ! save original pr value in k3
500         mova    exception_data, k0
501
502         ! Setup stack and save DSP context (k0 contains original r15 on return)
503         bsr     prepare_stack
504          PREF(k0)
505
506         ! Save registers / Switch to bank 0
507         mov.l   1f, k4          ! SR bits to clear in k4
508         bsr     save_regs       ! needs original pr value in k3
509          mov    #-1, k2         ! default vector kept in k2
510
511         stc     sr, r0  ! get status register
512         shlr2   r0
513         and     #0x3c, r0
514         cmp/eq  #0x3c, r0
515         bf      9f
516         TRACE_IRQS_OFF
517 9:
518
519         ! Setup return address and jump to do_IRQ
520         mov.l   4f, r9          ! fetch return address
521         lds     r9, pr          ! put return address in pr
522         mov.l   2f, r4
523         mov.l   3f, r9
524         mov.l   @r4, r4         ! pass INTEVT vector as arg0
525         jmp     @r9
526          mov    r15, r5         ! pass saved registers as arg1
527
528 ENTRY(exception_none)
529         rts
530          nop
531
532         .align  L1_CACHE_SHIFT
533 exception_data:
534 0:      .long   0x000080f0      ! FD=1, IMASK=15
535 1:      .long   0xcfffffff      ! RB=0, BL=0
536 2:      .long   INTEVT
537 3:      .long   do_IRQ
538 4:      .long   ret_from_irq
539 5:      .long   EXPEVT
540 6:      .long   exception_handling_table
541 7:      .long   ret_from_exception