2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle
7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8 * Copyright (C) 2001 MIPS Technologies, Inc.
9 * Copyright (C) 2004 Thiemo Seufer
11 * Hairy, the userspace application uses a different argument passing
12 * convention than the kernel, so we have to translate things from o32
13 * to ABI64 calling convention. 64-bit syscalls are also processed
16 #include <linux/errno.h>
18 #include <asm/asmmacro.h>
19 #include <asm/irqflags.h>
20 #include <asm/mipsregs.h>
21 #include <asm/regdef.h>
22 #include <asm/stackframe.h>
23 #include <asm/thread_info.h>
24 #include <asm/unistd.h>
25 #include <asm/sysmips.h>
28 NESTED(handle_sys, PT_SIZE, sp)
34 ld t1, PT_EPC(sp) # skip syscall on return
36 dsubu t0, v0, __NR_O32_Linux # check syscall number
37 sltiu t0, t0, __NR_O32_Linux_syscalls
38 daddiu t1, 4 # skip to next instruction
40 beqz t0, not_o32_scall
48 /* We don't want to stumble over broken sign extensions from
49 userland. O32 does never use the upper half. */
55 sd a3, PT_R26(sp) # save a3 for syscall restarting
58 * More than four arguments. Try to deal with it by copying the
59 * stack arguments from the user stack to the kernel stack.
62 * We intentionally keep the kernel stack a little below the top of
63 * userspace so we don't have to do a slower byte accurate check here.
65 ld t0, PT_R29(sp) # get old user stack pointer
69 load_a4: lw a4, 16(t0) # argument #5 from usp
70 load_a5: lw a5, 20(t0) # argument #6 from usp
71 load_a6: lw a6, 24(t0) # argument #7 from usp
72 load_a7: lw a7, 28(t0) # argument #8 from usp
75 .section __ex_table,"a"
76 PTR load_a4, bad_stack_a4
77 PTR load_a5, bad_stack_a5
78 PTR load_a6, bad_stack_a6
79 PTR load_a7, bad_stack_a7
82 li t1, _TIF_WORK_SYSCALL_ENTRY
83 LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
85 bnez t0, trace_a_syscall
88 dsll t0, v0, 3 # offset into table
89 ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
91 jalr t2 # Do The Real Thing (TM)
93 li t0, -EMAXERRNO - 1 # error?
95 sd t0, PT_R7(sp) # set error flag
98 ld t1, PT_R2(sp) # syscall number
100 sd t1, PT_R0(sp) # save it for syscall restarting
101 1: sd v0, PT_R2(sp) # result
104 j syscall_exit_partial
106 /* ------------------------------------------------------------------------ */
110 sd a4, PT_R8(sp) # Save argument registers
113 sd a7, PT_R11(sp) # For indirect syscalls
117 * absolute syscall number is in v0 unless we called syscall(__NR_###)
118 * where the real syscall number is in a0
119 * note: NR_syscall is the first O32 syscall but the macro is
120 * only defined when compiling with -mabi=32 (CONFIG_32BIT)
121 * therefore __NR_O32_Linux is used (4000)
125 subu t1, v0, __NR_O32_Linux
127 bnez t1, 1f /* __NR_syscall at offset 0 */
128 ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
131 1: jal syscall_trace_enter
133 bltz v0, 1f # seccomp failed? Skip syscall
136 ld v0, PT_R2(sp) # Restore syscall (maybe modified)
137 ld a0, PT_R4(sp) # Restore argument registers
144 ld a7, PT_R11(sp) # For indirect syscalls
146 dsubu t0, v0, __NR_O32_Linux # check (new) syscall number
147 sltiu t0, t0, __NR_O32_Linux_syscalls
148 beqz t0, not_o32_scall
154 /* ------------------------------------------------------------------------ */
157 * The stackpointer for a call with more than 4 arguments is bad.
162 li t0, 1 # set error flag
184 * This is not an o32 compatibility syscall, pass it on
185 * to the 64-bit syscall handlers.
187 #ifdef CONFIG_MIPS32_N32
195 subu t0, a0, __NR_O32_Linux # check syscall number
196 sltiu v0, t0, __NR_O32_Linux_syscalls
197 beqz t0, einval # do not recurse
200 ld t2, sys32_call_table(t1) # syscall routine
202 move a0, a1 # shift argument registers
212 einval: li v0, -ENOSYS
216 #define __SYSCALL(nr, entry) PTR entry
218 .type sys32_call_table,@object
219 EXPORT(sys32_call_table)
220 #include <asm/syscall_table_64_o32.h>