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/assembler.h>
12#include <asm/unistd.h>
13#include <asm/ftrace.h>
14#include <asm/unwind.h>
15
16#ifdef CONFIG_NEED_RET_TO_USER
17#include <mach/entry-macro.S>
18#else
19	.macro  arch_ret_to_user, tmp1, tmp2
20	.endm
21#endif
22
23#include "entry-header.S"
24
25
26	.align	5
27/*
28 * This is the fast syscall return path.  We do as little as
29 * possible here, and this includes saving r0 back into the SVC
30 * stack.
31 */
32ret_fast_syscall:
33 UNWIND(.fnstart	)
34 UNWIND(.cantunwind	)
35	disable_irq				@ disable interrupts
36	ldr	r1, [tsk, #TI_FLAGS]		@ re-check for syscall tracing
37	tst	r1, #_TIF_SYSCALL_WORK
38	bne	__sys_trace_return
39	tst	r1, #_TIF_WORK_MASK
40	bne	fast_work_pending
41	asm_trace_hardirqs_on
42
43	/* perform architecture specific actions before user return */
44	arch_ret_to_user r1, lr
45	ct_user_enter
46
47	restore_user_regs fast = 1, offset = S_OFF
48 UNWIND(.fnend		)
49
50/*
51 * Ok, we need to do extra processing, enter the slow path.
52 */
53fast_work_pending:
54	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0
55work_pending:
56	mov	r0, sp				@ 'regs'
57	mov	r2, why				@ 'syscall'
58	bl	do_work_pending
59	cmp	r0, #0
60	beq	no_work_pending
61	movlt	scno, #(__NR_restart_syscall - __NR_SYSCALL_BASE)
62	ldmia	sp, {r0 - r6}			@ have to reload r0 - r6
63	b	local_restart			@ ... and off we go
64
65/*
66 * "slow" syscall return path.  "why" tells us if this was a real syscall.
67 */
68ENTRY(ret_to_user)
69ret_slow_syscall:
70	disable_irq				@ disable interrupts
71ENTRY(ret_to_user_from_irq)
72	ldr	r1, [tsk, #TI_FLAGS]
73	tst	r1, #_TIF_WORK_MASK
74	bne	work_pending
75no_work_pending:
76	asm_trace_hardirqs_on
77
78	/* perform architecture specific actions before user return */
79	arch_ret_to_user r1, lr
80	ct_user_enter save = 0
81
82	restore_user_regs fast = 0, offset = 0
83ENDPROC(ret_to_user_from_irq)
84ENDPROC(ret_to_user)
85
86/*
87 * This is how we return from a fork.
88 */
89ENTRY(ret_from_fork)
90	bl	schedule_tail
91	cmp	r5, #0
92	movne	r0, r4
93	adrne	lr, BSYM(1f)
94	retne	r5
951:	get_thread_info tsk
96	b	ret_slow_syscall
97ENDPROC(ret_from_fork)
98
99	.equ NR_syscalls,0
100#define CALL(x) .equ NR_syscalls,NR_syscalls+1
101#include "calls.S"
102
103/*
104 * Ensure that the system call table is equal to __NR_syscalls,
105 * which is the value the rest of the system sees
106 */
107.ifne NR_syscalls - __NR_syscalls
108.error "__NR_syscalls is not equal to the size of the syscall table"
109.endif
110
111#undef CALL
112#define CALL(x) .long x
113
114/*=============================================================================
115 * SWI handler
116 *-----------------------------------------------------------------------------
117 */
118
119	.align	5
120ENTRY(vector_swi)
121#ifdef CONFIG_CPU_V7M
122	v7m_exception_entry
123#else
124	sub	sp, sp, #S_FRAME_SIZE
125	stmia	sp, {r0 - r12}			@ Calling r0 - r12
126 ARM(	add	r8, sp, #S_PC		)
127 ARM(	stmdb	r8, {sp, lr}^		)	@ Calling sp, lr
128 THUMB(	mov	r8, sp			)
129 THUMB(	store_user_sp_lr r8, r10, S_SP	)	@ calling sp, lr
130	mrs	r8, spsr			@ called from non-FIQ mode, so ok.
131	str	lr, [sp, #S_PC]			@ Save calling PC
132	str	r8, [sp, #S_PSR]		@ Save CPSR
133	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
134#endif
135	zero_fp
136	alignment_trap r10, ip, __cr_alignment
137	enable_irq
138	ct_user_exit
139	get_thread_info tsk
140
141	/*
142	 * Get the system call number.
143	 */
144
145#if defined(CONFIG_OABI_COMPAT)
146
147	/*
148	 * If we have CONFIG_OABI_COMPAT then we need to look at the swi
149	 * value to determine if it is an EABI or an old ABI call.
150	 */
151#ifdef CONFIG_ARM_THUMB
152	tst	r8, #PSR_T_BIT
153	movne	r10, #0				@ no thumb OABI emulation
154 USER(	ldreq	r10, [lr, #-4]		)	@ get SWI instruction
155#else
156 USER(	ldr	r10, [lr, #-4]		)	@ get SWI instruction
157#endif
158 ARM_BE8(rev	r10, r10)			@ little endian instruction
159
160#elif defined(CONFIG_AEABI)
161
162	/*
163	 * Pure EABI user space always put syscall number into scno (r7).
164	 */
165#elif defined(CONFIG_ARM_THUMB)
166	/* Legacy ABI only, possibly thumb mode. */
167	tst	r8, #PSR_T_BIT			@ this is SPSR from save_user_regs
168	addne	scno, r7, #__NR_SYSCALL_BASE	@ put OS number in
169 USER(	ldreq	scno, [lr, #-4]		)
170
171#else
172	/* Legacy ABI only. */
173 USER(	ldr	scno, [lr, #-4]		)	@ get SWI instruction
174#endif
175
176	adr	tbl, sys_call_table		@ load syscall table pointer
177
178#if defined(CONFIG_OABI_COMPAT)
179	/*
180	 * If the swi argument is zero, this is an EABI call and we do nothing.
181	 *
182	 * If this is an old ABI call, get the syscall number into scno and
183	 * get the old ABI syscall table address.
184	 */
185	bics	r10, r10, #0xff000000
186	eorne	scno, r10, #__NR_OABI_SYSCALL_BASE
187	ldrne	tbl, =sys_oabi_call_table
188#elif !defined(CONFIG_AEABI)
189	bic	scno, scno, #0xff000000		@ mask off SWI op-code
190	eor	scno, scno, #__NR_SYSCALL_BASE	@ check OS number
191#endif
192
193local_restart:
194	ldr	r10, [tsk, #TI_FLAGS]		@ check for syscall tracing
195	stmdb	sp!, {r4, r5}			@ push fifth and sixth args
196
197	tst	r10, #_TIF_SYSCALL_WORK		@ are we tracing syscalls?
198	bne	__sys_trace
199
200	cmp	scno, #NR_syscalls		@ check upper syscall limit
201	adr	lr, BSYM(ret_fast_syscall)	@ return address
202	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
203
204	add	r1, sp, #S_OFF
2052:	cmp	scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
206	eor	r0, scno, #__NR_SYSCALL_BASE	@ put OS number back
207	bcs	arm_syscall
208	mov	why, #0				@ no longer a real syscall
209	b	sys_ni_syscall			@ not private func
210
211#if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI)
212	/*
213	 * We failed to handle a fault trying to access the page
214	 * containing the swi instruction, but we're not really in a
215	 * position to return -EFAULT. Instead, return back to the
216	 * instruction and re-enter the user fault handling path trying
217	 * to page it in. This will likely result in sending SEGV to the
218	 * current task.
219	 */
2209001:
221	sub	lr, lr, #4
222	str	lr, [sp, #S_PC]
223	b	ret_fast_syscall
224#endif
225ENDPROC(vector_swi)
226
227	/*
228	 * This is the really slow path.  We're going to be doing
229	 * context switches, and waiting for our parent to respond.
230	 */
231__sys_trace:
232	mov	r1, scno
233	add	r0, sp, #S_OFF
234	bl	syscall_trace_enter
235
236	adr	lr, BSYM(__sys_trace_return)	@ return address
237	mov	scno, r0			@ syscall number (possibly new)
238	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
239	cmp	scno, #NR_syscalls		@ check upper syscall limit
240	ldmccia	r1, {r0 - r6}			@ have to reload r0 - r6
241	stmccia	sp, {r4, r5}			@ and update the stack args
242	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
243	cmp	scno, #-1			@ skip the syscall?
244	bne	2b
245	add	sp, sp, #S_OFF			@ restore stack
246	b	ret_slow_syscall
247
248__sys_trace_return:
249	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
250	mov	r0, sp
251	bl	syscall_trace_exit
252	b	ret_slow_syscall
253
254	.align	5
255#ifdef CONFIG_ALIGNMENT_TRAP
256	.type	__cr_alignment, #object
257__cr_alignment:
258	.word	cr_alignment
259#endif
260	.ltorg
261
262/*
263 * This is the syscall table declaration for native ABI syscalls.
264 * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
265 */
266#define ABI(native, compat) native
267#ifdef CONFIG_AEABI
268#define OBSOLETE(syscall) sys_ni_syscall
269#else
270#define OBSOLETE(syscall) syscall
271#endif
272
273	.type	sys_call_table, #object
274ENTRY(sys_call_table)
275#include "calls.S"
276#undef ABI
277#undef OBSOLETE
278
279/*============================================================================
280 * Special system call wrappers
281 */
282@ r0 = syscall number
283@ r8 = syscall table
284sys_syscall:
285		bic	scno, r0, #__NR_OABI_SYSCALL_BASE
286		cmp	scno, #__NR_syscall - __NR_SYSCALL_BASE
287		cmpne	scno, #NR_syscalls	@ check range
288		stmloia	sp, {r5, r6}		@ shuffle args
289		movlo	r0, r1
290		movlo	r1, r2
291		movlo	r2, r3
292		movlo	r3, r4
293		ldrlo	pc, [tbl, scno, lsl #2]
294		b	sys_ni_syscall
295ENDPROC(sys_syscall)
296
297sys_sigreturn_wrapper:
298		add	r0, sp, #S_OFF
299		mov	why, #0		@ prevent syscall restart handling
300		b	sys_sigreturn
301ENDPROC(sys_sigreturn_wrapper)
302
303sys_rt_sigreturn_wrapper:
304		add	r0, sp, #S_OFF
305		mov	why, #0		@ prevent syscall restart handling
306		b	sys_rt_sigreturn
307ENDPROC(sys_rt_sigreturn_wrapper)
308
309sys_statfs64_wrapper:
310		teq	r1, #88
311		moveq	r1, #84
312		b	sys_statfs64
313ENDPROC(sys_statfs64_wrapper)
314
315sys_fstatfs64_wrapper:
316		teq	r1, #88
317		moveq	r1, #84
318		b	sys_fstatfs64
319ENDPROC(sys_fstatfs64_wrapper)
320
321/*
322 * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
323 * offset, we return EINVAL.
324 */
325sys_mmap2:
326#if PAGE_SHIFT > 12
327		tst	r5, #PGOFF_MASK
328		moveq	r5, r5, lsr #PAGE_SHIFT - 12
329		streq	r5, [sp, #4]
330		beq	sys_mmap_pgoff
331		mov	r0, #-EINVAL
332		ret	lr
333#else
334		str	r5, [sp, #4]
335		b	sys_mmap_pgoff
336#endif
337ENDPROC(sys_mmap2)
338
339#ifdef CONFIG_OABI_COMPAT
340
341/*
342 * These are syscalls with argument register differences
343 */
344
345sys_oabi_pread64:
346		stmia	sp, {r3, r4}
347		b	sys_pread64
348ENDPROC(sys_oabi_pread64)
349
350sys_oabi_pwrite64:
351		stmia	sp, {r3, r4}
352		b	sys_pwrite64
353ENDPROC(sys_oabi_pwrite64)
354
355sys_oabi_truncate64:
356		mov	r3, r2
357		mov	r2, r1
358		b	sys_truncate64
359ENDPROC(sys_oabi_truncate64)
360
361sys_oabi_ftruncate64:
362		mov	r3, r2
363		mov	r2, r1
364		b	sys_ftruncate64
365ENDPROC(sys_oabi_ftruncate64)
366
367sys_oabi_readahead:
368		str	r3, [sp]
369		mov	r3, r2
370		mov	r2, r1
371		b	sys_readahead
372ENDPROC(sys_oabi_readahead)
373
374/*
375 * Let's declare a second syscall table for old ABI binaries
376 * using the compatibility syscall entries.
377 */
378#define ABI(native, compat) compat
379#define OBSOLETE(syscall) syscall
380
381	.type	sys_oabi_call_table, #object
382ENTRY(sys_oabi_call_table)
383#include "calls.S"
384#undef ABI
385#undef OBSOLETE
386
387#endif
388
389