blob: 8f79a4789ed48d0a513f16f107eca73726b26e59 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/arm/kernel/entry-common.S
3 *
4 * Copyright (C) 2000 Russell King
5 *
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.
9 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <asm/unistd.h>
Dan Williamsf80dff92007-02-16 22:16:32 +010012#include <asm/arch/entry-macro.S>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013
14#include "entry-header.S"
15
Linus Torvalds1da177e2005-04-16 15:20:36 -070016
17 .align 5
18/*
19 * This is the fast syscall return path. We do as little as
20 * possible here, and this includes saving r0 back into the SVC
21 * stack.
22 */
23ret_fast_syscall:
Russell King1ec42c02005-04-26 15:18:26 +010024 disable_irq @ disable interrupts
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 ldr r1, [tsk, #TI_FLAGS]
26 tst r1, #_TIF_WORK_MASK
27 bne fast_work_pending
Russell Kingf4dc9a42005-04-26 15:20:34 +010028
Dan Williamsf80dff92007-02-16 22:16:32 +010029 /* perform architecture specific actions before user return */
30 arch_ret_to_user r1, lr
31
Russell Kingf4dc9a42005-04-26 15:20:34 +010032 @ fast_restore_user_regs
33 ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
34 ldr lr, [sp, #S_OFF + S_PC]! @ get pc
35 msr spsr_cxsf, r1 @ save in spsr_svc
36 ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
37 mov r0, r0
38 add sp, sp, #S_FRAME_SIZE - S_PC
39 movs pc, lr @ return & move spsr_svc into cpsr
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41/*
42 * Ok, we need to do extra processing, enter the slow path.
43 */
44fast_work_pending:
45 str r0, [sp, #S_R0+S_OFF]! @ returned r0
46work_pending:
47 tst r1, #_TIF_NEED_RESCHED
48 bne work_resched
Stephane Eraniana583f1b2007-07-31 00:38:00 -070049 tst r1, #_TIF_SIGPENDING
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 beq no_work_pending
51 mov r0, sp @ 'regs'
52 mov r2, why @ 'syscall'
53 bl do_notify_resume
Daniel Jacobowitza6c61e92005-11-19 10:01:07 +000054 b ret_slow_syscall @ Check work again
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56work_resched:
57 bl schedule
58/*
59 * "slow" syscall return path. "why" tells us if this was a real syscall.
60 */
61ENTRY(ret_to_user)
62ret_slow_syscall:
Russell King1ec42c02005-04-26 15:18:26 +010063 disable_irq @ disable interrupts
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 ldr r1, [tsk, #TI_FLAGS]
65 tst r1, #_TIF_WORK_MASK
66 bne work_pending
67no_work_pending:
Dan Williamsf80dff92007-02-16 22:16:32 +010068 /* perform architecture specific actions before user return */
69 arch_ret_to_user r1, lr
70
Russell Kingf4dc9a42005-04-26 15:20:34 +010071 @ slow_restore_user_regs
72 ldr r1, [sp, #S_PSR] @ get calling cpsr
73 ldr lr, [sp, #S_PC]! @ get pc
74 msr spsr_cxsf, r1 @ save in spsr_svc
George G. Davis7b544c92007-12-01 05:49:41 +010075 ldmdb sp, {r0 - lr}^ @ get calling r0 - lr
Russell Kingf4dc9a42005-04-26 15:20:34 +010076 mov r0, r0
77 add sp, sp, #S_FRAME_SIZE - S_PC
78 movs pc, lr @ return & move spsr_svc into cpsr
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80/*
81 * This is how we return from a fork.
82 */
83ENTRY(ret_from_fork)
84 bl schedule_tail
85 get_thread_info tsk
86 ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing
87 mov why, #1
88 tst r1, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
89 beq ret_slow_syscall
90 mov r1, sp
91 mov r0, #1 @ trace exit [IP = 1]
92 bl syscall_trace
93 b ret_slow_syscall
94
95
Al Virofa1b4f92006-01-19 12:57:01 +000096 .equ NR_syscalls,0
97#define CALL(x) .equ NR_syscalls,NR_syscalls+1
Linus Torvalds1da177e2005-04-16 15:20:36 -070098#include "calls.S"
Al Virofa1b4f92006-01-19 12:57:01 +000099#undef CALL
100#define CALL(x) .long x
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Abhishek Sagar014c2572008-05-31 14:23:50 +0530102#ifdef CONFIG_FTRACE
103#ifdef CONFIG_DYNAMIC_FTRACE
104ENTRY(mcount)
105 stmdb sp!, {r0-r3, lr}
106 mov r0, lr
107
108 .globl mcount_call
109mcount_call:
110 bl ftrace_stub
111 ldmia sp!, {r0-r3, pc}
112
113ENTRY(ftrace_caller)
114 stmdb sp!, {r0-r3, lr}
115 ldr r1, [fp, #-4]
116 mov r0, lr
117
118 .globl ftrace_call
119ftrace_call:
120 bl ftrace_stub
121 ldmia sp!, {r0-r3, pc}
122
123#else
124
125ENTRY(mcount)
126 stmdb sp!, {r0-r3, lr}
127 ldr r0, =ftrace_trace_function
128 ldr r2, [r0]
129 adr r0, ftrace_stub
130 cmp r0, r2
131 bne trace
132 ldmia sp!, {r0-r3, pc}
133
134trace:
135 ldr r1, [fp, #-4]
136 mov r0, lr
137 mov lr, pc
138 mov pc, r2
139 ldmia sp!, {r0-r3, pc}
140
141#endif /* CONFIG_DYNAMIC_FTRACE */
142
143 .globl ftrace_stub
144ftrace_stub:
145 mov pc, lr
146
147#endif /* CONFIG_FTRACE */
148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149/*=============================================================================
150 * SWI handler
151 *-----------------------------------------------------------------------------
152 */
153
154 /* If we're optimising for StrongARM the resulting code won't
155 run on an ARM7 and we can save a couple of instructions.
156 --pb */
157#ifdef CONFIG_CPU_ARM710
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000158#define A710(code...) code
159.Larm710bug:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
161 mov r0, r0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 add sp, sp, #S_FRAME_SIZE
Nicolas Pitre60ac1332005-10-12 19:51:24 +0100163 subs pc, lr, #4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164#else
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000165#define A710(code...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166#endif
167
168 .align 5
169ENTRY(vector_swi)
Russell Kingf4dc9a42005-04-26 15:20:34 +0100170 sub sp, sp, #S_FRAME_SIZE
171 stmia sp, {r0 - r12} @ Calling r0 - r12
172 add r8, sp, #S_PC
173 stmdb r8, {sp, lr}^ @ Calling sp, lr
174 mrs r8, spsr @ called from non-FIQ mode, so ok.
175 str lr, [sp, #S_PC] @ Save calling PC
176 str r8, [sp, #S_PSR] @ Save CPSR
177 str r0, [sp, #S_OLD_R0] @ Save OLD_R0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 zero_fp
Russell Kinge0f9f4a2005-04-26 15:19:24 +0100179
180 /*
181 * Get the system call number.
182 */
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000183
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000184#if defined(CONFIG_OABI_COMPAT)
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000185
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000186 /*
187 * If we have CONFIG_OABI_COMPAT then we need to look at the swi
188 * value to determine if it is an EABI or an old ABI call.
189 */
190#ifdef CONFIG_ARM_THUMB
191 tst r8, #PSR_T_BIT
192 movne r10, #0 @ no thumb OABI emulation
193 ldreq r10, [lr, #-4] @ get SWI instruction
194#else
195 ldr r10, [lr, #-4] @ get SWI instruction
196 A710( and ip, r10, #0x0f000000 @ check for SWI )
197 A710( teq ip, #0x0f000000 )
198 A710( bne .Larm710bug )
199#endif
200
201#elif defined(CONFIG_AEABI)
202
203 /*
204 * Pure EABI user space always put syscall number into scno (r7).
205 */
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000206 A710( ldr ip, [lr, #-4] @ get SWI instruction )
207 A710( and ip, ip, #0x0f000000 @ check for SWI )
208 A710( teq ip, #0x0f000000 )
209 A710( bne .Larm710bug )
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000210
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000211#elif defined(CONFIG_ARM_THUMB)
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000212
213 /* Legacy ABI only, possibly thumb mode. */
Russell Kinge0f9f4a2005-04-26 15:19:24 +0100214 tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
215 addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
216 ldreq scno, [lr, #-4]
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000217
Russell Kinge0f9f4a2005-04-26 15:19:24 +0100218#else
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000219
220 /* Legacy ABI only. */
Russell Kinge0f9f4a2005-04-26 15:19:24 +0100221 ldr scno, [lr, #-4] @ get SWI instruction
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000222 A710( and ip, scno, #0x0f000000 @ check for SWI )
223 A710( teq ip, #0x0f000000 )
224 A710( bne .Larm710bug )
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000225
Russell Kinge0f9f4a2005-04-26 15:19:24 +0100226#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
228#ifdef CONFIG_ALIGNMENT_TRAP
229 ldr ip, __cr_alignment
230 ldr ip, [ip]
231 mcr p15, 0, ip, c1, c0 @ update control register
232#endif
Russell King1ec42c02005-04-26 15:18:26 +0100233 enable_irq
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 get_thread_info tsk
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000236 adr tbl, sys_call_table @ load syscall table pointer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000238
239#if defined(CONFIG_OABI_COMPAT)
240 /*
241 * If the swi argument is zero, this is an EABI call and we do nothing.
242 *
243 * If this is an old ABI call, get the syscall number into scno and
244 * get the old ABI syscall table address.
245 */
246 bics r10, r10, #0xff000000
247 eorne scno, r10, #__NR_OABI_SYSCALL_BASE
248 ldrne tbl, =sys_oabi_call_table
249#elif !defined(CONFIG_AEABI)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 bic scno, scno, #0xff000000 @ mask off SWI op-code
Russell Kinge0f9f4a2005-04-26 15:19:24 +0100251 eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000252#endif
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000253
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000254 stmdb sp!, {r4, r5} @ push fifth and sixth args
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
256 bne __sys_trace
257
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 cmp scno, #NR_syscalls @ check upper syscall limit
Nicolas Pitre3f2829a2006-01-14 16:31:29 +0000259 adr lr, ret_fast_syscall @ return address
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
261
262 add r1, sp, #S_OFF
2632: mov why, #0 @ no longer a real syscall
Russell Kinge0f9f4a2005-04-26 15:19:24 +0100264 cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
265 eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 bcs arm_syscall
267 b sys_ni_syscall @ not private func
268
269 /*
270 * This is the really slow path. We're going to be doing
271 * context switches, and waiting for our parent to respond.
272 */
273__sys_trace:
Nicolas Pitre3f471122006-01-14 19:30:04 +0000274 mov r2, scno
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 add r1, sp, #S_OFF
276 mov r0, #0 @ trace entry [IP = 0]
277 bl syscall_trace
278
279 adr lr, __sys_trace_return @ return address
Nicolas Pitre3f471122006-01-14 19:30:04 +0000280 mov scno, r0 @ syscall number (possibly new)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 add r1, sp, #S_R0 + S_OFF @ pointer to regs
282 cmp scno, #NR_syscalls @ check upper syscall limit
283 ldmccia r1, {r0 - r3} @ have to reload r0 - r3
284 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
285 b 2b
286
287__sys_trace_return:
288 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
Nicolas Pitre3f471122006-01-14 19:30:04 +0000289 mov r2, scno
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 mov r1, sp
291 mov r0, #1 @ trace exit [IP = 1]
292 bl syscall_trace
293 b ret_slow_syscall
294
295 .align 5
296#ifdef CONFIG_ALIGNMENT_TRAP
297 .type __cr_alignment, #object
298__cr_alignment:
299 .word cr_alignment
300#endif
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000301 .ltorg
302
303/*
304 * This is the syscall table declaration for native ABI syscalls.
305 * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
306 */
307#define ABI(native, compat) native
308#ifdef CONFIG_AEABI
309#define OBSOLETE(syscall) sys_ni_syscall
310#else
311#define OBSOLETE(syscall) syscall
312#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
314 .type sys_call_table, #object
315ENTRY(sys_call_table)
316#include "calls.S"
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000317#undef ABI
318#undef OBSOLETE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320/*============================================================================
321 * Special system call wrappers
322 */
323@ r0 = syscall number
Russell King567bd982005-12-17 15:25:42 +0000324@ r8 = syscall table
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 .type sys_syscall, #function
326sys_syscall:
Paul Brook52475932006-05-16 14:25:55 +0100327 bic scno, r0, #__NR_OABI_SYSCALL_BASE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
329 cmpne scno, #NR_syscalls @ check range
330 stmloia sp, {r5, r6} @ shuffle args
331 movlo r0, r1
332 movlo r1, r2
333 movlo r2, r3
334 movlo r3, r4
335 ldrlo pc, [tbl, scno, lsl #2]
336 b sys_ni_syscall
337
338sys_fork_wrapper:
339 add r0, sp, #S_OFF
340 b sys_fork
341
342sys_vfork_wrapper:
343 add r0, sp, #S_OFF
344 b sys_vfork
345
346sys_execve_wrapper:
347 add r3, sp, #S_OFF
348 b sys_execve
349
350sys_clone_wrapper:
351 add ip, sp, #S_OFF
352 str ip, [sp, #4]
353 b sys_clone
354
355sys_sigsuspend_wrapper:
356 add r3, sp, #S_OFF
357 b sys_sigsuspend
358
359sys_rt_sigsuspend_wrapper:
360 add r2, sp, #S_OFF
361 b sys_rt_sigsuspend
362
363sys_sigreturn_wrapper:
364 add r0, sp, #S_OFF
365 b sys_sigreturn
366
367sys_rt_sigreturn_wrapper:
368 add r0, sp, #S_OFF
369 b sys_rt_sigreturn
370
371sys_sigaltstack_wrapper:
372 ldr r2, [sp, #S_OFF + S_SP]
373 b do_sigaltstack
374
Nicolas Pitre713c4812006-01-14 16:35:03 +0000375sys_statfs64_wrapper:
376 teq r1, #88
377 moveq r1, #84
378 b sys_statfs64
379
380sys_fstatfs64_wrapper:
381 teq r1, #88
382 moveq r1, #84
383 b sys_fstatfs64
384
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385/*
386 * Note: off_4k (r5) is always units of 4K. If we can't do the requested
387 * offset, we return EINVAL.
388 */
389sys_mmap2:
390#if PAGE_SHIFT > 12
391 tst r5, #PGOFF_MASK
392 moveq r5, r5, lsr #PAGE_SHIFT - 12
393 streq r5, [sp, #4]
394 beq do_mmap2
395 mov r0, #-EINVAL
Russell King7999d8d2006-06-25 11:17:23 +0100396 mov pc, lr
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397#else
398 str r5, [sp, #4]
399 b do_mmap2
400#endif
Nicolas Pitre687ad012006-01-14 16:35:31 +0000401
Paul Brook48d79272008-04-18 22:43:07 +0100402ENTRY(pabort_ifar)
403 mrc p15, 0, r0, cr6, cr0, 2
404ENTRY(pabort_noifar)
405 mov pc, lr
406
Nicolas Pitre687ad012006-01-14 16:35:31 +0000407#ifdef CONFIG_OABI_COMPAT
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000408
Nicolas Pitre687ad012006-01-14 16:35:31 +0000409/*
410 * These are syscalls with argument register differences
411 */
412
413sys_oabi_pread64:
414 stmia sp, {r3, r4}
415 b sys_pread64
416
417sys_oabi_pwrite64:
418 stmia sp, {r3, r4}
419 b sys_pwrite64
420
421sys_oabi_truncate64:
422 mov r3, r2
423 mov r2, r1
424 b sys_truncate64
425
426sys_oabi_ftruncate64:
427 mov r3, r2
428 mov r2, r1
429 b sys_ftruncate64
430
431sys_oabi_readahead:
432 str r3, [sp]
433 mov r3, r2
434 mov r2, r1
435 b sys_readahead
436
Nicolas Pitredd35afc2006-01-14 16:36:12 +0000437/*
438 * Let's declare a second syscall table for old ABI binaries
439 * using the compatibility syscall entries.
440 */
441#define ABI(native, compat) compat
442#define OBSOLETE(syscall) syscall
443
444 .type sys_oabi_call_table, #object
445ENTRY(sys_oabi_call_table)
446#include "calls.S"
447#undef ABI
448#undef OBSOLETE
449
Nicolas Pitre687ad012006-01-14 16:35:31 +0000450#endif
451