xref: /linux/arch/mips/kernel/scall32-o32.S (revision 3a07362fab1653d3aca31a9155c8cc776138fd02)
11da177e4SLinus Torvalds/*
21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public
31da177e4SLinus Torvalds * License.  See the file "COPYING" in the main directory of this archive
41da177e4SLinus Torvalds * for more details.
51da177e4SLinus Torvalds *
6192ef366SRalf Baechle * Copyright (C) 1995-99, 2000- 02, 06 Ralf Baechle <ralf@linux-mips.org>
71da177e4SLinus Torvalds * Copyright (C) 2001 MIPS Technologies, Inc.
81da177e4SLinus Torvalds * Copyright (C) 2004 Thiemo Seufer
986bdb277SMarkos Chandras * Copyright (C) 2014 Imagination Technologies Ltd.
101da177e4SLinus Torvalds */
111da177e4SLinus Torvalds#include <linux/errno.h>
121da177e4SLinus Torvalds#include <asm/asm.h>
131da177e4SLinus Torvalds#include <asm/asmmacro.h>
14192ef366SRalf Baechle#include <asm/irqflags.h>
151da177e4SLinus Torvalds#include <asm/mipsregs.h>
161da177e4SLinus Torvalds#include <asm/regdef.h>
171da177e4SLinus Torvalds#include <asm/stackframe.h>
181da177e4SLinus Torvalds#include <asm/isadep.h>
191da177e4SLinus Torvalds#include <asm/sysmips.h>
201da177e4SLinus Torvalds#include <asm/thread_info.h>
211da177e4SLinus Torvalds#include <asm/unistd.h>
22048eb582SSam Ravnborg#include <asm/asm-offsets.h>
231da177e4SLinus Torvalds
241da177e4SLinus Torvalds	.align	5
251da177e4SLinus TorvaldsNESTED(handle_sys, PT_SIZE, sp)
261da177e4SLinus Torvalds	.set	noat
271da177e4SLinus Torvalds	SAVE_SOME
28eae6c0daSAtsushi Nemoto	TRACE_IRQS_ON_RELOAD
291da177e4SLinus Torvalds	STI
301da177e4SLinus Torvalds	.set	at
311da177e4SLinus Torvalds
321da177e4SLinus Torvalds	lw	t1, PT_EPC(sp)		# skip syscall on return
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds	addiu	t1, 4			# skip to next instruction
351da177e4SLinus Torvalds	sw	t1, PT_EPC(sp)
361da177e4SLinus Torvalds
371da177e4SLinus Torvalds	sw	a3, PT_R26(sp)		# save a3 for syscall restarting
381da177e4SLinus Torvalds
3946e12c07SRalf Baechle	/*
4046e12c07SRalf Baechle	 * More than four arguments.  Try to deal with it by copying the
4146e12c07SRalf Baechle	 * stack arguments from the user stack to the kernel stack.
4246e12c07SRalf Baechle	 * This Sucks (TM).
4346e12c07SRalf Baechle	 */
4446e12c07SRalf Baechle	lw	t0, PT_R29(sp)		# get old user stack pointer
4546e12c07SRalf Baechle
4646e12c07SRalf Baechle	/*
4746e12c07SRalf Baechle	 * We intentionally keep the kernel stack a little below the top of
4846e12c07SRalf Baechle	 * userspace so we don't have to do a slower byte accurate check here.
4946e12c07SRalf Baechle	 */
5046e12c07SRalf Baechle	addu	t4, t0, 32
5104324f44SThomas Bogendoerfer	bltz	t4, bad_stack		# -> sp is bad
5246e12c07SRalf Baechle
5346e12c07SRalf Baechle	/*
5446e12c07SRalf Baechle	 * Ok, copy the args from the luser stack to the kernel stack.
5546e12c07SRalf Baechle	 */
5646e12c07SRalf Baechle
5746e12c07SRalf Baechle	.set    push
5846e12c07SRalf Baechle	.set    noreorder
5946e12c07SRalf Baechle	.set	nomacro
6046e12c07SRalf Baechle
617928eb03SRalf Baechleload_a4: user_lw(t5, 16(t0))		# argument #5 from usp
627928eb03SRalf Baechleload_a5: user_lw(t6, 20(t0))		# argument #6 from usp
637928eb03SRalf Baechleload_a6: user_lw(t7, 24(t0))		# argument #7 from usp
647928eb03SRalf Baechleload_a7: user_lw(t8, 28(t0))		# argument #8 from usp
657928eb03SRalf Baechleloads_done:
6646e12c07SRalf Baechle
6746e12c07SRalf Baechle	sw	t5, 16(sp)		# argument #5 to ksp
6846e12c07SRalf Baechle	sw	t6, 20(sp)		# argument #6 to ksp
6946e12c07SRalf Baechle	sw	t7, 24(sp)		# argument #7 to ksp
7046e12c07SRalf Baechle	sw	t8, 28(sp)		# argument #8 to ksp
7146e12c07SRalf Baechle	.set	pop
7246e12c07SRalf Baechle
7346e12c07SRalf Baechle	.section __ex_table,"a"
74fa62f39dSThomas Bogendoerfer	PTR_WD	load_a4, bad_stack_a4
75fa62f39dSThomas Bogendoerfer	PTR_WD	load_a5, bad_stack_a5
76fa62f39dSThomas Bogendoerfer	PTR_WD	load_a6, bad_stack_a6
77fa62f39dSThomas Bogendoerfer	PTR_WD	load_a7, bad_stack_a7
7846e12c07SRalf Baechle	.previous
7946e12c07SRalf Baechle
80*4370b673SJiaxun Yang	/*
81*4370b673SJiaxun Yang	 * syscall number is in v0 unless we called syscall(__NR_###)
82*4370b673SJiaxun Yang	 * where the real syscall number is in a0
83*4370b673SJiaxun Yang	 */
84*4370b673SJiaxun Yang	subu	t2, v0,  __NR_O32_Linux
85*4370b673SJiaxun Yang	bnez	t2, 1f /* __NR_syscall at offset 0 */
86*4370b673SJiaxun Yang	LONG_S	a0, TI_SYSCALL($28)	# Save a0 as syscall number
87*4370b673SJiaxun Yang	b	2f
88*4370b673SJiaxun Yang1:
89*4370b673SJiaxun Yang	LONG_S	v0, TI_SYSCALL($28)	# Save v0 as syscall number
90*4370b673SJiaxun Yang2:
91*4370b673SJiaxun Yang
921da177e4SLinus Torvalds	lw	t0, TI_FLAGS($28)	# syscall tracing enabled?
93e7f3b48aSRalf Baechle	li	t1, _TIF_WORK_SYSCALL_ENTRY
941da177e4SLinus Torvalds	and	t0, t1
951da177e4SLinus Torvalds	bnez	t0, syscall_trace_entry # -> yes
96d218af78SMarkos Chandrassyscall_common:
97a400bed6SMatt Redfearn	subu	v0, v0, __NR_O32_Linux	# check syscall number
98be856439SFiroz Khan	sltiu	t0, v0, __NR_O32_Linux_syscalls
99d218af78SMarkos Chandras	beqz	t0, illegal_syscall
100d218af78SMarkos Chandras
101d218af78SMarkos Chandras	sll	t0, v0, 2
102d218af78SMarkos Chandras	la	t1, sys_call_table
103d218af78SMarkos Chandras	addu	t1, t0
104d218af78SMarkos Chandras	lw	t2, (t1)		# syscall routine
105d218af78SMarkos Chandras
106d218af78SMarkos Chandras	beqz	t2, illegal_syscall
1071da177e4SLinus Torvalds
1081da177e4SLinus Torvalds	jalr	t2			# Do The Real Thing (TM)
1091da177e4SLinus Torvalds
1101da177e4SLinus Torvalds	li	t0, -EMAXERRNO - 1	# error?
1111da177e4SLinus Torvalds	sltu	t0, t0, v0
1121da177e4SLinus Torvalds	sw	t0, PT_R7(sp)		# set error flag
1131da177e4SLinus Torvalds	beqz	t0, 1f
1141da177e4SLinus Torvalds
1158f5a00ebSAl Viro	lw	t1, PT_R2(sp)		# syscall number
1161da177e4SLinus Torvalds	negu	v0			# error
1178f5a00ebSAl Viro	sw	t1, PT_R0(sp)		# save it for syscall restarting
1181da177e4SLinus Torvalds1:	sw	v0, PT_R2(sp)		# result
1191da177e4SLinus Torvalds
1201da177e4SLinus Torvaldso32_syscall_exit:
12102f884edSAl Viro	j	syscall_exit_partial
1221da177e4SLinus Torvalds
1231da177e4SLinus Torvalds/* ------------------------------------------------------------------------ */
1241da177e4SLinus Torvalds
1251da177e4SLinus Torvaldssyscall_trace_entry:
1261da177e4SLinus Torvalds	SAVE_STATIC
1271da177e4SLinus Torvalds	move	a0, sp
1284c21b8fdSMarkos Chandras
129*4370b673SJiaxun Yang	jal	syscall_trace_enter
1301da177e4SLinus Torvalds
131d218af78SMarkos Chandras	bltz	v0, 1f			# seccomp failed? Skip syscall
1329d37c405SMarkos Chandras
13304a7052cSRalf Baechle	RESTORE_STATIC
134a400bed6SMatt Redfearn	lw	v0, PT_R2(sp)		# Restore syscall (maybe modified)
1351da177e4SLinus Torvalds	lw	a0, PT_R4(sp)		# Restore argument registers
1361da177e4SLinus Torvalds	lw	a1, PT_R5(sp)
1371da177e4SLinus Torvalds	lw	a2, PT_R6(sp)
1381da177e4SLinus Torvalds	lw	a3, PT_R7(sp)
139d218af78SMarkos Chandras	j	syscall_common
1401da177e4SLinus Torvalds
141d218af78SMarkos Chandras1:	j	syscall_exit
1421da177e4SLinus Torvalds
1431da177e4SLinus Torvalds/* ------------------------------------------------------------------------ */
1441da177e4SLinus Torvalds
1451da177e4SLinus Torvalds	/*
1467928eb03SRalf Baechle	 * Our open-coded access area sanity test for the stack pointer
1477928eb03SRalf Baechle	 * failed. We probably should handle this case a bit more drastic.
1481da177e4SLinus Torvalds	 */
1491da177e4SLinus Torvaldsbad_stack:
1505b89c004SAl Viro	li	v0, EFAULT
1511da177e4SLinus Torvalds	sw	v0, PT_R2(sp)
1521da177e4SLinus Torvalds	li	t0, 1				# set error flag
1531da177e4SLinus Torvalds	sw	t0, PT_R7(sp)
1541da177e4SLinus Torvalds	j	o32_syscall_exit
1551da177e4SLinus Torvalds
1567928eb03SRalf Baechlebad_stack_a4:
1577928eb03SRalf Baechle	li	t5, 0
1587928eb03SRalf Baechle	b	load_a5
1597928eb03SRalf Baechle
1607928eb03SRalf Baechlebad_stack_a5:
1617928eb03SRalf Baechle	li	t6, 0
1627928eb03SRalf Baechle	b	load_a6
1637928eb03SRalf Baechle
1647928eb03SRalf Baechlebad_stack_a6:
1657928eb03SRalf Baechle	li	t7, 0
1667928eb03SRalf Baechle	b	load_a7
1677928eb03SRalf Baechle
1687928eb03SRalf Baechlebad_stack_a7:
1697928eb03SRalf Baechle	li	t8, 0
1707928eb03SRalf Baechle	b	loads_done
1717928eb03SRalf Baechle
1721da177e4SLinus Torvalds	/*
1731da177e4SLinus Torvalds	 * The system call does not exist in this kernel
1741da177e4SLinus Torvalds	 */
1751da177e4SLinus Torvaldsillegal_syscall:
176bda8229bSAtsushi Nemoto	li	v0, ENOSYS			# error
1771da177e4SLinus Torvalds	sw	v0, PT_R2(sp)
1781da177e4SLinus Torvalds	li	t0, 1				# set error flag
1791da177e4SLinus Torvalds	sw	t0, PT_R7(sp)
1801da177e4SLinus Torvalds	j	o32_syscall_exit
1811da177e4SLinus Torvalds	END(handle_sys)
1821da177e4SLinus Torvalds
1831da177e4SLinus Torvalds	LEAF(sys_syscall)
1841da177e4SLinus Torvalds	subu	t0, a0, __NR_O32_Linux	# check syscall number
185be856439SFiroz Khan	sltiu	v0, t0, __NR_O32_Linux_syscalls
186e807f957SVlad Malov	beqz	t0, einval		# do not recurse
18746e12c07SRalf Baechle	sll	t1, t0, 2
1881da177e4SLinus Torvalds	beqz	v0, einval
1891da177e4SLinus Torvalds	lw	t2, sys_call_table(t1)		# syscall routine
1901da177e4SLinus Torvalds
1911da177e4SLinus Torvalds	move	a0, a1				# shift argument registers
1921da177e4SLinus Torvalds	move	a1, a2
1931da177e4SLinus Torvalds	move	a2, a3
1941da177e4SLinus Torvalds	lw	a3, 16(sp)
1951da177e4SLinus Torvalds	lw	t4, 20(sp)
1961da177e4SLinus Torvalds	lw	t5, 24(sp)
1971da177e4SLinus Torvalds	lw	t6, 28(sp)
1981da177e4SLinus Torvalds	sw	t4, 16(sp)
1991da177e4SLinus Torvalds	sw	t5, 20(sp)
2001da177e4SLinus Torvalds	sw	t6, 24(sp)
2011da177e4SLinus Torvalds	jr	t2
2021da177e4SLinus Torvalds	/* Unreached */
2031da177e4SLinus Torvalds
204fb498e25SAtsushi Nemotoeinval: li	v0, -ENOSYS
2051da177e4SLinus Torvalds	jr	ra
2061da177e4SLinus Torvalds	END(sys_syscall)
2071da177e4SLinus Torvalds
2086a00cb61SFiroz Khan#ifdef CONFIG_MIPS_MT_FPAFF
2096a00cb61SFiroz Khan	/*
2106a00cb61SFiroz Khan	 * For FPU affinity scheduling on MIPS MT processors, we need to
2116a00cb61SFiroz Khan	 * intercept sys_sched_xxxaffinity() calls until we get a proper hook
2126a00cb61SFiroz Khan	 * in kernel/sched/core.c.  Considered only temporary we only support
2136a00cb61SFiroz Khan	 * these hooks for the 32-bit kernel - there is no MIPS64 MT processor
2146a00cb61SFiroz Khan	 * atm.
2156a00cb61SFiroz Khan	 */
2166a00cb61SFiroz Khan#define sys_sched_setaffinity	mipsmt_sys_sched_setaffinity
2176a00cb61SFiroz Khan#define sys_sched_getaffinity	mipsmt_sys_sched_getaffinity
2186a00cb61SFiroz Khan#endif /* CONFIG_MIPS_MT_FPAFF */
2196a00cb61SFiroz Khan
220ecbba30fSMasahiro Yamada#define __SYSCALL_WITH_COMPAT(nr, native, compat)	__SYSCALL(nr, native)
221fa62f39dSThomas Bogendoerfer#define __SYSCALL(nr, entry) 	PTR_WD entry
22246e12c07SRalf Baechle	.align	2
22346e12c07SRalf Baechle	.type	sys_call_table, @object
22446e12c07SRalf BaechleEXPORT(sys_call_table)
225ecbba30fSMasahiro Yamada#include <asm/syscall_table_o32.h>
226