Import 2.3.49pre2
[davej-history.git] / arch / arm / kernel / entry-common.S
blob97dfef0c1339f318e6b5d9674e5b297af9e4b855
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
8                 .macro  get_softirq, rd
9 #ifdef __SMP__
10 #error SMP not supported
11 #else
12                 ldr     \rd, __softirq_state
13 #endif
14                 .endm
16                 .globl  ret_from_sys_call
18                 .align  5
19 fast_syscall_return:
20                 str     r0, [sp, #S_R0 + S_OFF] @ returned r0
21 slow_syscall_return:
22                 add     sp, sp, #S_OFF
23 ret_from_sys_call:                              @ external entry
24                 get_softirq r0
25                 ldmia   r0, {r0, r1}
26                 mov     r4, #1                  @ flag this as being syscall return
27                 tst     r0, r1
28                 blne    SYMBOL_NAME(do_softirq)
29 ret_with_reschedule:                            @ external entry (__irq_usr)
30                 get_current_task r5
31                 ldr     r0, [r5, #TSK_NEED_RESCHED]
32                 ldr     r1, [r5, #TSK_SIGPENDING]
33                 teq     r0, #0
34                 bne     ret_reschedule
35                 teq     r1, #0                  @ check for signals
36                 bne     ret_signal
38 ret_from_all:   restore_user_regs               @ internal
40 ret_signal:     mov     r1, sp                  @ internal
41                 adrsvc  al, lr, ret_from_all
42                 mov     r2, r4
43                 b       SYMBOL_NAME(do_signal)
45 ret_reschedule: adrsvc  al, lr, ret_with_reschedule     @ internal
46                 b       SYMBOL_NAME(schedule)
48                 .globl  ret_from_exception
49 ret_from_exception:                             @ external entry
50                 get_softirq r0
51                 ldmia   r0, {r0, r1}
52                 mov     r4, #0
53                 tst     r0, r1
54                 blne    SYMBOL_NAME(do_softirq)
55                 ldr     r0, [sp, #S_PSR]
56                 tst     r0, #3                  @ returning to user mode?
57                 beq     ret_with_reschedule
58                 b       ret_from_all
60 #include "calls.S"
62 /*=============================================================================
63  * SWI handler
64  *-----------------------------------------------------------------------------
65  */
68  * Create some aliases for some registers.  These should allow
69  * us to have in theory up to 7 arguments to a function.
70  */
71 scno            .req    r9                      @ syscall number
72 tbl             .req    r8                      @ syscall table pointer
73 tip             .req    r7                      @ temporary IP
75                 .align  5
76 vector_swi:     save_user_regs
77                 mask_pc lr, lr
78                 zero_fp
79                 ldr     scno, [lr, #-4]         @ get SWI instruction
80                 arm700_bug_check scno, ip
81 #ifdef CONFIG_ALIGNMENT_TRAP
82                 ldr     ip, .LCswi
83                 ldr     ip, [ip]
84                 mcr     p15, 0, ip, c1, c0
85 #endif
86                 enable_irqs ip
88                 str     r4, [sp, #-S_OFF]!      @ push fifth arg
89                 adrsvc  al, lr, fast_syscall_return
91                 bic     scno, scno, #0xff000000 @ mask off SWI op-code
92                 eor     scno, scno, #OS_NUMBER<<20      @ check OS number
93                 cmp     scno, #NR_syscalls      @ check upper syscall limit
94                 bcs     2f
96                 get_current_task ip
97                 ldr     ip, [ip, #TSK_FLAGS]    @ check for syscall tracing
98                 adr     tbl, SYMBOL_NAME(sys_call_table)
99                 tst     ip, #PF_TRACESYS
100                 ldreq   pc, [tbl, scno, lsl #2] @ call sys routine
102                 ldr     tip, [sp, #S_IP + S_OFF]        @ save old IP
103                 mov     ip, #0
104                 str     ip, [sp, #S_IP + S_OFF] @ trace entry [IP = 0]
105                 bl      SYMBOL_NAME(syscall_trace)
106                 str     tip, [sp, #S_IP + S_OFF]
108                 add     ip, sp, #S_OFF
109                 ldmia   ip, {r0 - r3}           @ have to reload r0 - r3
110                 mov     lr, pc
111                 ldr     pc, [tbl, scno, lsl #2] @ call sys routine
112                 str     r0, [sp, #S_R0 + S_OFF] @ returned r0
114                 mov     ip, #1
115                 str     ip, [sp, #S_IP + S_OFF] @ trace exit [IP = 1]
116                 bl      SYMBOL_NAME(syscall_trace)
117                 str     tip, [sp, #S_IP + S_OFF]
118                 b       slow_syscall_return
120 2:              add     r1, sp, #S_OFF
121                 tst     scno, #0x00f00000       @ is it a Unix SWI?
122                 bne     3f
123                 subs    r0, scno, #(KSWI_SYS_BASE - KSWI_BASE)
124                 bcs     SYMBOL_NAME(arm_syscall)
125                 b       SYMBOL_NAME(sys_ni_syscall) @ not private func
127 3:              eor     r0, scno, #OS_NUMBER <<20       @ Put OS number back
128                 adrsvc  al, lr, slow_syscall_return
129                 b       SYMBOL_NAME(deferred)
131                 .align  5
132                 .type   __softirq_state, #object
133 __softirq_state:
134                 .word   SYMBOL_NAME(softirq_state)
136                 .type   sys_call_table, #object
137 ENTRY(sys_call_table)
138 #include "calls.S"
140 /*============================================================================
141  * Special system call wrappers
142  */
143 @ r0 = syscall number
144 @ r5 = syscall table
145                 .type   sys_syscall, #function
146 SYMBOL_NAME(sys_syscall):
147                 eor     scno, r0, #OS_NUMBER << 20
148                 cmp     scno, #NR_syscalls      @ check range
149                 add     ip, sp, #S_OFF
150                 stmleia sp, {r5, r6}            @ shuffle args
151                 movle   r0, r1
152                 movle   r1, r2
153                 movle   r2, r3
154                 movle   r3, r4
155                 ldrle   pc, [tbl, scno, lsl #2]
156                 b       sys_ni_syscall
158 sys_fork_wrapper:
159                 add     r0, sp, #S_OFF
160                 b       SYMBOL_NAME(sys_fork)
162 sys_vfork_wrapper:
163                 add     r0, sp, #S_OFF
164                 b       SYMBOL_NAME(sys_vfork)
166 sys_execve_wrapper:
167                 add     r3, sp, #S_OFF
168                 b       SYMBOL_NAME(sys_execve)
170 sys_clone_wapper:
171                 add     r2, sp, #S_OFF
172                 b       SYMBOL_NAME(sys_clone)
174 sys_sigsuspend_wrapper:
175                 add     r3, sp, #S_OFF
176                 b       SYMBOL_NAME(sys_sigsuspend)
178 sys_rt_sigsuspend_wrapper:
179                 add     r2, sp, #S_OFF
180                 b       SYMBOL_NAME(sys_rt_sigsuspend)
182 sys_sigreturn_wrapper:
183                 add     r0, sp, #S_OFF
184                 b       SYMBOL_NAME(sys_sigreturn)
186 sys_rt_sigreturn_wrapper:
187                 add     r0, sp, #S_OFF
188                 b       SYMBOL_NAME(sys_rt_sigreturn)
190 sys_sigaltstack_wrapper:
191                 ldr     r2, [sp, #S_OFF + S_SP]
192                 b       do_sigaltstack
195  * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
196  * offset, we return EINVAL.
197  */
198 sys_mmap2:
199 #if PAGE_SHIFT > 12
200                 tst     r5, #PGOFF_MASK
201                 moveq   r5, r5, lsr #PGOFF_SHIFT
202                 streq   r5, [sp, #4]
203                 beq     do_mmap2
204                 mov     r0, #-EINVAL
205                 RETINSTR(mov,pc, lr)
206 #else
207                 str     r5, [sp, #4]
208                 b       do_mmap2
209 #endif
211                 .data
213 ENTRY(fp_enter)
214                 .word   fpe_not_present