Merge branch 'origin'
[pandora-kernel.git] / arch / sh / kernel / entry.S
1 /* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
2  *
3  *  linux/arch/sh/entry.S
4  *
5  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
6  *  Copyright (C) 2003  Paul Mundt
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file "COPYING" in the main directory of this archive
10  * for more details.
11  *
12  */
13
14 #include <linux/sys.h>
15 #include <linux/linkage.h>
16 #include <linux/config.h>
17 #include <asm/asm-offsets.h>
18 #include <asm/thread_info.h>
19 #include <asm/cpu/mmu_context.h>
20 #include <asm/unistd.h>
21
22 #if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
23 #define sys_nfsservctl          sys_ni_syscall
24 #endif
25
26 #if !defined(CONFIG_MMU)
27 #define sys_madvise             sys_ni_syscall
28 #define sys_readahead           sys_ni_syscall
29 #define sys_mprotect            sys_ni_syscall
30 #define sys_msync               sys_ni_syscall
31 #define sys_mlock               sys_ni_syscall
32 #define sys_munlock             sys_ni_syscall
33 #define sys_mlockall            sys_ni_syscall
34 #define sys_munlockall          sys_ni_syscall
35 #define sys_mremap              sys_ni_syscall
36 #define sys_mincore             sys_ni_syscall
37 #define sys_remap_file_pages    sys_ni_syscall
38 #endif
39
40 ! NOTE:
41 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
42 ! to be jumped is too far, but it causes illegal slot exception.
43
44 /*      
45  * entry.S contains the system-call and fault low-level handling routines.
46  * This also contains the timer-interrupt handler, as well as all interrupts
47  * and faults that can result in a task-switch.
48  *
49  * NOTE: This code handles signal-recognition, which happens every time
50  * after a timer-interrupt and after each system call.
51  *
52  * NOTE: This code uses a convention that instructions in the delay slot
53  * of a transfer-control instruction are indented by an extra space, thus:
54  *
55  *    jmp       @k0         ! control-transfer instruction
56  *     ldc      k1, ssr     ! delay slot
57  *
58  * Stack layout in 'ret_from_syscall':
59  *      ptrace needs to have all regs on the stack.
60  *      if the order here is changed, it needs to be
61  *      updated in ptrace.c and ptrace.h
62  *
63  *      r0
64  *      ...
65  *      r15 = stack pointer
66  *      spc
67  *      pr
68  *      ssr
69  *      gbr
70  *      mach
71  *      macl
72  *      syscall #
73  *
74  */
75
76 ENOSYS = 38
77 EINVAL = 22
78
79 #if defined(CONFIG_KGDB_NMI)
80 NMI_VEC = 0x1c0                 ! Must catch early for debounce
81 #endif
82
83 /* Offsets to the stack */
84 OFF_R0  =  0            /* Return value. New ABI also arg4 */
85 OFF_R1  =  4            /* New ABI: arg5 */
86 OFF_R2  =  8            /* New ABI: arg6 */
87 OFF_R3  =  12           /* New ABI: syscall_nr */
88 OFF_R4  =  16           /* New ABI: arg0 */
89 OFF_R5  =  20           /* New ABI: arg1 */
90 OFF_R6  =  24           /* New ABI: arg2 */
91 OFF_R7  =  28           /* New ABI: arg3 */
92 OFF_SP  =  (15*4)
93 OFF_PC  =  (16*4)
94 OFF_SR  =  (16*4+8)
95 OFF_TRA =  (16*4+6*4)
96
97
98 #define k0      r0
99 #define k1      r1
100 #define k2      r2
101 #define k3      r3
102 #define k4      r4
103
104 #define k_ex_code       r2_bank /* r2_bank1 */
105 #define g_imask         r6      /* r6_bank1 */
106 #define k_g_imask       r6_bank /* r6_bank1 */
107 #define current         r7      /* r7_bank1 */
108
109 /*
110  * Kernel mode register usage:
111  *      k0      scratch
112  *      k1      scratch
113  *      k2      scratch (Exception code)
114  *      k3      scratch (Return address)
115  *      k4      scratch
116  *      k5      reserved
117  *      k6      Global Interrupt Mask (0--15 << 4)
118  *      k7      CURRENT_THREAD_INFO (pointer to current thread info)
119  */
120
121 !
122 ! TLB Miss / Initial Page write exception handling
123 !                       _and_
124 ! TLB hits, but the access violate the protection.
125 ! It can be valid access, such as stack grow and/or C-O-W.
126 !
127 !
128 ! Find the pmd/pte entry and loadtlb
129 ! If it's not found, cause address error (SEGV)
130 !
131 ! Although this could be written in assembly language (and it'd be faster),
132 ! this first version depends *much* on C implementation.
133 !
134
135 #define CLI()                           \
136         stc     sr, r0;                 \
137         or      #0xf0, r0;              \
138         ldc     r0, sr
139
140 #define STI()                           \
141         mov.l   __INV_IMASK, r11;       \
142         stc     sr, r10;                \
143         and     r11, r10;               \
144         stc     k_g_imask, r11;         \
145         or      r11, r10;               \
146         ldc     r10, sr
147
148 #if defined(CONFIG_PREEMPT)
149 #  define preempt_stop()        CLI()
150 #else
151 #  define preempt_stop()
152 #  define resume_kernel         restore_all
153 #endif
154
155 #if defined(CONFIG_MMU)
156         .align  2
157 ENTRY(tlb_miss_load)
158         bra     call_dpf
159          mov    #0, r5
160
161         .align  2
162 ENTRY(tlb_miss_store)
163         bra     call_dpf
164          mov    #1, r5
165
166         .align  2
167 ENTRY(initial_page_write)
168         bra     call_dpf
169          mov    #1, r5
170
171         .align  2
172 ENTRY(tlb_protection_violation_load)
173         bra     call_dpf
174          mov    #0, r5
175
176         .align  2
177 ENTRY(tlb_protection_violation_store)
178         bra     call_dpf
179          mov    #1, r5
180
181 call_dpf:
182         mov.l   1f, r0
183         mov     r5, r8
184         mov.l   @r0, r6
185         mov     r6, r9
186         mov.l   2f, r0
187         sts     pr, r10
188         jsr     @r0
189          mov    r15, r4
190         !
191         tst     r0, r0
192         bf/s    0f
193          lds    r10, pr
194         rts
195          nop
196 0:      STI()
197         mov.l   3f, r0
198         mov     r9, r6
199         mov     r8, r5
200         jmp     @r0
201          mov    r15, r4
202
203         .align 2
204 1:      .long   MMU_TEA
205 2:      .long   __do_page_fault
206 3:      .long   do_page_fault
207
208         .align  2
209 ENTRY(address_error_load)
210         bra     call_dae
211          mov    #0,r5           ! writeaccess = 0
212
213         .align  2
214 ENTRY(address_error_store)
215         bra     call_dae
216          mov    #1,r5           ! writeaccess = 1
217
218         .align  2
219 call_dae:
220         mov.l   1f, r0
221         mov.l   @r0, r6         ! address
222         mov.l   2f, r0
223         jmp     @r0
224          mov    r15, r4         ! regs
225
226         .align 2
227 1:      .long   MMU_TEA
228 2:      .long   do_address_error
229 #endif /* CONFIG_MMU */
230
231 #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
232 ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
233 ! If both are configured, handle the debug traps (breakpoints) in SW,
234 ! but still allow BIOS traps to FW.
235
236         .align  2
237 debug_kernel:
238 #if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
239         /* Force BIOS call to FW (debug_trap put TRA in r8) */
240         mov     r8,r0
241         shlr2   r0
242         cmp/eq  #0x3f,r0
243         bt      debug_kernel_fw
244 #endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
245
246 debug_enter:            
247 #if defined(CONFIG_SH_KGDB)
248         /* Jump to kgdb, pass stacked regs as arg */
249 debug_kernel_sw:
250         mov.l   3f, r0
251         jmp     @r0
252          mov    r15, r4
253         .align  2
254 3:      .long   kgdb_handle_exception
255 #endif /* CONFIG_SH_KGDB */
256
257 #if defined(CONFIG_SH_STANDARD_BIOS)
258         /* Unwind the stack and jmp to the debug entry */
259 debug_kernel_fw:
260         mov.l   @r15+, r0
261         mov.l   @r15+, r1
262         mov.l   @r15+, r2
263         mov.l   @r15+, r3
264         mov.l   @r15+, r4
265         mov.l   @r15+, r5
266         mov.l   @r15+, r6
267         mov.l   @r15+, r7
268         stc     sr, r8
269         mov.l   1f, r9                  ! BL =1, RB=1, IMASK=0x0F
270         or      r9, r8
271         ldc     r8, sr                  ! here, change the register bank
272         mov.l   @r15+, r8
273         mov.l   @r15+, r9
274         mov.l   @r15+, r10
275         mov.l   @r15+, r11
276         mov.l   @r15+, r12
277         mov.l   @r15+, r13
278         mov.l   @r15+, r14
279         mov.l   @r15+, k0
280         ldc.l   @r15+, spc
281         lds.l   @r15+, pr
282         mov.l   @r15+, k1
283         ldc.l   @r15+, gbr
284         lds.l   @r15+, mach
285         lds.l   @r15+, macl
286         mov     k0, r15
287         !
288         mov.l   2f, k0
289         mov.l   @k0, k0
290         jmp     @k0
291          ldc    k1, ssr
292         .align  2
293 1:      .long   0x300000f0
294 2:      .long   gdb_vbr_vector
295 #endif /* CONFIG_SH_STANDARD_BIOS */
296
297 #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
298
299
300         .align  2
301 debug_trap:     
302 #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
303         mov     #OFF_SR, r0
304         mov.l   @(r0,r15), r0           ! get status register
305         shll    r0
306         shll    r0                      ! kernel space?
307         bt/s    debug_kernel
308 #endif
309          mov.l  @r15, r0                ! Restore R0 value
310         mov.l   1f, r8
311         jmp     @r8
312          nop
313
314         .align  2
315 ENTRY(exception_error)
316         !
317         STI()
318         mov.l   2f, r0
319         jmp     @r0
320          nop
321
322 !
323         .align  2
324 1:      .long   break_point_trap_software
325 2:      .long   do_exception_error
326
327         .align  2
328 ret_from_exception:
329         preempt_stop()
330 ret_from_irq:
331         !
332         mov     #OFF_SR, r0
333         mov.l   @(r0,r15), r0   ! get status register
334         shll    r0
335         shll    r0              ! kernel space?
336         bt/s    resume_kernel   ! Yes, it's from kernel, go back soon
337          GET_THREAD_INFO(r8)
338
339 #ifdef CONFIG_PREEMPT
340         bra     resume_userspace
341          nop
342 ENTRY(resume_kernel)
343         mov.l   @(TI_PRE_COUNT,r8), r0  ! current_thread_info->preempt_count
344         tst     r0, r0
345         bf      noresched
346 need_resched:
347         mov.l   @(TI_FLAGS,r8), r0      ! current_thread_info->flags
348         tst     #_TIF_NEED_RESCHED, r0  ! need_resched set?
349         bt      noresched
350
351         mov     #OFF_SR, r0
352         mov.l   @(r0,r15), r0           ! get status register
353         and     #0xf0, r0               ! interrupts off (exception path)?
354         cmp/eq  #0xf0, r0
355         bt      noresched
356
357         mov.l   1f, r0
358         mov.l   r0, @(TI_PRE_COUNT,r8)
359
360         STI()
361         mov.l   2f, r0
362         jsr     @r0
363          nop
364         mov     #0, r0
365         mov.l   r0, @(TI_PRE_COUNT,r8)
366         CLI()
367
368         bra     need_resched
369          nop
370 noresched:
371         bra     restore_all
372          nop
373
374         .align 2
375 1:      .long   PREEMPT_ACTIVE
376 2:      .long   schedule
377 #endif
378
379 ENTRY(resume_userspace)
380         ! r8: current_thread_info
381         CLI()
382         mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
383         tst     #_TIF_WORK_MASK, r0
384         bt/s    restore_all
385          tst    #_TIF_NEED_RESCHED, r0
386
387         .align  2
388 work_pending:
389         ! r0: current_thread_info->flags
390         ! r8: current_thread_info
391         ! t:  result of "tst    #_TIF_NEED_RESCHED, r0"
392         bf/s    work_resched
393          tst    #_TIF_SIGPENDING, r0
394 work_notifysig:
395         bt/s    restore_all
396          mov    r15, r4
397         mov     #0, r5
398         mov.l   2f, r1
399         mova    restore_all, r0
400         jmp     @r1
401          lds    r0, pr
402 work_resched:
403 #ifndef CONFIG_PREEMPT
404         ! gUSA handling
405         mov.l   @(OFF_SP,r15), r0       ! get user space stack pointer
406         mov     r0, r1
407         shll    r0
408         bf/s    1f
409          shll   r0
410         bf/s    1f
411          mov    #OFF_PC, r0
412         !                                 SP >= 0xc0000000 : gUSA mark
413         mov.l   @(r0,r15), r2           ! get user space PC (program counter)
414         mov.l   @(OFF_R0,r15), r3       ! end point
415         cmp/hs  r3, r2                  ! r2 >= r3? 
416         bt      1f
417         add     r3, r1                  ! rewind point #2
418         mov.l   r1, @(r0,r15)           ! reset PC to rewind point #2
419         !
420 1:
421 #endif
422         mov.l   1f, r1
423         jsr     @r1                             ! schedule
424          nop
425         CLI()
426         !
427         mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
428         tst     #_TIF_WORK_MASK, r0
429         bt      restore_all
430         bra     work_pending
431          tst    #_TIF_NEED_RESCHED, r0
432
433         .align  2
434 1:      .long   schedule
435 2:      .long   do_signal
436
437         .align  2
438 syscall_exit_work:
439         ! r0: current_thread_info->flags
440         ! r8: current_thread_info
441         tst     #_TIF_SYSCALL_TRACE, r0
442         bt/s    work_pending
443          tst    #_TIF_NEED_RESCHED, r0
444         STI()
445         ! XXX setup arguments...
446         mov.l   4f, r0                  ! do_syscall_trace
447         jsr     @r0
448          nop
449         bra     resume_userspace
450          nop
451
452         .align  2
453 syscall_trace_entry:
454         !                       Yes it is traced.
455         ! XXX setup arguments...
456         mov.l   4f, r11         ! Call do_syscall_trace which notifies
457         jsr     @r11            ! superior (will chomp R[0-7])
458          nop
459         !                       Reload R0-R4 from kernel stack, where the
460         !                       parent may have modified them using
461         !                       ptrace(POKEUSR).  (Note that R0-R2 are
462         !                       used by the system call handler directly
463         !                       from the kernel stack anyway, so don't need
464         !                       to be reloaded here.)  This allows the parent
465         !                       to rewrite system calls and args on the fly.
466         mov.l   @(OFF_R4,r15), r4   ! arg0
467         mov.l   @(OFF_R5,r15), r5
468         mov.l   @(OFF_R6,r15), r6
469         mov.l   @(OFF_R7,r15), r7   ! arg3
470         mov.l   @(OFF_R3,r15), r3   ! syscall_nr
471         !                   Arrange for do_syscall_trace to be called
472         !                   again as the system call returns.
473         mov.l   2f, r10                 ! Number of syscalls
474         cmp/hs  r10, r3
475         bf      syscall_call
476         mov     #-ENOSYS, r0
477         bra     syscall_exit
478          mov.l  r0, @(OFF_R0,r15)       ! Return value
479
480 /*
481  * Syscall interface:
482  *
483  *      Syscall #: R3
484  *      Arguments #0 to #3: R4--R7
485  *      Arguments #4 to #6: R0, R1, R2
486  *      TRA: (number of arguments + 0x10) x 4
487  *
488  * This code also handles delegating other traps to the BIOS/gdb stub
489  * according to:
490  *
491  * Trap number
492  * (TRA>>2)         Purpose
493  * --------         -------
494  * 0x0-0xf          old syscall ABI
495  * 0x10-0x1f        new syscall ABI
496  * 0x20-0xff        delegated through debug_trap to BIOS/gdb stub.
497  *
498  * Note: When we're first called, the TRA value must be shifted
499  * right 2 bits in order to get the value that was used as the "trapa"
500  * argument.
501  */
502
503         .align  2
504         .globl  ret_from_fork
505 ret_from_fork:
506         mov.l   1f, r8
507         jsr     @r8
508          mov    r0, r4
509         bra     syscall_exit
510          nop
511         .align  2
512 1:      .long   schedule_tail
513         !
514 ENTRY(system_call)
515         mov.l   1f, r9
516         mov.l   @r9, r8         ! Read from TRA (Trap Address) Register
517         !
518         ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
519         mov     #0x7f, r9
520         cmp/hi  r9, r8
521         bt/s    0f
522          mov    #OFF_TRA, r9
523         add     r15, r9
524         !
525         mov.l   r8, @r9                 ! set TRA value to tra
526         STI()
527         !                   Call the system call handler through the table.
528         !                   First check for bad syscall number
529         mov     r3, r9
530         mov.l   2f, r8                  ! Number of syscalls
531         cmp/hs  r8, r9
532         bf/s    good_system_call
533          GET_THREAD_INFO(r8)
534 syscall_badsys:                 ! Bad syscall number
535         mov     #-ENOSYS, r0
536         bra     resume_userspace
537          mov.l  r0, @(OFF_R0,r15)       ! Return value
538         !
539 0:
540         bra     debug_trap
541          nop
542         !
543 good_system_call:               ! Good syscall number
544         mov.l   @(TI_FLAGS,r8), r8
545         mov     #_TIF_SYSCALL_TRACE, r10
546         tst     r10, r8
547         bf      syscall_trace_entry
548         !
549 syscall_call:
550         shll2   r9              ! x4
551         mov.l   3f, r8          ! Load the address of sys_call_table
552         add     r8, r9
553         mov.l   @r9, r8
554         jsr     @r8             ! jump to specific syscall handler
555          nop
556         mov.l   r0, @(OFF_R0,r15)               ! save the return value
557         !
558 syscall_exit:
559         CLI()
560         !
561         GET_THREAD_INFO(r8)
562         mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
563         tst     #_TIF_ALLWORK_MASK, r0
564         bf      syscall_exit_work
565 restore_all:
566         mov.l   @r15+, r0
567         mov.l   @r15+, r1
568         mov.l   @r15+, r2
569         mov.l   @r15+, r3
570         mov.l   @r15+, r4
571         mov.l   @r15+, r5
572         mov.l   @r15+, r6
573         mov.l   @r15+, r7
574         !
575         stc     sr, r8
576         mov.l   7f, r9
577         or      r9, r8                  ! BL =1, RB=1
578         ldc     r8, sr                  ! here, change the register bank
579         !
580         mov.l   @r15+, r8
581         mov.l   @r15+, r9
582         mov.l   @r15+, r10
583         mov.l   @r15+, r11
584         mov.l   @r15+, r12
585         mov.l   @r15+, r13
586         mov.l   @r15+, r14
587         mov.l   @r15+, k4               ! original stack pointer
588         ldc.l   @r15+, spc
589         lds.l   @r15+, pr
590         mov.l   @r15+, k3               ! original SR
591         ldc.l   @r15+, gbr
592         lds.l   @r15+, mach
593         lds.l   @r15+, macl
594         add     #4, r15                 ! Skip syscall number
595         !
596 #ifdef CONFIG_SH_DSP
597         mov.l   @r15+, k0               ! DSP mode marker
598         mov.l   5f, k1
599         cmp/eq  k0, k1                  ! Do we have a DSP stack frame?
600         bf      skip_restore
601
602         stc     sr, k0                  ! Enable CPU DSP mode
603         or      k1, k0                  ! (within kernel it may be disabled)
604         ldc     k0, sr
605         mov     r2, k0                  ! Backup r2
606
607         ! Restore DSP registers from stack
608         mov     r15, r2
609         movs.l  @r2+, a1
610         movs.l  @r2+, a0g
611         movs.l  @r2+, a1g
612         movs.l  @r2+, m0
613         movs.l  @r2+, m1
614         mov     r2, r15
615
616         lds.l   @r15+, a0
617         lds.l   @r15+, x0
618         lds.l   @r15+, x1
619         lds.l   @r15+, y0
620         lds.l   @r15+, y1
621         lds.l   @r15+, dsr
622         ldc.l   @r15+, rs
623         ldc.l   @r15+, re
624         ldc.l   @r15+, mod
625
626         mov     k0, r2                  ! Restore r2
627 skip_restore:
628 #endif
629         !
630         ! Calculate new SR value
631         mov     k3, k2                  ! original SR value
632         mov.l   9f, k1
633         and     k1, k2                  ! Mask orignal SR value
634         !
635         mov     k3, k0                  ! Calculate IMASK-bits
636         shlr2   k0
637         and     #0x3c, k0
638         cmp/eq  #0x3c, k0
639         bt/s    6f
640          shll2  k0
641         mov     g_imask, k0
642         !
643 6:      or      k0, k2                  ! Set the IMASK-bits
644         ldc     k2, ssr
645         !
646 #if defined(CONFIG_KGDB_NMI)
647         ! Clear in_nmi
648         mov.l   4f, k0
649         mov     #0, k1
650         mov.b   k1, @k0
651 #endif
652         mov.l   @r15+, k2               ! restore EXPEVT
653         mov     k4, r15
654         rte
655          nop
656
657         .align  2
658 1:      .long   TRA
659 2:      .long   NR_syscalls
660 3:      .long   sys_call_table
661 4:      .long   do_syscall_trace
662 5:      .long   0x00001000      ! DSP
663 7:      .long   0x30000000
664 9:
665 __INV_IMASK:
666         .long   0xffffff0f      ! ~(IMASK)
667
668 ! Exception Vector Base
669 !
670 !       Should be aligned page boundary.
671 !
672         .balign         4096,0,4096
673 ENTRY(vbr_base)
674         .long   0
675 !
676         .balign         256,0,256
677 general_exception:
678         mov.l   1f, k2
679         mov.l   2f, k3
680         bra     handle_exception
681          mov.l  @k2, k2
682         .align  2
683 1:      .long   EXPEVT
684 2:      .long   ret_from_exception
685 !
686 !
687         .balign         1024,0,1024
688 tlb_miss:
689         mov.l   1f, k2
690         mov.l   4f, k3
691         bra     handle_exception
692          mov.l  @k2, k2
693 !
694         .balign         512,0,512
695 interrupt:
696         mov.l   2f, k2
697         mov.l   3f, k3
698 #if defined(CONFIG_KGDB_NMI)
699         ! Debounce (filter nested NMI)
700         mov.l   @k2, k0
701         mov.l   5f, k1
702         cmp/eq  k1, k0
703         bf      0f
704         mov.l   6f, k1
705         tas.b   @k1
706         bt      0f
707         rte
708          nop
709         .align  2
710 5:      .long   NMI_VEC
711 6:      .long   in_nmi
712 0:
713 #endif /* defined(CONFIG_KGDB_NMI) */
714         bra     handle_exception
715          mov.l  @k2, k2
716
717         .align  2
718 1:      .long   EXPEVT
719 2:      .long   INTEVT
720 3:      .long   ret_from_irq
721 4:      .long   ret_from_exception
722
723 !
724 !
725         .align  2
726 handle_exception:
727         ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
728         ! save all registers onto stack.
729         !
730         stc     ssr, k0         ! Is it from kernel space?
731         shll    k0              ! Check MD bit (bit30) by shifting it into...
732         shll    k0              !       ...the T bit
733         bt/s    1f              ! It's a kernel to kernel transition.
734          mov    r15, k0         ! save original stack to k0
735         /* User space to kernel */
736         mov     #0x20, k1
737         shll8   k1              ! k1 := 8192 (== THREAD_SIZE)
738         add     current, k1
739         mov     k1, r15         ! change to kernel stack
740         !
741 1:      mov     #-1, k4
742         mov.l   2f, k1
743         !
744 #ifdef CONFIG_SH_DSP
745         mov.l   r2, @-r15               ! Save r2, we need another reg
746         stc     sr, k4
747         mov.l   1f, r2
748         tst     r2, k4                  ! Check if in DSP mode
749         mov.l   @r15+, r2               ! Restore r2 now
750         bt/s    skip_save
751          mov    #0, k4                  ! Set marker for no stack frame
752
753         mov     r2, k4                  ! Backup r2 (in k4) for later
754
755         ! Save DSP registers on stack
756         stc.l   mod, @-r15
757         stc.l   re, @-r15
758         stc.l   rs, @-r15
759         sts.l   dsr, @-r15
760         sts.l   y1, @-r15
761         sts.l   y0, @-r15
762         sts.l   x1, @-r15
763         sts.l   x0, @-r15
764         sts.l   a0, @-r15
765
766         ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr.
767
768         ! FIXME: Make sure that this is still the case with newer toolchains,
769         ! as we're not at all interested in supporting ancient toolchains at
770         ! this point. -- PFM.
771
772         mov     r15, r2
773         .word   0xf653                  ! movs.l        a1, @-r2
774         .word   0xf6f3                  ! movs.l        a0g, @-r2
775         .word   0xf6d3                  ! movs.l        a1g, @-r2
776         .word   0xf6c3                  ! movs.l        m0, @-r2
777         .word   0xf6e3                  ! movs.l        m1, @-r2
778         mov     r2, r15
779
780         mov     k4, r2                  ! Restore r2
781         mov.l   1f, k4                  ! Force DSP stack frame
782 skip_save:
783         mov.l   k4, @-r15               ! Push DSP mode marker onto stack
784 #endif
785         ! Save the user registers on the stack.
786         mov.l   k2, @-r15       ! EXPEVT
787         mov.l   k4, @-r15       ! set TRA (default: -1)
788         !
789         sts.l   macl, @-r15
790         sts.l   mach, @-r15
791         stc.l   gbr, @-r15
792         stc.l   ssr, @-r15
793         sts.l   pr, @-r15
794         stc.l   spc, @-r15
795         !
796         lds     k3, pr          ! Set the return address to pr
797         !
798         mov.l   k0, @-r15       ! save orignal stack
799         mov.l   r14, @-r15
800         mov.l   r13, @-r15
801         mov.l   r12, @-r15
802         mov.l   r11, @-r15
803         mov.l   r10, @-r15
804         mov.l   r9, @-r15
805         mov.l   r8, @-r15
806         !
807         stc     sr, r8          ! Back to normal register bank, and
808         or      k1, r8          ! Block all interrupts
809         mov.l   3f, k1
810         and     k1, r8          ! ...
811         ldc     r8, sr          ! ...changed here.
812         !
813         mov.l   r7, @-r15
814         mov.l   r6, @-r15
815         mov.l   r5, @-r15
816         mov.l   r4, @-r15
817         mov.l   r3, @-r15
818         mov.l   r2, @-r15
819         mov.l   r1, @-r15
820         mov.l   r0, @-r15
821         ! Then, dispatch to the handler, according to the exception code.
822         stc     k_ex_code, r8
823         shlr2   r8
824         shlr    r8
825         mov.l   4f, r9
826         add     r8, r9
827         mov.l   @r9, r9
828         jmp     @r9
829          nop
830
831         .align  2
832 1:      .long   0x00001000      ! DSP=1
833 2:      .long   0x000080f0      ! FD=1, IMASK=15
834 3:      .long   0xcfffffff      ! RB=0, BL=0
835 4:      .long   exception_handling_table
836
837         .align  2
838 ENTRY(exception_none)
839         rts
840          nop
841
842         .data
843 ENTRY(sys_call_table)
844         .long sys_ni_syscall    /* 0  -  old "setup()" system call*/
845         .long sys_exit
846         .long sys_fork
847         .long sys_read
848         .long sys_write
849         .long sys_open          /* 5 */
850         .long sys_close
851         .long sys_waitpid
852         .long sys_creat
853         .long sys_link
854         .long sys_unlink                /* 10 */
855         .long sys_execve
856         .long sys_chdir
857         .long sys_time
858         .long sys_mknod
859         .long sys_chmod         /* 15 */
860         .long sys_lchown16
861         .long sys_ni_syscall    /* old break syscall holder */
862         .long sys_stat
863         .long sys_lseek
864         .long sys_getpid                /* 20 */
865         .long sys_mount
866         .long sys_oldumount
867         .long sys_setuid16
868         .long sys_getuid16
869         .long sys_stime         /* 25 */
870         .long sys_ptrace
871         .long sys_alarm
872         .long sys_fstat
873         .long sys_pause
874         .long sys_utime         /* 30 */
875         .long sys_ni_syscall    /* old stty syscall holder */
876         .long sys_ni_syscall    /* old gtty syscall holder */
877         .long sys_access
878         .long sys_nice
879         .long sys_ni_syscall    /* 35 */                /* old ftime syscall holder */
880         .long sys_sync
881         .long sys_kill
882         .long sys_rename
883         .long sys_mkdir
884         .long sys_rmdir         /* 40 */
885         .long sys_dup
886         .long sys_pipe
887         .long sys_times
888         .long sys_ni_syscall    /* old prof syscall holder */
889         .long sys_brk           /* 45 */
890         .long sys_setgid16
891         .long sys_getgid16
892         .long sys_signal
893         .long sys_geteuid16
894         .long sys_getegid16     /* 50 */
895         .long sys_acct
896         .long sys_umount                /* recycled never used phys() */
897         .long sys_ni_syscall    /* old lock syscall holder */
898         .long sys_ioctl
899         .long sys_fcntl         /* 55 */
900         .long sys_ni_syscall    /* old mpx syscall holder */
901         .long sys_setpgid
902         .long sys_ni_syscall    /* old ulimit syscall holder */
903         .long sys_ni_syscall    /* sys_olduname */
904         .long sys_umask         /* 60 */
905         .long sys_chroot
906         .long sys_ustat
907         .long sys_dup2
908         .long sys_getppid
909         .long sys_getpgrp               /* 65 */
910         .long sys_setsid
911         .long sys_sigaction
912         .long sys_sgetmask
913         .long sys_ssetmask
914         .long sys_setreuid16    /* 70 */
915         .long sys_setregid16
916         .long sys_sigsuspend
917         .long sys_sigpending
918         .long sys_sethostname
919         .long sys_setrlimit     /* 75 */
920         .long sys_old_getrlimit
921         .long sys_getrusage
922         .long sys_gettimeofday
923         .long sys_settimeofday
924         .long sys_getgroups16   /* 80 */
925         .long sys_setgroups16
926         .long sys_ni_syscall    /* sys_oldselect */
927         .long sys_symlink
928         .long sys_lstat
929         .long sys_readlink              /* 85 */
930         .long sys_uselib
931         .long sys_swapon
932         .long sys_reboot
933         .long old_readdir
934         .long old_mmap          /* 90 */
935         .long sys_munmap
936         .long sys_truncate
937         .long sys_ftruncate
938         .long sys_fchmod
939         .long sys_fchown16              /* 95 */
940         .long sys_getpriority
941         .long sys_setpriority
942         .long sys_ni_syscall    /* old profil syscall holder */
943         .long sys_statfs
944         .long sys_fstatfs               /* 100 */
945         .long sys_ni_syscall    /* ioperm */
946         .long sys_socketcall
947         .long sys_syslog
948         .long sys_setitimer
949         .long sys_getitimer     /* 105 */
950         .long sys_newstat
951         .long sys_newlstat
952         .long sys_newfstat
953         .long sys_uname
954         .long sys_ni_syscall    /* 110 */ /* iopl */
955         .long sys_vhangup
956         .long sys_ni_syscall    /* idle */
957         .long sys_ni_syscall    /* vm86old */
958         .long sys_wait4
959         .long sys_swapoff               /* 115 */
960         .long sys_sysinfo
961         .long sys_ipc
962         .long sys_fsync
963         .long sys_sigreturn
964         .long sys_clone         /* 120 */
965         .long sys_setdomainname
966         .long sys_newuname
967         .long sys_ni_syscall    /* sys_modify_ldt */
968         .long sys_adjtimex
969         .long sys_mprotect              /* 125 */
970         .long sys_sigprocmask
971         .long sys_ni_syscall    /* old "create_module" */
972         .long sys_init_module
973         .long sys_delete_module
974         .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
975         .long sys_quotactl
976         .long sys_getpgid
977         .long sys_fchdir
978         .long sys_bdflush
979         .long sys_sysfs         /* 135 */
980         .long sys_personality
981         .long sys_ni_syscall    /* for afs_syscall */
982         .long sys_setfsuid16
983         .long sys_setfsgid16
984         .long sys_llseek                /* 140 */
985         .long sys_getdents
986         .long sys_select
987         .long sys_flock
988         .long sys_msync
989         .long sys_readv         /* 145 */
990         .long sys_writev
991         .long sys_getsid
992         .long sys_fdatasync
993         .long sys_sysctl
994         .long sys_mlock         /* 150 */
995         .long sys_munlock
996         .long sys_mlockall
997         .long sys_munlockall
998         .long sys_sched_setparam
999         .long sys_sched_getparam   /* 155 */
1000         .long sys_sched_setscheduler
1001         .long sys_sched_getscheduler
1002         .long sys_sched_yield
1003         .long sys_sched_get_priority_max
1004         .long sys_sched_get_priority_min  /* 160 */
1005         .long sys_sched_rr_get_interval
1006         .long sys_nanosleep
1007         .long sys_mremap
1008         .long sys_setresuid16
1009         .long sys_getresuid16   /* 165 */
1010         .long sys_ni_syscall    /* vm86 */
1011         .long sys_ni_syscall    /* old "query_module" */
1012         .long sys_poll
1013         .long sys_nfsservctl
1014         .long sys_setresgid16   /* 170 */
1015         .long sys_getresgid16
1016         .long sys_prctl
1017         .long sys_rt_sigreturn
1018         .long sys_rt_sigaction
1019         .long sys_rt_sigprocmask        /* 175 */
1020         .long sys_rt_sigpending
1021         .long sys_rt_sigtimedwait
1022         .long sys_rt_sigqueueinfo
1023         .long sys_rt_sigsuspend
1024         .long sys_pread_wrapper    /* 180 */
1025         .long sys_pwrite_wrapper
1026         .long sys_chown16
1027         .long sys_getcwd
1028         .long sys_capget
1029         .long sys_capset           /* 185 */
1030         .long sys_sigaltstack
1031         .long sys_sendfile
1032         .long sys_ni_syscall    /* streams1 */
1033         .long sys_ni_syscall    /* streams2 */
1034         .long sys_vfork            /* 190 */
1035         .long sys_getrlimit
1036         .long sys_mmap2
1037         .long sys_truncate64
1038         .long sys_ftruncate64
1039         .long sys_stat64                /* 195 */
1040         .long sys_lstat64
1041         .long sys_fstat64
1042         .long sys_lchown
1043         .long sys_getuid
1044         .long sys_getgid                /* 200 */
1045         .long sys_geteuid
1046         .long sys_getegid
1047         .long sys_setreuid
1048         .long sys_setregid
1049         .long sys_getgroups     /* 205 */
1050         .long sys_setgroups
1051         .long sys_fchown
1052         .long sys_setresuid
1053         .long sys_getresuid
1054         .long sys_setresgid     /* 210 */
1055         .long sys_getresgid
1056         .long sys_chown
1057         .long sys_setuid
1058         .long sys_setgid
1059         .long sys_setfsuid              /* 215 */
1060         .long sys_setfsgid
1061         .long sys_pivot_root
1062         .long sys_mincore
1063         .long sys_madvise
1064         .long sys_getdents64    /* 220 */
1065         .long sys_fcntl64
1066         .long sys_ni_syscall    /* reserved for TUX */
1067         .long sys_ni_syscall    /* Reserved for Security */
1068         .long sys_gettid
1069         .long sys_readahead     /* 225 */
1070         .long sys_setxattr
1071         .long sys_lsetxattr
1072         .long sys_fsetxattr
1073         .long sys_getxattr
1074         .long sys_lgetxattr     /* 230 */
1075         .long sys_fgetxattr
1076         .long sys_listxattr
1077         .long sys_llistxattr
1078         .long sys_flistxattr
1079         .long sys_removexattr   /* 235 */
1080         .long sys_lremovexattr
1081         .long sys_fremovexattr
1082         .long sys_tkill
1083         .long sys_sendfile64
1084         .long sys_futex         /* 240 */
1085         .long sys_sched_setaffinity
1086         .long sys_sched_getaffinity
1087         .long sys_ni_syscall
1088         .long sys_ni_syscall
1089         .long sys_io_setup      /* 245 */
1090         .long sys_io_destroy
1091         .long sys_io_getevents
1092         .long sys_io_submit
1093         .long sys_io_cancel
1094         .long sys_fadvise64     /* 250 */
1095         .long sys_ni_syscall
1096         .long sys_exit_group
1097         .long sys_lookup_dcookie
1098         .long sys_epoll_create
1099         .long sys_epoll_ctl     /* 255 */
1100         .long sys_epoll_wait
1101         .long sys_remap_file_pages
1102         .long sys_set_tid_address
1103         .long sys_timer_create
1104         .long sys_timer_settime         /* 260 */
1105         .long sys_timer_gettime
1106         .long sys_timer_getoverrun
1107         .long sys_timer_delete
1108         .long sys_clock_settime
1109         .long sys_clock_gettime         /* 265 */
1110         .long sys_clock_getres
1111         .long sys_clock_nanosleep
1112         .long sys_statfs64
1113         .long sys_fstatfs64     
1114         .long sys_tgkill                /* 270 */
1115         .long sys_utimes
1116         .long sys_fadvise64_64_wrapper
1117         .long sys_ni_syscall    /* Reserved for vserver */
1118         .long sys_ni_syscall    /* Reserved for mbind */
1119         .long sys_ni_syscall    /* 275 - get_mempolicy */
1120         .long sys_ni_syscall    /* set_mempolicy */
1121         .long sys_mq_open
1122         .long sys_mq_unlink
1123         .long sys_mq_timedsend
1124         .long sys_mq_timedreceive       /* 280 */
1125         .long sys_mq_notify
1126         .long sys_mq_getsetattr
1127         .long sys_ni_syscall    /* Reserved for kexec */
1128         .long sys_waitid
1129         .long sys_add_key               /* 285 */
1130         .long sys_request_key
1131         .long sys_keyctl
1132         .long sys_ioprio_set
1133         .long sys_ioprio_get
1134         .long sys_inotify_init          /* 290 */
1135         .long sys_inotify_add_watch
1136         .long sys_inotify_rm_watch
1137
1138 /* End of entry.S */