entry-common.S 11.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10
/*
 *  linux/arch/arm/kernel/entry-common.S
 *
 *  Copyright (C) 2000 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

11
#include <asm/assembler.h>
L
Linus Torvalds 已提交
12
#include <asm/unistd.h>
13
#include <asm/ftrace.h>
14
#include <asm/unwind.h>
15 16 17 18 19
#ifdef CONFIG_AEABI
#include <asm/unistd-oabi.h>
#endif

	.equ	NR_syscalls, __NR_syscalls
L
Linus Torvalds 已提交
20

21 22 23 24 25 26 27
#ifdef CONFIG_NEED_RET_TO_USER
#include <mach/entry-macro.S>
#else
	.macro  arch_ret_to_user, tmp1, tmp2
	.endm
#endif

L
Linus Torvalds 已提交
28 29
#include "entry-header.S"

30
saved_psr	.req	r8
R
Russell King 已提交
31 32 33 34
#if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING)
saved_pc	.req	r9
#define TRACE(x...) x
#else
35
saved_pc	.req	lr
R
Russell King 已提交
36 37
#define TRACE(x...)
#endif
L
Linus Torvalds 已提交
38 39

	.align	5
R
Russell King 已提交
40
#if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING))
L
Linus Torvalds 已提交
41
/*
R
Russell King 已提交
42 43 44 45
 * This is the fast syscall return path.  We do as little as possible here,
 * such as avoiding writing r0 to the stack.  We only use this path if we
 * have tracing and context tracking disabled - the overheads from those
 * features make this path too inefficient.
L
Linus Torvalds 已提交
46 47
 */
ret_fast_syscall:
48 49
 UNWIND(.fnstart	)
 UNWIND(.cantunwind	)
R
Russell King 已提交
50
	disable_irq_notrace			@ disable interrupts
51
	ldr	r1, [tsk, #TI_FLAGS]		@ re-check for syscall tracing
52
	tst	r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
L
Linus Torvalds 已提交
53
	bne	fast_work_pending
54

55 56 57
	/* perform architecture specific actions before user return */
	arch_ret_to_user r1, lr

58
	restore_user_regs fast = 1, offset = S_OFF
59
 UNWIND(.fnend		)
R
Russell King 已提交
60
ENDPROC(ret_fast_syscall)
L
Linus Torvalds 已提交
61

R
Russell King 已提交
62
	/* Ok, we need to do extra processing, enter the slow path. */
L
Linus Torvalds 已提交
63 64
fast_work_pending:
	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0
R
Russell King 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77
	/* fall through to work_pending */
#else
/*
 * The "replacement" ret_fast_syscall for when tracing or context tracking
 * is enabled.  As we will need to call out to some C functions, we save
 * r0 first to avoid needing to save registers around each C function call.
 */
ret_fast_syscall:
 UNWIND(.fnstart	)
 UNWIND(.cantunwind	)
	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
	disable_irq_notrace			@ disable interrupts
	ldr	r1, [tsk, #TI_FLAGS]		@ re-check for syscall tracing
78
	tst	r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
R
Russell King 已提交
79 80 81 82 83 84 85 86 87 88
	beq	no_work_pending
 UNWIND(.fnend		)
ENDPROC(ret_fast_syscall)

	/* Slower path - fall through to work_pending */
#endif

	tst	r1, #_TIF_SYSCALL_WORK
	bne	__sys_trace_return_nosave
slow_work_pending:
L
Linus Torvalds 已提交
89 90
	mov	r0, sp				@ 'regs'
	mov	r2, why				@ 'syscall'
91
	bl	do_work_pending
92
	cmp	r0, #0
93
	beq	no_work_pending
94
	movlt	scno, #(__NR_restart_syscall - __NR_SYSCALL_BASE)
95 96
	ldmia	sp, {r0 - r6}			@ have to reload r0 - r6
	b	local_restart			@ ... and off we go
97
ENDPROC(ret_fast_syscall)
98

L
Linus Torvalds 已提交
99 100
/*
 * "slow" syscall return path.  "why" tells us if this was a real syscall.
R
Russell King 已提交
101 102 103
 * IRQs may be enabled here, so always disable them.  Note that we use the
 * "notrace" version to avoid calling into the tracing code unnecessarily.
 * do_work_pending() will update this state if necessary.
L
Linus Torvalds 已提交
104 105 106
 */
ENTRY(ret_to_user)
ret_slow_syscall:
R
Russell King 已提交
107
	disable_irq_notrace			@ disable interrupts
108
ENTRY(ret_to_user_from_irq)
L
Linus Torvalds 已提交
109 110
	ldr	r1, [tsk, #TI_FLAGS]
	tst	r1, #_TIF_WORK_MASK
R
Russell King 已提交
111
	bne	slow_work_pending
L
Linus Torvalds 已提交
112
no_work_pending:
R
Russell King 已提交
113
	asm_trace_hardirqs_on save = 0
114

115 116
	/* perform architecture specific actions before user return */
	arch_ret_to_user r1, lr
117
	ct_user_enter save = 0
118

119
	restore_user_regs fast = 0, offset = 0
120
ENDPROC(ret_to_user_from_irq)
121
ENDPROC(ret_to_user)
L
Linus Torvalds 已提交
122 123 124 125 126 127

/*
 * This is how we return from a fork.
 */
ENTRY(ret_from_fork)
	bl	schedule_tail
128 129
	cmp	r5, #0
	movne	r0, r4
130
	badrne	lr, 1f
131
	retne	r5
132
1:	get_thread_info tsk
L
Linus Torvalds 已提交
133
	b	ret_slow_syscall
134
ENDPROC(ret_from_fork)
L
Linus Torvalds 已提交
135 136 137 138 139 140 141 142

/*=============================================================================
 * SWI handler
 *-----------------------------------------------------------------------------
 */

	.align	5
ENTRY(vector_swi)
143 144 145
#ifdef CONFIG_CPU_V7M
	v7m_exception_entry
#else
146
	sub	sp, sp, #PT_REGS_SIZE
147
	stmia	sp, {r0 - r12}			@ Calling r0 - r12
148 149 150 151
 ARM(	add	r8, sp, #S_PC		)
 ARM(	stmdb	r8, {sp, lr}^		)	@ Calling sp, lr
 THUMB(	mov	r8, sp			)
 THUMB(	store_user_sp_lr r8, r10, S_SP	)	@ calling sp, lr
152
	mrs	saved_psr, spsr			@ called from non-FIQ mode, so ok.
R
Russell King 已提交
153
 TRACE(	mov	saved_pc, lr		)
154 155
	str	saved_pc, [sp, #S_PC]		@ Save calling PC
	str	saved_psr, [sp, #S_PSR]		@ Save CPSR
156
	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
157
#endif
L
Linus Torvalds 已提交
158
	zero_fp
159
	alignment_trap r10, ip, __cr_alignment
160 161 162
	asm_trace_hardirqs_on save=0
	enable_irq_notrace
	ct_user_exit save=0
163

164 165 166
	/*
	 * Get the system call number.
	 */
167

168
#if defined(CONFIG_OABI_COMPAT)
169

170 171 172 173 174
	/*
	 * If we have CONFIG_OABI_COMPAT then we need to look at the swi
	 * value to determine if it is an EABI or an old ABI call.
	 */
#ifdef CONFIG_ARM_THUMB
175
	tst	saved_psr, #PSR_T_BIT
176
	movne	r10, #0				@ no thumb OABI emulation
177
 USER(	ldreq	r10, [saved_pc, #-4]	)	@ get SWI instruction
178
#else
179
 USER(	ldr	r10, [saved_pc, #-4]	)	@ get SWI instruction
180
#endif
181
 ARM_BE8(rev	r10, r10)			@ little endian instruction
182 183 184 185 186 187

#elif defined(CONFIG_AEABI)

	/*
	 * Pure EABI user space always put syscall number into scno (r7).
	 */
188
#elif defined(CONFIG_ARM_THUMB)
189
	/* Legacy ABI only, possibly thumb mode. */
190
	tst	saved_psr, #PSR_T_BIT		@ this is SPSR from save_user_regs
191
	addne	scno, r7, #__NR_SYSCALL_BASE	@ put OS number in
192
 USER(	ldreq	scno, [saved_pc, #-4]	)
193

194
#else
195
	/* Legacy ABI only. */
196
 USER(	ldr	scno, [saved_pc, #-4]	)	@ get SWI instruction
197
#endif
L
Linus Torvalds 已提交
198

199 200
	/* saved_psr and saved_pc are now dead */

201 202
	uaccess_disable tbl

203 204 205 206 207 208 209 210 211 212 213 214 215
	adr	tbl, sys_call_table		@ load syscall table pointer

#if defined(CONFIG_OABI_COMPAT)
	/*
	 * If the swi argument is zero, this is an EABI call and we do nothing.
	 *
	 * If this is an old ABI call, get the syscall number into scno and
	 * get the old ABI syscall table address.
	 */
	bics	r10, r10, #0xff000000
	eorne	scno, r10, #__NR_OABI_SYSCALL_BASE
	ldrne	tbl, =sys_oabi_call_table
#elif !defined(CONFIG_AEABI)
L
Linus Torvalds 已提交
216
	bic	scno, scno, #0xff000000		@ mask off SWI op-code
217
	eor	scno, scno, #__NR_SYSCALL_BASE	@ check OS number
218
#endif
219
	get_thread_info tsk
220 221 222 223 224
	/*
	 * Reload the registers that may have been corrupted on entry to
	 * the syscall assembly (by tracing or context tracking.)
	 */
 TRACE(	ldmia	sp, {r0 - r3}		)
225

226
local_restart:
N
Nicolas Pitre 已提交
227
	ldr	r10, [tsk, #TI_FLAGS]		@ check for syscall tracing
228
	stmdb	sp!, {r4, r5}			@ push fifth and sixth args
N
Nicolas Pitre 已提交
229

230
	tst	r10, #_TIF_SYSCALL_WORK		@ are we tracing syscalls?
L
Linus Torvalds 已提交
231 232 233
	bne	__sys_trace

	cmp	scno, #NR_syscalls		@ check upper syscall limit
234
	badr	lr, ret_fast_syscall		@ return address
L
Linus Torvalds 已提交
235 236 237
	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine

	add	r1, sp, #S_OFF
238
2:	cmp	scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
239
	eor	r0, scno, #__NR_SYSCALL_BASE	@ put OS number back
240
	bcs	arm_syscall
241
	mov	why, #0				@ no longer a real syscall
L
Linus Torvalds 已提交
242
	b	sys_ni_syscall			@ not private func
243 244 245 246 247 248 249 250 251 252 253

#if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI)
	/*
	 * We failed to handle a fault trying to access the page
	 * containing the swi instruction, but we're not really in a
	 * position to return -EFAULT. Instead, return back to the
	 * instruction and re-enter the user fault handling path trying
	 * to page it in. This will likely result in sending SEGV to the
	 * current task.
	 */
9001:
254
	sub	lr, saved_pc, #4
255
	str	lr, [sp, #S_PC]
256
	get_thread_info tsk
257 258
	b	ret_fast_syscall
#endif
259
ENDPROC(vector_swi)
L
Linus Torvalds 已提交
260 261 262 263 264 265

	/*
	 * This is the really slow path.  We're going to be doing
	 * context switches, and waiting for our parent to respond.
	 */
__sys_trace:
266 267 268
	mov	r1, scno
	add	r0, sp, #S_OFF
	bl	syscall_trace_enter
L
Linus Torvalds 已提交
269

270
	badr	lr, __sys_trace_return		@ return address
271
	mov	scno, r0			@ syscall number (possibly new)
L
Linus Torvalds 已提交
272 273
	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
	cmp	scno, #NR_syscalls		@ check upper syscall limit
274 275
	ldmccia	r1, {r0 - r6}			@ have to reload r0 - r6
	stmccia	sp, {r4, r5}			@ and update the stack args
L
Linus Torvalds 已提交
276
	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
277 278 279 280
	cmp	scno, #-1			@ skip the syscall?
	bne	2b
	add	sp, sp, #S_OFF			@ restore stack
	b	ret_slow_syscall
L
Linus Torvalds 已提交
281 282 283

__sys_trace_return:
	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
284 285
	mov	r0, sp
	bl	syscall_trace_exit
L
Linus Torvalds 已提交
286 287
	b	ret_slow_syscall

R
Russell King 已提交
288
__sys_trace_return_nosave:
289
	enable_irq_notrace
R
Russell King 已提交
290 291 292 293
	mov	r0, sp
	bl	syscall_trace_exit
	b	ret_slow_syscall

L
Linus Torvalds 已提交
294 295 296 297 298
	.align	5
#ifdef CONFIG_ALIGNMENT_TRAP
	.type	__cr_alignment, #object
__cr_alignment:
	.word	cr_alignment
299 300 301
#endif
	.ltorg

302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
	.macro	syscall_table_start, sym
	.equ	__sys_nr, 0
	.type	\sym, #object
ENTRY(\sym)
	.endm

	.macro	syscall, nr, func
	.ifgt	__sys_nr - \nr
	.error	"Duplicated/unorded system call entry"
	.endif
	.rept	\nr - __sys_nr
	.long	sys_ni_syscall
	.endr
	.long	\func
	.equ	__sys_nr, \nr + 1
	.endm

	.macro	syscall_table_end, sym
	.ifgt	__sys_nr - __NR_syscalls
	.error	"System call table too big"
	.endif
	.rept	__NR_syscalls - __sys_nr
	.long	sys_ni_syscall
	.endr
	.size	\sym, . - \sym
	.endm

#define NATIVE(nr, func) syscall nr, func

331 332 333 334
/*
 * This is the syscall table declaration for native ABI syscalls.
 * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
 */
335 336
	syscall_table_start sys_call_table
#define COMPAT(nr, native, compat) syscall nr, native
337
#ifdef CONFIG_AEABI
338
#include <calls-eabi.S>
339
#else
340
#include <calls-oabi.S>
L
Linus Torvalds 已提交
341
#endif
342 343
#undef COMPAT
	syscall_table_end sys_call_table
L
Linus Torvalds 已提交
344 345 346 347 348

/*============================================================================
 * Special system call wrappers
 */
@ r0 = syscall number
349
@ r8 = syscall table
L
Linus Torvalds 已提交
350
sys_syscall:
351
		bic	scno, r0, #__NR_OABI_SYSCALL_BASE
L
Linus Torvalds 已提交
352 353 354 355 356 357 358 359 360
		cmp	scno, #__NR_syscall - __NR_SYSCALL_BASE
		cmpne	scno, #NR_syscalls	@ check range
		stmloia	sp, {r5, r6}		@ shuffle args
		movlo	r0, r1
		movlo	r1, r2
		movlo	r2, r3
		movlo	r3, r4
		ldrlo	pc, [tbl, scno, lsl #2]
		b	sys_ni_syscall
361
ENDPROC(sys_syscall)
L
Linus Torvalds 已提交
362 363 364

sys_sigreturn_wrapper:
		add	r0, sp, #S_OFF
A
Al Viro 已提交
365
		mov	why, #0		@ prevent syscall restart handling
L
Linus Torvalds 已提交
366
		b	sys_sigreturn
367
ENDPROC(sys_sigreturn_wrapper)
L
Linus Torvalds 已提交
368 369 370

sys_rt_sigreturn_wrapper:
		add	r0, sp, #S_OFF
A
Al Viro 已提交
371
		mov	why, #0		@ prevent syscall restart handling
L
Linus Torvalds 已提交
372
		b	sys_rt_sigreturn
373
ENDPROC(sys_rt_sigreturn_wrapper)
L
Linus Torvalds 已提交
374

375 376 377 378
sys_statfs64_wrapper:
		teq	r1, #88
		moveq	r1, #84
		b	sys_statfs64
379
ENDPROC(sys_statfs64_wrapper)
380 381 382 383 384

sys_fstatfs64_wrapper:
		teq	r1, #88
		moveq	r1, #84
		b	sys_fstatfs64
385
ENDPROC(sys_fstatfs64_wrapper)
386

L
Linus Torvalds 已提交
387 388 389 390 391 392 393 394 395
/*
 * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
 * offset, we return EINVAL.
 */
sys_mmap2:
#if PAGE_SHIFT > 12
		tst	r5, #PGOFF_MASK
		moveq	r5, r5, lsr #PAGE_SHIFT - 12
		streq	r5, [sp, #4]
A
Al Viro 已提交
396
		beq	sys_mmap_pgoff
L
Linus Torvalds 已提交
397
		mov	r0, #-EINVAL
398
		ret	lr
L
Linus Torvalds 已提交
399 400
#else
		str	r5, [sp, #4]
A
Al Viro 已提交
401
		b	sys_mmap_pgoff
L
Linus Torvalds 已提交
402
#endif
403
ENDPROC(sys_mmap2)
404 405

#ifdef CONFIG_OABI_COMPAT
406

407 408 409 410 411 412 413
/*
 * These are syscalls with argument register differences
 */

sys_oabi_pread64:
		stmia	sp, {r3, r4}
		b	sys_pread64
414
ENDPROC(sys_oabi_pread64)
415 416 417 418

sys_oabi_pwrite64:
		stmia	sp, {r3, r4}
		b	sys_pwrite64
419
ENDPROC(sys_oabi_pwrite64)
420 421 422 423 424

sys_oabi_truncate64:
		mov	r3, r2
		mov	r2, r1
		b	sys_truncate64
425
ENDPROC(sys_oabi_truncate64)
426 427 428 429 430

sys_oabi_ftruncate64:
		mov	r3, r2
		mov	r2, r1
		b	sys_ftruncate64
431
ENDPROC(sys_oabi_ftruncate64)
432 433 434 435 436 437

sys_oabi_readahead:
		str	r3, [sp]
		mov	r3, r2
		mov	r2, r1
		b	sys_readahead
438
ENDPROC(sys_oabi_readahead)
439

440 441 442 443
/*
 * Let's declare a second syscall table for old ABI binaries
 * using the compatibility syscall entries.
 */
444 445 446 447
	syscall_table_start sys_oabi_call_table
#define COMPAT(nr, native, compat) syscall nr, compat
#include <calls-oabi.S>
	syscall_table_end sys_oabi_call_table
448

449 450
#endif