Linux 2.6.28-rc5
[cris-mirror.git] / arch / sh / kernel / cpu / sh3 / entry.S
blob3fe482dd05c164a3b7cce794f17833e115b4af44
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>
20 ! NOTE:
21 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
22 ! to be jumped is too far, but it causes illegal slot exception.
24 /*      
25  * entry.S contains the system-call and fault low-level handling routines.
26  * This also contains the timer-interrupt handler, as well as all interrupts
27  * and faults that can result in a task-switch.
28  *
29  * NOTE: This code handles signal-recognition, which happens every time
30  * after a timer-interrupt and after each system call.
31  *
32  * NOTE: This code uses a convention that instructions in the delay slot
33  * of a transfer-control instruction are indented by an extra space, thus:
34  *
35  *    jmp       @k0         ! control-transfer instruction
36  *     ldc      k1, ssr     ! delay slot
37  *
38  * Stack layout in 'ret_from_syscall':
39  *      ptrace needs to have all regs on the stack.
40  *      if the order here is changed, it needs to be
41  *      updated in ptrace.c and ptrace.h
42  *
43  *      r0
44  *      ...
45  *      r15 = stack pointer
46  *      spc
47  *      pr
48  *      ssr
49  *      gbr
50  *      mach
51  *      macl
52  *      syscall #
53  *
54  */
55 #if defined(CONFIG_KGDB_NMI)
56 NMI_VEC = 0x1c0                 ! Must catch early for debounce
57 #endif
59 /* Offsets to the stack */
60 OFF_R0  =  0            /* Return value. New ABI also arg4 */
61 OFF_R1  =  4            /* New ABI: arg5 */
62 OFF_R2  =  8            /* New ABI: arg6 */
63 OFF_R3  =  12           /* New ABI: syscall_nr */
64 OFF_R4  =  16           /* New ABI: arg0 */
65 OFF_R5  =  20           /* New ABI: arg1 */
66 OFF_R6  =  24           /* New ABI: arg2 */
67 OFF_R7  =  28           /* New ABI: arg3 */
68 OFF_SP  =  (15*4)
69 OFF_PC  =  (16*4)
70 OFF_SR  =  (16*4+8)
71 OFF_TRA =  (16*4+6*4)
74 #define k0      r0
75 #define k1      r1
76 #define k2      r2
77 #define k3      r3
78 #define k4      r4
80 #define g_imask         r6      /* r6_bank1 */
81 #define k_g_imask       r6_bank /* r6_bank1 */
82 #define current         r7      /* r7_bank1 */
84 #include <asm/entry-macros.S>
85         
87  * Kernel mode register usage:
88  *      k0      scratch
89  *      k1      scratch
90  *      k2      scratch (Exception code)
91  *      k3      scratch (Return address)
92  *      k4      scratch
93  *      k5      reserved
94  *      k6      Global Interrupt Mask (0--15 << 4)
95  *      k7      CURRENT_THREAD_INFO (pointer to current thread info)
96  */
99 ! TLB Miss / Initial Page write exception handling
100 !                       _and_
101 ! TLB hits, but the access violate the protection.
102 ! It can be valid access, such as stack grow and/or C-O-W.
105 ! Find the pmd/pte entry and loadtlb
106 ! If it's not found, cause address error (SEGV)
108 ! Although this could be written in assembly language (and it'd be faster),
109 ! this first version depends *much* on C implementation.
112 #if defined(CONFIG_MMU)
113         .align  2
114 ENTRY(tlb_miss_load)
115         bra     call_dpf
116          mov    #0, r5
118         .align  2
119 ENTRY(tlb_miss_store)
120         bra     call_dpf
121          mov    #1, r5
123         .align  2
124 ENTRY(initial_page_write)
125         bra     call_dpf
126          mov    #1, r5
128         .align  2
129 ENTRY(tlb_protection_violation_load)
130         bra     call_dpf
131          mov    #0, r5
133         .align  2
134 ENTRY(tlb_protection_violation_store)
135         bra     call_dpf
136          mov    #1, r5
138 call_dpf:
139         mov.l   1f, r0
140         mov     r5, r8
141         mov.l   @r0, r6
142         mov     r6, r9
143         mov.l   2f, r0
144         sts     pr, r10
145         jsr     @r0
146          mov    r15, r4
147         !
148         tst     r0, r0
149         bf/s    0f
150          lds    r10, pr
151         rts
152          nop
153 0:      mov.l   3f, r0
154         mov     r9, r6
155         mov     r8, r5
156         jmp     @r0
157          mov    r15, r4
159         .align 2
160 1:      .long   MMU_TEA
161 2:      .long   __do_page_fault
162 3:      .long   do_page_fault
164         .align  2
165 ENTRY(address_error_load)
166         bra     call_dae
167          mov    #0,r5           ! writeaccess = 0
169         .align  2
170 ENTRY(address_error_store)
171         bra     call_dae
172          mov    #1,r5           ! writeaccess = 1
174         .align  2
175 call_dae:
176         mov.l   1f, r0
177         mov.l   @r0, r6         ! address
178         mov.l   2f, r0
179         jmp     @r0
180          mov    r15, r4         ! regs
182         .align 2
183 1:      .long   MMU_TEA
184 2:      .long   do_address_error
185 #endif /* CONFIG_MMU */
187 #if defined(CONFIG_SH_STANDARD_BIOS)
188         /* Unwind the stack and jmp to the debug entry */
189 ENTRY(sh_bios_handler)
190         mov.l   @r15+, r0
191         mov.l   @r15+, r1
192         mov.l   @r15+, r2
193         mov.l   @r15+, r3
194         mov.l   @r15+, r4
195         mov.l   @r15+, r5
196         mov.l   @r15+, r6
197         mov.l   @r15+, r7
198         stc     sr, r8
199         mov.l   1f, r9                  ! BL =1, RB=1, IMASK=0x0F
200         or      r9, r8
201         ldc     r8, sr                  ! here, change the register bank
202         mov.l   @r15+, r8
203         mov.l   @r15+, r9
204         mov.l   @r15+, r10
205         mov.l   @r15+, r11
206         mov.l   @r15+, r12
207         mov.l   @r15+, r13
208         mov.l   @r15+, r14
209         mov.l   @r15+, k0
210         ldc.l   @r15+, spc
211         lds.l   @r15+, pr
212         mov.l   @r15+, k1
213         ldc.l   @r15+, gbr
214         lds.l   @r15+, mach
215         lds.l   @r15+, macl
216         mov     k0, r15
217         !
218         mov.l   2f, k0
219         mov.l   @k0, k0
220         jmp     @k0
221          ldc    k1, ssr
222         .align  2
223 1:      .long   0x300000f0
224 2:      .long   gdb_vbr_vector
225 #endif /* CONFIG_SH_STANDARD_BIOS */
227 restore_all:
228         mov.l   @r15+, r0
229         mov.l   @r15+, r1
230         mov.l   @r15+, r2
231         mov.l   @r15+, r3
232         mov.l   @r15+, r4
233         mov.l   @r15+, r5
234         mov.l   @r15+, r6
235         mov.l   @r15+, r7
236         !
237         stc     sr, r8
238         mov.l   7f, r9
239         or      r9, r8                  ! BL =1, RB=1
240         ldc     r8, sr                  ! here, change the register bank
241         !
242         mov.l   @r15+, r8
243         mov.l   @r15+, r9
244         mov.l   @r15+, r10
245         mov.l   @r15+, r11
246         mov.l   @r15+, r12
247         mov.l   @r15+, r13
248         mov.l   @r15+, r14
249         mov.l   @r15+, k4               ! original stack pointer
250         ldc.l   @r15+, spc
251         lds.l   @r15+, pr
252         mov.l   @r15+, k3               ! original SR
253         ldc.l   @r15+, gbr
254         lds.l   @r15+, mach
255         lds.l   @r15+, macl
256         add     #4, r15                 ! Skip syscall number
257         !
258 #ifdef CONFIG_SH_DSP
259         mov.l   @r15+, k0               ! DSP mode marker
260         mov.l   5f, k1
261         cmp/eq  k0, k1                  ! Do we have a DSP stack frame?
262         bf      skip_restore
264         stc     sr, k0                  ! Enable CPU DSP mode
265         or      k1, k0                  ! (within kernel it may be disabled)
266         ldc     k0, sr
267         mov     r2, k0                  ! Backup r2
269         ! Restore DSP registers from stack
270         mov     r15, r2
271         movs.l  @r2+, a1
272         movs.l  @r2+, a0g
273         movs.l  @r2+, a1g
274         movs.l  @r2+, m0
275         movs.l  @r2+, m1
276         mov     r2, r15
278         lds.l   @r15+, a0
279         lds.l   @r15+, x0
280         lds.l   @r15+, x1
281         lds.l   @r15+, y0
282         lds.l   @r15+, y1
283         lds.l   @r15+, dsr
284         ldc.l   @r15+, rs
285         ldc.l   @r15+, re
286         ldc.l   @r15+, mod
288         mov     k0, r2                  ! Restore r2
289 skip_restore:
290 #endif
291         !
292         ! Calculate new SR value
293         mov     k3, k2                  ! original SR value
294         mov     #0xf0, k1
295         extu.b  k1, k1
296         not     k1, k1
297         and     k1, k2                  ! Mask orignal SR value
298         !
299         mov     k3, k0                  ! Calculate IMASK-bits
300         shlr2   k0
301         and     #0x3c, k0
302         cmp/eq  #0x3c, k0
303         bt/s    6f
304          shll2  k0
305         mov     g_imask, k0
306         !
307 6:      or      k0, k2                  ! Set the IMASK-bits
308         ldc     k2, ssr
309         !
310 #if defined(CONFIG_KGDB_NMI)
311         ! Clear in_nmi
312         mov.l   6f, k0
313         mov     #0, k1
314         mov.b   k1, @k0
315 #endif
316         mov.l   @r15+, k2               ! restore EXPEVT
317         mov     k4, r15
318         rte
319          nop
321         .align  2
322 5:      .long   0x00001000      ! DSP
323 #ifdef CONFIG_KGDB_NMI
324 6:      .long   in_nmi
325 #endif
326 7:      .long   0x30000000
328 ! common exception handler
329 #include "../../entry-common.S"
330         
331 ! Exception Vector Base
333 !       Should be aligned page boundary.
335         .balign         4096,0,4096
336 ENTRY(vbr_base)
337         .long   0
339         .balign         256,0,256
340 general_exception:
341         mov.l   1f, k2
342         mov.l   2f, k3
343 #ifdef CONFIG_CPU_SUBTYPE_SHX3
344         mov.l   @k2, k2
346         ! Is EXPEVT larger than 0x800?
347         mov     #0x8, k0
348         shll8   k0
349         cmp/hs  k0, k2
350         bf      0f
352         ! then add 0x580 (k2 is 0xd80 or 0xda0)
353         mov     #0x58, k0
354         shll2   k0
355         shll2   k0
356         add     k0, k2
358         bra     handle_exception
359          nop
360 #else
361         bra     handle_exception
362          mov.l  @k2, k2
363 #endif
364         .align  2
365 1:      .long   EXPEVT
366 2:      .long   ret_from_exception
370         .balign         1024,0,1024
371 tlb_miss:
372         mov.l   1f, k2
373         mov.l   4f, k3
374         bra     handle_exception
375          mov.l  @k2, k2
377         .balign         512,0,512
378 interrupt:
379         mov.l   2f, k2
380         mov.l   3f, k3
381 #if defined(CONFIG_KGDB_NMI)
382         ! Debounce (filter nested NMI)
383         mov.l   @k2, k0
384         mov.l   5f, k1
385         cmp/eq  k1, k0
386         bf      0f
387         mov.l   6f, k1
388         tas.b   @k1
389         bt      0f
390         rte
391          nop
392         .align  2
393 5:      .long   NMI_VEC
394 6:      .long   in_nmi
396 #endif /* defined(CONFIG_KGDB_NMI) */
397         bra     handle_exception
398          mov    #-1, k2         ! interrupt exception marker
400         .align  2
401 1:      .long   EXPEVT
402 2:      .long   INTEVT
403 3:      .long   ret_from_irq
404 4:      .long   ret_from_exception
408         .align  2
409 ENTRY(handle_exception)
410         ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
411         ! save all registers onto stack.
412         !
414 #ifdef CONFIG_GUSA
415         ! Check for roll back gRB (User and Kernel)
416         mov     r15, k0
417         shll    k0
418         bf/s    1f
419          shll   k0
420         bf/s    1f
421          stc    spc, k1
422         stc     r0_bank, k0
423         cmp/hs  k0, k1          ! test k1 (saved PC) >= k0 (saved r0)
424         bt/s    2f
425          stc    r1_bank, k1
427         add     #-2, k0
428         add     r15, k0
429         ldc     k0, spc         ! PC = saved r0 + r15 - 2
430 2:      mov     k1, r15         ! SP = r1
432 #endif
434         stc     ssr, k0         ! Is it from kernel space?
435         shll    k0              ! Check MD bit (bit30) by shifting it into...
436         shll    k0              !       ...the T bit
437         bt/s    1f              ! It's a kernel to kernel transition.
438          mov    r15, k0         ! save original stack to k0
439         /* User space to kernel */
440         mov     #(THREAD_SIZE >> 10), k1
441         shll8   k1              ! k1 := THREAD_SIZE
442         shll2   k1
443         add     current, k1
444         mov     k1, r15         ! change to kernel stack
445         !
446 1:      mov.l   2f, k1
447         !
448 #ifdef CONFIG_SH_DSP
449         mov.l   r2, @-r15               ! Save r2, we need another reg
450         stc     sr, k4
451         mov.l   1f, r2
452         tst     r2, k4                  ! Check if in DSP mode
453         mov.l   @r15+, r2               ! Restore r2 now
454         bt/s    skip_save
455          mov    #0, k4                  ! Set marker for no stack frame
457         mov     r2, k4                  ! Backup r2 (in k4) for later
459         ! Save DSP registers on stack
460         stc.l   mod, @-r15
461         stc.l   re, @-r15
462         stc.l   rs, @-r15
463         sts.l   dsr, @-r15
464         sts.l   y1, @-r15
465         sts.l   y0, @-r15
466         sts.l   x1, @-r15
467         sts.l   x0, @-r15
468         sts.l   a0, @-r15
470         ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr.
472         ! FIXME: Make sure that this is still the case with newer toolchains,
473         ! as we're not at all interested in supporting ancient toolchains at
474         ! this point. -- PFM.
476         mov     r15, r2
477         .word   0xf653                  ! movs.l        a1, @-r2
478         .word   0xf6f3                  ! movs.l        a0g, @-r2
479         .word   0xf6d3                  ! movs.l        a1g, @-r2
480         .word   0xf6c3                  ! movs.l        m0, @-r2
481         .word   0xf6e3                  ! movs.l        m1, @-r2
482         mov     r2, r15
484         mov     k4, r2                  ! Restore r2
485         mov.l   1f, k4                  ! Force DSP stack frame
486 skip_save:
487         mov.l   k4, @-r15               ! Push DSP mode marker onto stack
488 #endif
489         ! Save the user registers on the stack.
490         mov.l   k2, @-r15       ! EXPEVT
492         mov     #-1, k4
493         mov.l   k4, @-r15       ! set TRA (default: -1)
494         !
495         sts.l   macl, @-r15
496         sts.l   mach, @-r15
497         stc.l   gbr, @-r15
498         stc.l   ssr, @-r15
499         sts.l   pr, @-r15
500         stc.l   spc, @-r15
501         !
502         lds     k3, pr          ! Set the return address to pr
503         !
504         mov.l   k0, @-r15       ! save orignal stack
505         mov.l   r14, @-r15
506         mov.l   r13, @-r15
507         mov.l   r12, @-r15
508         mov.l   r11, @-r15
509         mov.l   r10, @-r15
510         mov.l   r9, @-r15
511         mov.l   r8, @-r15
512         !
513         stc     sr, r8          ! Back to normal register bank, and
514         or      k1, r8          ! Block all interrupts
515         mov.l   3f, k1
516         and     k1, r8          ! ...
517         ldc     r8, sr          ! ...changed here.
518         !
519         mov.l   r7, @-r15
520         mov.l   r6, @-r15
521         mov.l   r5, @-r15
522         mov.l   r4, @-r15
523         mov.l   r3, @-r15
524         mov.l   r2, @-r15
525         mov.l   r1, @-r15
526         mov.l   r0, @-r15
528         /*
529          * This gets a bit tricky.. in the INTEVT case we don't want to use
530          * the VBR offset as a destination in the jump call table, since all
531          * of the destinations are the same. In this case, (interrupt) sets
532          * a marker in r2 (now r2_bank since SR.RB changed), which we check
533          * to determine the exception type. For all other exceptions, we
534          * forcibly read EXPEVT from memory and fix up the jump address, in
535          * the interrupt exception case we jump to do_IRQ() and defer the
536          * INTEVT read until there. As a bonus, we can also clean up the SR.RB
537          * checks that do_IRQ() was doing..
538          */
539         stc     r2_bank, r8
540         cmp/pz  r8
541         bf      interrupt_exception
542         shlr2   r8
543         shlr    r8
544         mov.l   4f, r9
545         add     r8, r9
546         mov.l   @r9, r9
547         jmp     @r9
548          nop
549         rts
550          nop
552         .align  2
553 1:      .long   0x00001000      ! DSP=1
554 2:      .long   0x000080f0      ! FD=1, IMASK=15
555 3:      .long   0xcfffffff      ! RB=0, BL=0
556 4:      .long   exception_handling_table
558 interrupt_exception:
559         mov.l   1f, r9
560         mov.l   2f, r4
561         mov.l   @r4, r4
562         jmp     @r9
563          mov    r15, r5
564         rts
565          nop
567         .align 2
568 1:      .long   do_IRQ
569 2:      .long   INTEVT
571         .align  2
572 ENTRY(exception_none)
573         rts
574          nop