1 #include <linux/config.h>
2 /*============================================================================
3 * All exits to user mode from the kernel go through this code.
7 #define SYSCALL_REGS r4, r5
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.
14 #if defined(CONFIG_CPU_SA110)
18 .globl ret_from_sys_call
22 str r0, [sp, #S_R0 + S_OFF] @ returned r0
36 blne SYMBOL_NAME(do_bottom_half)
39 ldr r0, [r5, #TSK_NEED_RESCHED]
40 ldr r1, [r5, #TSK_SIGPENDING]
43 teq r1, #0 @ check for signals
46 ret_from_all: restore_user_regs
48 ret_signal: mov r1, sp
49 adrsvc al, lr, ret_from_all
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
69 blne SYMBOL_NAME(do_bottom_half)
71 tst r0, #3 @ returning to user mode?
72 beq ret_with_reschedule
77 /*=============================================================================
79 *-----------------------------------------------------------------------------
83 * Create some aliases for some registers. These should allow
84 * us to have in theory up to 7 arguments to a function.
86 scno .req r9 @ syscall number
87 tbl .req r8 @ syscall table pointer
88 tip .req r7 @ temporary IP
91 vector_swi: save_user_regs
94 ldr scno, [lr, #-4] @ get SWI instruction
95 arm700_bug_check scno, ip
96 #ifdef CONFIG_ALIGNMENT_TRAP
99 mcr p15, 0, ip, c1, c0
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
114 ldr ip, [ip, #TSK_FLAGS] @ check for syscall tracing
115 adr tbl, SYMBOL_NAME(sys_call_table)
117 ldreq pc, [tbl, scno, lsl #2] @ call sys routine
119 ldr tip, [sp, #S_IP + S_OFF] @ save old IP
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]
126 ldmia ip, {r0 - r3} @ have to reload r0 - r3
128 ldr pc, [tbl, scno, lsl #2] @ call sys routine
129 str r0, [sp, #S_R0 + S_OFF] @ returned r0
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?
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)
150 bh_data: .word SYMBOL_NAME(bh_mask)
151 .word SYMBOL_NAME(bh_active)
153 ENTRY(sys_call_table)
156 /*============================================================================
157 * Special system call wrappers
159 @ r0 = syscall number
161 SYMBOL_NAME(sys_syscall):
162 eor scno, r0, #OS_NUMBER << 20
163 cmp scno, #NR_syscalls @ check range
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]
173 b SYMBOL_NAME(sys_fork)
177 b SYMBOL_NAME(sys_vfork)
181 b SYMBOL_NAME(sys_execve)
185 b SYMBOL_NAME(sys_clone)
187 sys_sigsuspend_wrapper:
189 b SYMBOL_NAME(sys_sigsuspend)
191 sys_rt_sigsuspend_wrapper:
193 b SYMBOL_NAME(sys_rt_sigsuspend)
195 sys_sigreturn_wrapper:
197 b SYMBOL_NAME(sys_sigreturn)
199 sys_rt_sigreturn_wrapper:
201 b SYMBOL_NAME(sys_rt_sigreturn)
203 sys_sigaltstack_wrapper:
204 ldr r2, [sp, #S_OFF + S_SP]
210 .word fpe_not_present