entry-common.S 11.5 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
#include <asm/memory.h>
16 17 18 19 20
#ifdef CONFIG_AEABI
#include <asm/unistd-oabi.h>
#endif

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

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

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

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

40
	.section .entry.text,"ax",%progbits
L
Linus Torvalds 已提交
41
	.align	5
42 43
#if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING) || \
	IS_ENABLED(CONFIG_DEBUG_RSEQ))
L
Linus Torvalds 已提交
44
/*
R
Russell King 已提交
45 46
 * 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
47 48
 * have tracing, context tracking and rseq debug disabled - the overheads
 * from those features make this path too inefficient.
L
Linus Torvalds 已提交
49 50
 */
ret_fast_syscall:
51 52
 UNWIND(.fnstart	)
 UNWIND(.cantunwind	)
R
Russell King 已提交
53
	disable_irq_notrace			@ disable interrupts
54 55 56
	ldr	r2, [tsk, #TI_ADDR_LIMIT]
	cmp	r2, #TASK_SIZE
	blne	addr_limit_check_failed
57
	ldr	r1, [tsk, #TI_FLAGS]		@ re-check for syscall tracing
58
	tst	r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
L
Linus Torvalds 已提交
59
	bne	fast_work_pending
60

61

62 63 64
	/* perform architecture specific actions before user return */
	arch_ret_to_user r1, lr

65
	restore_user_regs fast = 1, offset = S_OFF
66
 UNWIND(.fnend		)
R
Russell King 已提交
67
ENDPROC(ret_fast_syscall)
L
Linus Torvalds 已提交
68

R
Russell King 已提交
69
	/* Ok, we need to do extra processing, enter the slow path. */
L
Linus Torvalds 已提交
70 71
fast_work_pending:
	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0
R
Russell King 已提交
72 73 74
	/* fall through to work_pending */
#else
/*
75 76 77 78
 * The "replacement" ret_fast_syscall for when tracing, context tracking,
 * or rseq debug 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.
R
Russell King 已提交
79 80 81 82 83
 */
ret_fast_syscall:
 UNWIND(.fnstart	)
 UNWIND(.cantunwind	)
	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
84 85 86 87 88
#if IS_ENABLED(CONFIG_DEBUG_RSEQ)
	/* do_rseq_syscall needs interrupts enabled. */
	mov	r0, sp				@ 'regs'
	bl	do_rseq_syscall
#endif
R
Russell King 已提交
89
	disable_irq_notrace			@ disable interrupts
90 91 92
	ldr	r2, [tsk, #TI_ADDR_LIMIT]
	cmp	r2, #TASK_SIZE
	blne	addr_limit_check_failed
R
Russell King 已提交
93
	ldr	r1, [tsk, #TI_FLAGS]		@ re-check for syscall tracing
94
	tst	r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
R
Russell King 已提交
95 96 97 98 99 100 101 102 103 104
	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 已提交
105 106
	mov	r0, sp				@ 'regs'
	mov	r2, why				@ 'syscall'
107
	bl	do_work_pending
108
	cmp	r0, #0
109
	beq	no_work_pending
110
	movlt	scno, #(__NR_restart_syscall - __NR_SYSCALL_BASE)
111 112
	ldmia	sp, {r0 - r6}			@ have to reload r0 - r6
	b	local_restart			@ ... and off we go
113
ENDPROC(ret_fast_syscall)
114

L
Linus Torvalds 已提交
115 116
/*
 * "slow" syscall return path.  "why" tells us if this was a real syscall.
R
Russell King 已提交
117 118 119
 * 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 已提交
120 121 122
 */
ENTRY(ret_to_user)
ret_slow_syscall:
123 124 125 126 127 128
#if IS_ENABLED(CONFIG_DEBUG_RSEQ)
	/* do_rseq_syscall needs interrupts enabled. */
	enable_irq_notrace			@ enable interrupts
	mov	r0, sp				@ 'regs'
	bl	do_rseq_syscall
#endif
R
Russell King 已提交
129
	disable_irq_notrace			@ disable interrupts
130
ENTRY(ret_to_user_from_irq)
131 132 133
	ldr	r2, [tsk, #TI_ADDR_LIMIT]
	cmp	r2, #TASK_SIZE
	blne	addr_limit_check_failed
L
Linus Torvalds 已提交
134 135
	ldr	r1, [tsk, #TI_FLAGS]
	tst	r1, #_TIF_WORK_MASK
R
Russell King 已提交
136
	bne	slow_work_pending
L
Linus Torvalds 已提交
137
no_work_pending:
R
Russell King 已提交
138
	asm_trace_hardirqs_on save = 0
139

140 141
	/* perform architecture specific actions before user return */
	arch_ret_to_user r1, lr
142
	ct_user_enter save = 0
143

144
	restore_user_regs fast = 0, offset = 0
145
ENDPROC(ret_to_user_from_irq)
146
ENDPROC(ret_to_user)
L
Linus Torvalds 已提交
147 148 149 150 151 152

/*
 * This is how we return from a fork.
 */
ENTRY(ret_from_fork)
	bl	schedule_tail
153 154
	cmp	r5, #0
	movne	r0, r4
155
	badrne	lr, 1f
156
	retne	r5
157
1:	get_thread_info tsk
L
Linus Torvalds 已提交
158
	b	ret_slow_syscall
159
ENDPROC(ret_from_fork)
L
Linus Torvalds 已提交
160 161 162 163 164 165 166 167

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

	.align	5
ENTRY(vector_swi)
168 169 170
#ifdef CONFIG_CPU_V7M
	v7m_exception_entry
#else
171
	sub	sp, sp, #PT_REGS_SIZE
172
	stmia	sp, {r0 - r12}			@ Calling r0 - r12
173 174 175 176
 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
177
	mrs	saved_psr, spsr			@ called from non-FIQ mode, so ok.
R
Russell King 已提交
178
 TRACE(	mov	saved_pc, lr		)
179 180
	str	saved_pc, [sp, #S_PC]		@ Save calling PC
	str	saved_psr, [sp, #S_PSR]		@ Save CPSR
181
	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
182
#endif
L
Linus Torvalds 已提交
183
	zero_fp
184
	alignment_trap r10, ip, __cr_alignment
185 186 187
	asm_trace_hardirqs_on save=0
	enable_irq_notrace
	ct_user_exit save=0
188

189 190 191
	/*
	 * Get the system call number.
	 */
192

193
#if defined(CONFIG_OABI_COMPAT)
194

195 196 197 198 199
	/*
	 * 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
200
	tst	saved_psr, #PSR_T_BIT
201
	movne	r10, #0				@ no thumb OABI emulation
202
 USER(	ldreq	r10, [saved_pc, #-4]	)	@ get SWI instruction
203
#else
204
 USER(	ldr	r10, [saved_pc, #-4]	)	@ get SWI instruction
205
#endif
206
 ARM_BE8(rev	r10, r10)			@ little endian instruction
207 208 209 210 211 212

#elif defined(CONFIG_AEABI)

	/*
	 * Pure EABI user space always put syscall number into scno (r7).
	 */
213
#elif defined(CONFIG_ARM_THUMB)
214
	/* Legacy ABI only, possibly thumb mode. */
215
	tst	saved_psr, #PSR_T_BIT		@ this is SPSR from save_user_regs
216
	addne	scno, r7, #__NR_SYSCALL_BASE	@ put OS number in
217
 USER(	ldreq	scno, [saved_pc, #-4]	)
218

219
#else
220
	/* Legacy ABI only. */
221
 USER(	ldr	scno, [saved_pc, #-4]	)	@ get SWI instruction
222
#endif
L
Linus Torvalds 已提交
223

224 225
	/* saved_psr and saved_pc are now dead */

226 227
	uaccess_disable tbl

228 229 230 231 232 233 234 235 236 237 238 239 240
	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 已提交
241
	bic	scno, scno, #0xff000000		@ mask off SWI op-code
242
	eor	scno, scno, #__NR_SYSCALL_BASE	@ check OS number
243
#endif
244
	get_thread_info tsk
245 246 247 248 249
	/*
	 * Reload the registers that may have been corrupted on entry to
	 * the syscall assembly (by tracing or context tracking.)
	 */
 TRACE(	ldmia	sp, {r0 - r3}		)
250

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

255
	tst	r10, #_TIF_SYSCALL_WORK		@ are we tracing syscalls?
L
Linus Torvalds 已提交
256 257 258
	bne	__sys_trace

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

	add	r1, sp, #S_OFF
263
2:	cmp	scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
264
	eor	r0, scno, #__NR_SYSCALL_BASE	@ put OS number back
265
	bcs	arm_syscall
266
	mov	why, #0				@ no longer a real syscall
L
Linus Torvalds 已提交
267
	b	sys_ni_syscall			@ not private func
268 269 270 271 272 273 274 275 276 277 278

#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:
279
	sub	lr, saved_pc, #4
280
	str	lr, [sp, #S_PC]
281
	get_thread_info tsk
282 283
	b	ret_fast_syscall
#endif
284
ENDPROC(vector_swi)
L
Linus Torvalds 已提交
285 286 287 288 289 290

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

295
	badr	lr, __sys_trace_return		@ return address
296
	mov	scno, r0			@ syscall number (possibly new)
L
Linus Torvalds 已提交
297 298
	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
	cmp	scno, #NR_syscalls		@ check upper syscall limit
299 300
	ldmccia	r1, {r0 - r6}			@ have to reload r0 - r6
	stmccia	sp, {r4, r5}			@ and update the stack args
L
Linus Torvalds 已提交
301
	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
302 303 304 305
	cmp	scno, #-1			@ skip the syscall?
	bne	2b
	add	sp, sp, #S_OFF			@ restore stack
	b	ret_slow_syscall
L
Linus Torvalds 已提交
306 307 308

__sys_trace_return:
	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
309 310
	mov	r0, sp
	bl	syscall_trace_exit
L
Linus Torvalds 已提交
311 312
	b	ret_slow_syscall

R
Russell King 已提交
313
__sys_trace_return_nosave:
314
	enable_irq_notrace
R
Russell King 已提交
315 316 317 318
	mov	r0, sp
	bl	syscall_trace_exit
	b	ret_slow_syscall

L
Linus Torvalds 已提交
319 320 321 322 323
	.align	5
#ifdef CONFIG_ALIGNMENT_TRAP
	.type	__cr_alignment, #object
__cr_alignment:
	.word	cr_alignment
324 325 326
#endif
	.ltorg

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
	.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

356 357 358 359
/*
 * This is the syscall table declaration for native ABI syscalls.
 * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
 */
360 361
	syscall_table_start sys_call_table
#define COMPAT(nr, native, compat) syscall nr, native
362
#ifdef CONFIG_AEABI
363
#include <calls-eabi.S>
364
#else
365
#include <calls-oabi.S>
L
Linus Torvalds 已提交
366
#endif
367 368
#undef COMPAT
	syscall_table_end sys_call_table
L
Linus Torvalds 已提交
369 370 371 372 373

/*============================================================================
 * Special system call wrappers
 */
@ r0 = syscall number
374
@ r8 = syscall table
L
Linus Torvalds 已提交
375
sys_syscall:
376
		bic	scno, r0, #__NR_OABI_SYSCALL_BASE
L
Linus Torvalds 已提交
377 378 379 380 381 382 383 384 385
		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
386
ENDPROC(sys_syscall)
L
Linus Torvalds 已提交
387 388 389

sys_sigreturn_wrapper:
		add	r0, sp, #S_OFF
A
Al Viro 已提交
390
		mov	why, #0		@ prevent syscall restart handling
L
Linus Torvalds 已提交
391
		b	sys_sigreturn
392
ENDPROC(sys_sigreturn_wrapper)
L
Linus Torvalds 已提交
393 394 395

sys_rt_sigreturn_wrapper:
		add	r0, sp, #S_OFF
A
Al Viro 已提交
396
		mov	why, #0		@ prevent syscall restart handling
L
Linus Torvalds 已提交
397
		b	sys_rt_sigreturn
398
ENDPROC(sys_rt_sigreturn_wrapper)
L
Linus Torvalds 已提交
399

400 401 402 403
sys_statfs64_wrapper:
		teq	r1, #88
		moveq	r1, #84
		b	sys_statfs64
404
ENDPROC(sys_statfs64_wrapper)
405 406 407 408 409

sys_fstatfs64_wrapper:
		teq	r1, #88
		moveq	r1, #84
		b	sys_fstatfs64
410
ENDPROC(sys_fstatfs64_wrapper)
411

L
Linus Torvalds 已提交
412 413 414 415 416 417
/*
 * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
 * offset, we return EINVAL.
 */
sys_mmap2:
		str	r5, [sp, #4]
A
Al Viro 已提交
418
		b	sys_mmap_pgoff
419
ENDPROC(sys_mmap2)
420 421

#ifdef CONFIG_OABI_COMPAT
422

423 424 425 426 427 428 429
/*
 * These are syscalls with argument register differences
 */

sys_oabi_pread64:
		stmia	sp, {r3, r4}
		b	sys_pread64
430
ENDPROC(sys_oabi_pread64)
431 432 433 434

sys_oabi_pwrite64:
		stmia	sp, {r3, r4}
		b	sys_pwrite64
435
ENDPROC(sys_oabi_pwrite64)
436 437 438 439 440

sys_oabi_truncate64:
		mov	r3, r2
		mov	r2, r1
		b	sys_truncate64
441
ENDPROC(sys_oabi_truncate64)
442 443 444 445 446

sys_oabi_ftruncate64:
		mov	r3, r2
		mov	r2, r1
		b	sys_ftruncate64
447
ENDPROC(sys_oabi_ftruncate64)
448 449 450 451 452 453

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

456 457 458 459
/*
 * Let's declare a second syscall table for old ABI binaries
 * using the compatibility syscall entries.
 */
460 461 462 463
	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
464

465 466
#endif