2 * linux/arch/arm/kernel/entry-common.S
4 * Copyright (C) 2000 Russell King
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 #include <linux/config.h>
11 #include "entry-header.S"
14 * We rely on the fact that R0 is at the bottom of the stack (due to
15 * slow/fast restore user regs).
22 * Our do_softirq out of line code. See include/asm-arm/softirq.h for
23 * the calling assembly.
26 stmfd sp!, {r0 - r3, ip, lr}
28 ldmfd sp!, {r0 - r3, ip, pc}
32 * This is the fast syscall return path. We do as little as
33 * possible here, and this includes saving r0 back into the SVC
37 disable_irq r1 @ ensure IRQs are disabled
38 ldr r1, [tsk, #TSK_NEED_RESCHED]
39 ldr r2, [tsk, #TSK_SIGPENDING]
40 teq r1, #0 @ need_resched || sigpending
43 fast_restore_user_regs
46 * Ok, we need to do extra processing, enter the slow path.
48 slow: str r0, [sp, #S_R0+S_OFF]! @ returned r0
53 * "slow" syscall return path. "why" tells us if this was a real syscall.
56 bl SYMBOL_NAME(schedule)
58 disable_irq r1 @ ensure IRQs are disabled
61 ldr r1, [tsk, #TSK_NEED_RESCHED]
62 ldr r2, [tsk, #TSK_SIGPENDING]
63 teq r1, #0 @ need_resched => schedule()
65 1: teq r2, #0 @ sigpending => do_signal()
72 mov r0, #0 @ NULL 'oldset'
74 mov r2, why @ 'syscall'
75 bl SYMBOL_NAME(do_signal) @ note the bl above sets lr
76 disable_irq r1 @ ensure IRQs are disabled
80 * This is how we return from a fork. __switch_to will be calling us
81 * with r0 pointing at the previous task that was running (ready for
82 * calling schedule_tail).
85 bl SYMBOL_NAME(schedule_tail)
87 ldr ip, [tsk, #TSK_PTRACE] @ check for syscall tracing
89 tst ip, #PT_TRACESYS @ are we tracing syscalls?
92 mov r0, #1 @ trace exit [IP = 1]
93 bl SYMBOL_NAME(syscall_trace)
99 /*=============================================================================
101 *-----------------------------------------------------------------------------
104 /* If we're optimising for StrongARM the resulting code won't
105 run on an ARM7 and we can save a couple of instructions.
107 #ifdef CONFIG_CPU_ARM710
108 .macro arm710_bug_check, instr, temp
109 and \temp, \instr, #0x0f000000 @ check for SWI
110 teq \temp, #0x0f000000
115 ldr r0, [sp, #S_PSR] @ Get calling cpsr
119 ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
121 ldr lr, [sp, #S_PC] @ Get PC
122 add sp, sp, #S_FRAME_SIZE
125 .macro arm710_bug_check, instr, temp
134 arm710_bug_check scno, ip
136 #ifdef CONFIG_ALIGNMENT_TRAP
137 ldr ip, __cr_alignment
139 mcr p15, 0, ip, c1, c0 @ update control register
143 str r4, [sp, #-S_OFF]! @ push fifth arg
146 ldr ip, [tsk, #TSK_PTRACE] @ check for syscall tracing
147 bic scno, scno, #0xff000000 @ mask off SWI op-code
148 eor scno, scno, #OS_NUMBER << 20 @ check OS number
149 adr tbl, sys_call_table @ load syscall table pointer
150 tst ip, #PT_TRACESYS @ are we tracing syscalls?
153 adrsvc al, lr, ret_fast_syscall @ return address
154 cmp scno, #NR_syscalls @ check upper syscall limit
155 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
158 2: mov why, #0 @ no longer a real syscall
159 cmp scno, #ARMSWI_OFFSET
160 eor r0, scno, #OS_NUMBER << 20 @ put OS number back
161 bcs SYMBOL_NAME(arm_syscall)
162 b SYMBOL_NAME(sys_ni_syscall) @ not private func
165 * This is the really slow path. We're going to be doing
166 * context switches, and waiting for our parent to respond.
170 mov r0, #0 @ trace entry [IP = 0]
171 bl SYMBOL_NAME(syscall_trace)
173 adrsvc al, lr, __sys_trace_return @ return address
174 add r1, sp, #S_R0 + S_OFF @ pointer to regs
175 cmp scno, #NR_syscalls @ check upper syscall limit
176 ldmccia r1, {r0 - r3} @ have to reload r0 - r3
177 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
181 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
183 mov r0, #1 @ trace exit [IP = 1]
184 bl SYMBOL_NAME(syscall_trace)
188 #ifdef CONFIG_ALIGNMENT_TRAP
189 .type __cr_alignment, #object
191 .word SYMBOL_NAME(cr_alignment)
194 .type sys_call_table, #object
195 ENTRY(sys_call_table)
198 /*============================================================================
199 * Special system call wrappers
201 @ r0 = syscall number
203 .type sys_syscall, #function
204 SYMBOL_NAME(sys_syscall):
205 eor scno, r0, #OS_NUMBER << 20
206 cmp scno, #NR_syscalls @ check range
207 stmleia sp, {r5, r6} @ shuffle args
212 ldrle pc, [tbl, scno, lsl #2]
217 b SYMBOL_NAME(sys_fork)
221 b SYMBOL_NAME(sys_vfork)
225 b SYMBOL_NAME(sys_execve)
229 b SYMBOL_NAME(sys_clone)
231 sys_sigsuspend_wrapper:
233 b SYMBOL_NAME(sys_sigsuspend)
235 sys_rt_sigsuspend_wrapper:
237 b SYMBOL_NAME(sys_rt_sigsuspend)
239 sys_sigreturn_wrapper:
241 b SYMBOL_NAME(sys_sigreturn)
243 sys_rt_sigreturn_wrapper:
245 b SYMBOL_NAME(sys_rt_sigreturn)
247 sys_sigaltstack_wrapper:
248 ldr r2, [sp, #S_OFF + S_SP]
252 * Note: off_4k (r5) is always units of 4K. If we can't do the requested
253 * offset, we return EINVAL.
258 moveq r5, r5, lsr #PAGE_SHIFT - 12