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