Merge with Linux 2.3.40.
[linux-2.6/linux-mips.git] / arch / arm / kernel / entry-common.S
blob2be1a601216025107795e2ca6656bd186c9168b7
1 #include <linux/config.h>
2 /*============================================================================
3  * All exits to user mode from the kernel go through this code.
4  */
6 #define S_OFF           8
7 #define SYSCALL_REGS    r4, r5
9 /*
10  * Define to favour ARM8, ARM9 and StrongARM cpus.  This says that it is
11  * cheaper to use two LDR instructions than a two-register LDM, if the
12  * latter would entail calculating an address specially.
13  */
14 #if defined(CONFIG_CPU_SA110)
15 #define HARVARD_CACHE
16 #endif
18                 .globl  ret_from_sys_call
20                 .align  5
21 fast_syscall_return:
22                 str     r0, [sp, #S_R0 + S_OFF]         @ returned r0
23 slow_syscall_return:
24                 add     sp, sp, #S_OFF
25 ret_from_sys_call:
26 #ifdef HARVARD_CACHE
27                 ldr     r0, bh_data
28                 ldr     r4, bh_data+4
29 #else
30                 adr     r0, bh_data
31                 ldmia   r0, {r0, r4}
32 #endif
33                 ldr     r0, [r0]
34                 ldr     r1, [r4]
35                 tst     r0, r1
36                 blne    SYMBOL_NAME(do_bottom_half)
37 ret_with_reschedule:
38                 get_current_task r5
39                 ldr     r0, [r5, #TSK_NEED_RESCHED]
40                 ldr     r1, [r5, #TSK_SIGPENDING]
41                 teq     r0, #0
42                 bne     ret_reschedule
43                 teq     r1, #0                  @ check for signals
44                 bne     ret_signal
46 ret_from_all:   restore_user_regs
48 ret_signal:     mov     r1, sp
49                 adrsvc  al, lr, ret_from_all
50                 mov     r2, r4
51                 b       SYMBOL_NAME(do_signal)
53 ret_reschedule: adrsvc  al, lr, ret_with_reschedule
54                 b       SYMBOL_NAME(schedule)
56                 .globl  ret_from_exception
57 ret_from_exception:
58 #ifdef HARVARD_CACHE
59                 ldr     r0, bh_data
60                 ldr     r1, bh_data + 4
61 #else
62                 adr     r0, bh_data
63                 ldmia   r0, {r0, r1}
64 #endif
65                 ldr     r0, [r0]
66                 ldr     r1, [r1]
67                 mov     r4, #0
68                 tst     r0, r1
69                 blne    SYMBOL_NAME(do_bottom_half)
70                 ldr     r0, [sp, #S_PSR]
71                 tst     r0, #3                  @ returning to user mode?
72                 beq     ret_with_reschedule
73                 b       ret_from_all
75 #include "calls.S"
77 /*=============================================================================
78  * SWI handler
79  *-----------------------------------------------------------------------------
80  */
83  * Create some aliases for some registers.  These should allow
84  * us to have in theory up to 7 arguments to a function.
85  */
86 scno            .req    r9                      @ syscall number
87 tbl             .req    r8                      @ syscall table pointer
88 tip             .req    r7                      @ temporary IP
90                 .align  5
91 vector_swi:     save_user_regs
92                 mask_pc lr, lr
93                 mov     fp, #0
94                 ldr     scno, [lr, #-4]         @ get SWI instruction
95                 arm700_bug_check scno, ip
96 #ifdef CONFIG_ALIGNMENT_TRAP
97                 ldr     ip, .LCswi
98                 ldr     ip, [ip]
99                 mcr     p15, 0, ip, c1, c0
100 #endif
101                 enable_irqs ip
103                 stmdb   sp!, {SYSCALL_REGS}     @ new style: (r0 = arg1, r4 = arg5, r5 = arg6)
104                                                 @ Note that we dont have to handle
105                                                 @ sys_syscalls arg7 here
106                 adrsvc  al, lr, fast_syscall_return
108                 bic     scno, scno, #0xff000000 @ mask off SWI op-code
109                 eor     scno, scno, #OS_NUMBER<<20      @ check OS number
110                 cmp     scno, #NR_syscalls      @ check upper syscall limit
111                 bcs     2f
113                 get_current_task ip
114                 ldr     ip, [ip, #TSK_FLAGS]    @ check for syscall tracing
115                 adr     tbl, SYMBOL_NAME(sys_call_table)
116                 tst     ip, #PF_TRACESYS
117                 ldreq   pc, [tbl, scno, lsl #2] @ call sys routine
119                 ldr     tip, [sp, #S_IP + S_OFF]        @ save old IP
120                 mov     ip, #0
121                 str     ip, [sp, #S_IP + S_OFF] @ trace entry [IP = 0]
122                 bl      SYMBOL_NAME(syscall_trace)
123                 str     tip, [sp, #S_IP + S_OFF]
125                 add     ip, sp, #S_OFF
126                 ldmia   ip, {r0 - r3}           @ have to reload r0 - r3
127                 mov     lr, pc
128                 ldr     pc, [tbl, scno, lsl #2] @ call sys routine
129                 str     r0, [sp, #S_R0 + S_OFF] @ returned r0
131                 mov     ip, #1
132                 str     ip, [sp, #S_IP + S_OFF] @ trace exit [IP = 1]
133                 bl      SYMBOL_NAME(syscall_trace)
134                 str     tip, [sp, #S_IP + S_OFF]
135                 b       slow_syscall_return
137 2:              add     r1, sp, #S_OFF
138                 tst     scno, #0x00f00000       @ is it a Unix SWI?
139                 bne     3f
140                 subs    r0, scno, #(KSWI_SYS_BASE - KSWI_BASE)
141                 bcs     SYMBOL_NAME(arm_syscall)
142                 b       SYMBOL_NAME(sys_ni_syscall) @ not private func
144 3:              eor     r0, scno, #OS_NUMBER <<20       @ Put OS number back
145                 adrsvc  al, lr, slow_syscall_return
146                 b       SYMBOL_NAME(deferred)
148                 .align  5
150 bh_data:        .word   SYMBOL_NAME(bh_mask)
151                 .word   SYMBOL_NAME(bh_active)
153 ENTRY(sys_call_table)
154 #include "calls.S"
156 /*============================================================================
157  * Special system call wrappers
158  */
159 @ r0 = syscall number
160 @ r5 = syscall table
161 SYMBOL_NAME(sys_syscall):
162                 eor     scno, r0, #OS_NUMBER << 20
163                 cmp     scno, #NR_syscalls      @ check range
164                 add     ip, sp, #S_OFF
165                 ldmleib ip, {r0 - r3, SYSCALL_REGS}     @ get our args
166                 stmleia sp, {SYSCALL_REGS}      @ Put our arg on the stack
167                 ldrle   pc, [tbl, scno, lsl #2]
168                 mov     r0, #-ENOSYS
169                 RETINSTR(mov,pc,lr)
171 sys_fork_wrapper:
172                 add     r0, sp, #S_OFF
173                 b       SYMBOL_NAME(sys_fork)
175 sys_vfork_wrapper:
176                 add     r0, sp, #S_OFF
177                 b       SYMBOL_NAME(sys_vfork)
179 sys_execve_wrapper:
180                 add     r3, sp, #S_OFF
181                 b       SYMBOL_NAME(sys_execve)
183 sys_clone_wapper:
184                 add     r2, sp, #S_OFF
185                 b       SYMBOL_NAME(sys_clone)
187 sys_sigsuspend_wrapper:
188                 add     r3, sp, #S_OFF
189                 b       SYMBOL_NAME(sys_sigsuspend)
191 sys_rt_sigsuspend_wrapper:
192                 add     r2, sp, #S_OFF
193                 b       SYMBOL_NAME(sys_rt_sigsuspend)
195 sys_sigreturn_wrapper:
196                 add     r0, sp, #S_OFF
197                 b       SYMBOL_NAME(sys_sigreturn)
199 sys_rt_sigreturn_wrapper:
200                 add     r0, sp, #S_OFF
201                 b       SYMBOL_NAME(sys_rt_sigreturn)
203 sys_sigaltstack_wrapper:
204                 ldr     r2, [sp, #S_OFF + S_SP]
205                 b       do_sigaltstack
207                 .data
209 ENTRY(fp_enter)
210                 .word   fpe_not_present