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