81dda5819c7d84eabc530e3919a024013940f9b6
[h-e-n] / arch / arm / kernel / entry-common.S
1 /*
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  */
10
11 #include <asm/unistd.h>
12 #include <asm/ftrace.h>
13 #include <mach/entry-macro.S>
14
15 #include "entry-header.S"
16
17
18         .align  5
19 /*
20  * This is the fast syscall return path.  We do as little as
21  * possible here, and this includes saving r0 back into the SVC
22  * stack.
23  */
24 ret_fast_syscall:
25         disable_irq                             @ disable interrupts
26         ldr     r1, [tsk, #TI_FLAGS]
27         tst     r1, #_TIF_WORK_MASK
28         bne     fast_work_pending
29
30         /* perform architecture specific actions before user return */
31         arch_ret_to_user r1, lr
32
33         @ fast_restore_user_regs
34         ldr     r1, [sp, #S_OFF + S_PSR]        @ get calling cpsr
35         ldr     lr, [sp, #S_OFF + S_PC]!        @ get pc
36         msr     spsr_cxsf, r1                   @ save in spsr_svc
37         ldmdb   sp, {r1 - lr}^                  @ get calling r1 - lr
38         mov     r0, r0
39         add     sp, sp, #S_FRAME_SIZE - S_PC
40         movs    pc, lr                          @ return & move spsr_svc into cpsr
41
42 /*
43  * Ok, we need to do extra processing, enter the slow path.
44  */
45 fast_work_pending:
46         str     r0, [sp, #S_R0+S_OFF]!          @ returned r0
47 work_pending:
48         tst     r1, #_TIF_NEED_RESCHED
49         bne     work_resched
50         tst     r1, #_TIF_SIGPENDING
51         beq     no_work_pending
52         mov     r0, sp                          @ 'regs'
53         mov     r2, why                         @ 'syscall'
54         bl      do_notify_resume
55         b       ret_slow_syscall                @ Check work again
56
57 work_resched:
58         bl      schedule
59 /*
60  * "slow" syscall return path.  "why" tells us if this was a real syscall.
61  */
62 ENTRY(ret_to_user)
63 ret_slow_syscall:
64         disable_irq                             @ disable interrupts
65         ldr     r1, [tsk, #TI_FLAGS]
66         tst     r1, #_TIF_WORK_MASK
67         bne     work_pending
68 no_work_pending:
69         /* perform architecture specific actions before user return */
70         arch_ret_to_user r1, lr
71
72         @ slow_restore_user_regs
73         ldr     r1, [sp, #S_PSR]                @ get calling cpsr
74         ldr     lr, [sp, #S_PC]!                @ get pc
75         msr     spsr_cxsf, r1                   @ save in spsr_svc
76         ldmdb   sp, {r0 - lr}^                  @ get calling r0 - lr
77         mov     r0, r0
78         add     sp, sp, #S_FRAME_SIZE - S_PC
79         movs    pc, lr                          @ return & move spsr_svc into cpsr
80 ENDPROC(ret_to_user)
81
82 /*
83  * This is how we return from a fork.
84  */
85 ENTRY(ret_from_fork)
86         bl      schedule_tail
87         get_thread_info tsk
88         ldr     r1, [tsk, #TI_FLAGS]            @ check for syscall tracing
89         mov     why, #1
90         tst     r1, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
91         beq     ret_slow_syscall
92         mov     r1, sp
93         mov     r0, #1                          @ trace exit [IP = 1]
94         bl      syscall_trace
95         b       ret_slow_syscall
96 ENDPROC(ret_from_fork)
97
98         .equ NR_syscalls,0
99 #define CALL(x) .equ NR_syscalls,NR_syscalls+1
100 #include "calls.S"
101 #undef CALL
102 #define CALL(x) .long x
103
104 #ifdef CONFIG_FUNCTION_TRACER
105 #ifdef CONFIG_DYNAMIC_FTRACE
106 ENTRY(mcount)
107         stmdb sp!, {r0-r3, lr}
108         mov r0, lr
109         sub r0, r0, #MCOUNT_INSN_SIZE
110
111         .globl mcount_call
112 mcount_call:
113         bl ftrace_stub
114         ldmia sp!, {r0-r3, pc}
115
116 ENTRY(ftrace_caller)
117         stmdb sp!, {r0-r3, lr}
118         ldr r1, [fp, #-4]
119         mov r0, lr
120         sub r0, r0, #MCOUNT_INSN_SIZE
121
122         .globl ftrace_call
123 ftrace_call:
124         bl ftrace_stub
125         ldmia sp!, {r0-r3, pc}
126
127 #else
128
129                                 
130 gnu_trace:
131         ldr r1, [sp, #20]                       @ lr of instrumented routine
132         mov r0, lr
133         sub r0, r0, #MCOUNT_INSN_SIZE
134         mov lr, pc
135         mov pc, r2
136         ldmia sp!, {r0-r3, ip, lr}
137         mov pc, ip
138                                 
139 ENTRY(mcount)
140         stmdb sp!, {r0-r3, lr}
141         ldr r0, =ftrace_trace_function
142         ldr r2, [r0]
143         adr r0, ftrace_stub
144         cmp r0, r2
145         bne trace
146         ldmia sp!, {r0-r3, pc}
147
148 ENTRY(__gnu_mcount_nc)
149         stmdb sp!, {r0-r3, lr}
150         ldr r0, =ftrace_trace_function
151         ldr r2, [r0]
152         adr r0, ftrace_stub
153         cmp r0, r2
154         bne gnu_trace
155         ldmia sp!, {r0-r3, ip, lr}
156         mov pc, ip
157
158 trace:
159         ldr r1, [fp, #-4]
160         mov r0, lr
161         sub r0, r0, #MCOUNT_INSN_SIZE
162         mov lr, pc
163         mov pc, r2
164         ldmia sp!, {r0-r3, pc}
165
166 #endif /* CONFIG_DYNAMIC_FTRACE */
167
168         .globl ftrace_stub
169 ftrace_stub:
170         mov pc, lr
171
172 #endif /* CONFIG_FUNCTION_TRACER */
173
174 /*=============================================================================
175  * SWI handler
176  *-----------------------------------------------------------------------------
177  */
178
179         /* If we're optimising for StrongARM the resulting code won't 
180            run on an ARM7 and we can save a couple of instructions.  
181                                                                 --pb */
182 #ifdef CONFIG_CPU_ARM710
183 #define A710(code...) code
184 .Larm710bug:
185         ldmia   sp, {r0 - lr}^                  @ Get calling r0 - lr
186         mov     r0, r0
187         add     sp, sp, #S_FRAME_SIZE
188         subs    pc, lr, #4
189 #else
190 #define A710(code...)
191 #endif
192
193         .align  5
194 ENTRY(vector_swi)
195         sub     sp, sp, #S_FRAME_SIZE
196         stmia   sp, {r0 - r12}                  @ Calling r0 - r12
197         add     r8, sp, #S_PC
198         stmdb   r8, {sp, lr}^                   @ Calling sp, lr
199         mrs     r8, spsr                        @ called from non-FIQ mode, so ok.
200         str     lr, [sp, #S_PC]                 @ Save calling PC
201         str     r8, [sp, #S_PSR]                @ Save CPSR
202         str     r0, [sp, #S_OLD_R0]             @ Save OLD_R0
203         zero_fp
204
205         /*
206          * Get the system call number.
207          */
208
209 #if defined(CONFIG_OABI_COMPAT)
210
211         /*
212          * If we have CONFIG_OABI_COMPAT then we need to look at the swi
213          * value to determine if it is an EABI or an old ABI call.
214          */
215 #ifdef CONFIG_ARM_THUMB
216         tst     r8, #PSR_T_BIT
217         movne   r10, #0                         @ no thumb OABI emulation
218         ldreq   r10, [lr, #-4]                  @ get SWI instruction
219 #else
220         ldr     r10, [lr, #-4]                  @ get SWI instruction
221   A710( and     ip, r10, #0x0f000000            @ check for SWI         )
222   A710( teq     ip, #0x0f000000                                         )
223   A710( bne     .Larm710bug                                             )
224 #endif
225
226 #elif defined(CONFIG_AEABI)
227
228         /*
229          * Pure EABI user space always put syscall number into scno (r7).
230          */
231   A710( ldr     ip, [lr, #-4]                   @ get SWI instruction   )
232   A710( and     ip, ip, #0x0f000000             @ check for SWI         )
233   A710( teq     ip, #0x0f000000                                         )
234   A710( bne     .Larm710bug                                             )
235
236 #elif defined(CONFIG_ARM_THUMB)
237
238         /* Legacy ABI only, possibly thumb mode. */
239         tst     r8, #PSR_T_BIT                  @ this is SPSR from save_user_regs
240         addne   scno, r7, #__NR_SYSCALL_BASE    @ put OS number in
241         ldreq   scno, [lr, #-4]
242
243 #else
244
245         /* Legacy ABI only. */
246         ldr     scno, [lr, #-4]                 @ get SWI instruction
247   A710( and     ip, scno, #0x0f000000           @ check for SWI         )
248   A710( teq     ip, #0x0f000000                                         )
249   A710( bne     .Larm710bug                                             )
250
251 #endif
252
253 #ifdef CONFIG_ALIGNMENT_TRAP
254         ldr     ip, __cr_alignment
255         ldr     ip, [ip]
256         mcr     p15, 0, ip, c1, c0              @ update control register
257 #endif
258         enable_irq
259
260         get_thread_info tsk
261         adr     tbl, sys_call_table             @ load syscall table pointer
262         ldr     ip, [tsk, #TI_FLAGS]            @ check for syscall tracing
263
264 #if defined(CONFIG_OABI_COMPAT)
265         /*
266          * If the swi argument is zero, this is an EABI call and we do nothing.
267          *
268          * If this is an old ABI call, get the syscall number into scno and
269          * get the old ABI syscall table address.
270          */
271         bics    r10, r10, #0xff000000
272         eorne   scno, r10, #__NR_OABI_SYSCALL_BASE
273         ldrne   tbl, =sys_oabi_call_table
274 #elif !defined(CONFIG_AEABI)
275         bic     scno, scno, #0xff000000         @ mask off SWI op-code
276         eor     scno, scno, #__NR_SYSCALL_BASE  @ check OS number
277 #endif
278
279         stmdb   sp!, {r4, r5}                   @ push fifth and sixth args
280         tst     ip, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
281         bne     __sys_trace
282
283         cmp     scno, #NR_syscalls              @ check upper syscall limit
284         adr     lr, ret_fast_syscall            @ return address
285         ldrcc   pc, [tbl, scno, lsl #2]         @ call sys_* routine
286
287         add     r1, sp, #S_OFF
288 2:      mov     why, #0                         @ no longer a real syscall
289         cmp     scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
290         eor     r0, scno, #__NR_SYSCALL_BASE    @ put OS number back
291         bcs     arm_syscall     
292         b       sys_ni_syscall                  @ not private func
293 ENDPROC(vector_swi)
294
295         /*
296          * This is the really slow path.  We're going to be doing
297          * context switches, and waiting for our parent to respond.
298          */
299 __sys_trace:
300         mov     r2, scno
301         add     r1, sp, #S_OFF
302         mov     r0, #0                          @ trace entry [IP = 0]
303         bl      syscall_trace
304
305         adr     lr, __sys_trace_return          @ return address
306         mov     scno, r0                        @ syscall number (possibly new)
307         add     r1, sp, #S_R0 + S_OFF           @ pointer to regs
308         cmp     scno, #NR_syscalls              @ check upper syscall limit
309         ldmccia r1, {r0 - r3}                   @ have to reload r0 - r3
310         ldrcc   pc, [tbl, scno, lsl #2]         @ call sys_* routine
311         b       2b
312
313 __sys_trace_return:
314         str     r0, [sp, #S_R0 + S_OFF]!        @ save returned r0
315         mov     r2, scno
316         mov     r1, sp
317         mov     r0, #1                          @ trace exit [IP = 1]
318         bl      syscall_trace
319         b       ret_slow_syscall
320
321         .align  5
322 #ifdef CONFIG_ALIGNMENT_TRAP
323         .type   __cr_alignment, #object
324 __cr_alignment:
325         .word   cr_alignment
326 #endif
327         .ltorg
328
329 /*
330  * This is the syscall table declaration for native ABI syscalls.
331  * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
332  */
333 #define ABI(native, compat) native
334 #ifdef CONFIG_AEABI
335 #define OBSOLETE(syscall) sys_ni_syscall
336 #else
337 #define OBSOLETE(syscall) syscall
338 #endif
339
340         .type   sys_call_table, #object
341 ENTRY(sys_call_table)
342 #include "calls.S"
343 #undef ABI
344 #undef OBSOLETE
345
346 /*============================================================================
347  * Special system call wrappers
348  */
349 @ r0 = syscall number
350 @ r8 = syscall table
351 sys_syscall:
352                 bic     scno, r0, #__NR_OABI_SYSCALL_BASE
353                 cmp     scno, #__NR_syscall - __NR_SYSCALL_BASE
354                 cmpne   scno, #NR_syscalls      @ check range
355                 stmloia sp, {r5, r6}            @ shuffle args
356                 movlo   r0, r1
357                 movlo   r1, r2
358                 movlo   r2, r3
359                 movlo   r3, r4
360                 ldrlo   pc, [tbl, scno, lsl #2]
361                 b       sys_ni_syscall
362 ENDPROC(sys_syscall)
363
364 sys_fork_wrapper:
365                 add     r0, sp, #S_OFF
366                 b       sys_fork
367 ENDPROC(sys_fork_wrapper)
368
369 sys_vfork_wrapper:
370                 add     r0, sp, #S_OFF
371                 b       sys_vfork
372 ENDPROC(sys_vfork_wrapper)
373
374 sys_execve_wrapper:
375                 add     r3, sp, #S_OFF
376                 b       sys_execve
377 ENDPROC(sys_execve_wrapper)
378
379 sys_clone_wrapper:
380                 add     ip, sp, #S_OFF
381                 str     ip, [sp, #4]
382                 b       sys_clone
383 ENDPROC(sys_clone_wrapper)
384
385 sys_sigsuspend_wrapper:
386                 add     r3, sp, #S_OFF
387                 b       sys_sigsuspend
388 ENDPROC(sys_sigsuspend_wrapper)
389
390 sys_rt_sigsuspend_wrapper:
391                 add     r2, sp, #S_OFF
392                 b       sys_rt_sigsuspend
393 ENDPROC(sys_rt_sigsuspend_wrapper)
394
395 sys_sigreturn_wrapper:
396                 add     r0, sp, #S_OFF
397                 b       sys_sigreturn
398 ENDPROC(sys_sigreturn_wrapper)
399
400 sys_rt_sigreturn_wrapper:
401                 add     r0, sp, #S_OFF
402                 b       sys_rt_sigreturn
403 ENDPROC(sys_rt_sigreturn_wrapper)
404
405 sys_sigaltstack_wrapper:
406                 ldr     r2, [sp, #S_OFF + S_SP]
407                 b       do_sigaltstack
408 ENDPROC(sys_sigaltstack_wrapper)
409
410 sys_statfs64_wrapper:
411                 teq     r1, #88
412                 moveq   r1, #84
413                 b       sys_statfs64
414 ENDPROC(sys_statfs64_wrapper)
415
416 sys_fstatfs64_wrapper:
417                 teq     r1, #88
418                 moveq   r1, #84
419                 b       sys_fstatfs64
420 ENDPROC(sys_fstatfs64_wrapper)
421
422 /*
423  * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
424  * offset, we return EINVAL.
425  */
426 sys_mmap2:
427 #if PAGE_SHIFT > 12
428                 tst     r5, #PGOFF_MASK
429                 moveq   r5, r5, lsr #PAGE_SHIFT - 12
430                 streq   r5, [sp, #4]
431                 beq     do_mmap2
432                 mov     r0, #-EINVAL
433                 mov     pc, lr
434 #else
435                 str     r5, [sp, #4]
436                 b       do_mmap2
437 #endif
438 ENDPROC(sys_mmap2)
439
440 ENTRY(pabort_ifar)
441                 mrc     p15, 0, r0, cr6, cr0, 2
442 ENTRY(pabort_noifar)
443                 mov     pc, lr
444 ENDPROC(pabort_ifar)
445 ENDPROC(pabort_noifar)
446
447 #ifdef CONFIG_OABI_COMPAT
448
449 /*
450  * These are syscalls with argument register differences
451  */
452
453 sys_oabi_pread64:
454                 stmia   sp, {r3, r4}
455                 b       sys_pread64
456 ENDPROC(sys_oabi_pread64)
457
458 sys_oabi_pwrite64:
459                 stmia   sp, {r3, r4}
460                 b       sys_pwrite64
461 ENDPROC(sys_oabi_pwrite64)
462
463 sys_oabi_truncate64:
464                 mov     r3, r2
465                 mov     r2, r1
466                 b       sys_truncate64
467 ENDPROC(sys_oabi_truncate64)
468
469 sys_oabi_ftruncate64:
470                 mov     r3, r2
471                 mov     r2, r1
472                 b       sys_ftruncate64
473 ENDPROC(sys_oabi_ftruncate64)
474
475 sys_oabi_readahead:
476                 str     r3, [sp]
477                 mov     r3, r2
478                 mov     r2, r1
479                 b       sys_readahead
480 ENDPROC(sys_oabi_readahead)
481
482 /*
483  * Let's declare a second syscall table for old ABI binaries
484  * using the compatibility syscall entries.
485  */
486 #define ABI(native, compat) compat
487 #define OBSOLETE(syscall) syscall
488
489         .type   sys_oabi_call_table, #object
490 ENTRY(sys_oabi_call_table)
491 #include "calls.S"
492 #undef ABI
493 #undef OBSOLETE
494
495 #endif
496