blob: cedc8bd8880468251d5b3abf6431f7c29e0a372e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
4 * for more details.
5 *
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
10 *
11 * Hairy, the userspace application uses a different argument passing
12 * convention than the kernel, so we have to translate things from o32
Ralf Baechle70342282013-01-22 12:59:30 +010013 * to ABI64 calling convention. 64-bit syscalls are also processed
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * here for now.
15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/errno.h>
17#include <asm/asm.h>
18#include <asm/asmmacro.h>
Ralf Baechle192ef362006-07-07 14:07:18 +010019#include <asm/irqflags.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#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>
26
Ralf Baechle70342282013-01-22 12:59:30 +010027 .align 5
Linus Torvalds1da177e2005-04-16 15:20:36 -070028NESTED(handle_sys, PT_SIZE, sp)
29 .set noat
30 SAVE_SOME
Atsushi Nemotoeae6c0d2006-09-26 23:43:40 +090031 TRACE_IRQS_ON_RELOAD
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 STI
33 .set at
34 ld t1, PT_EPC(sp) # skip syscall on return
35
36 dsubu t0, v0, __NR_O32_Linux # check syscall number
Firoz Khanbe856432018-12-13 14:37:36 +053037 sltiu t0, t0, __NR_O32_Linux_syscalls
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 daddiu t1, 4 # skip to next instruction
39 sd t1, PT_EPC(sp)
40 beqz t0, not_o32_scall
41#if 0
42 SAVE_ALL
43 move a1, v0
Huacai Chenda706e52020-05-07 17:49:18 +080044 ASM_PRINT("Scall %ld\n")
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 RESTORE_ALL
46#endif
47
48 /* We don't want to stumble over broken sign extensions from
49 userland. O32 does never use the upper half. */
50 sll a0, a0, 0
51 sll a1, a1, 0
52 sll a2, a2, 0
53 sll a3, a3, 0
54
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 sd a3, PT_R26(sp) # save a3 for syscall restarting
56
57 /*
58 * More than four arguments. Try to deal with it by copying the
59 * stack arguments from the user stack to the kernel stack.
60 * This Sucks (TM).
61 *
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.
64 */
65 ld t0, PT_R29(sp) # get old user stack pointer
66 daddu t1, t0, 32
67 bltz t1, bad_stack
68
Ralf Baechle7928eb02015-07-08 04:49:10 +020069load_a4: lw a4, 16(t0) # argument #5 from usp
70load_a5: lw a5, 20(t0) # argument #6 from usp
71load_a6: lw a6, 24(t0) # argument #7 from usp
72load_a7: lw a7, 28(t0) # argument #8 from usp
73loads_done:
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
75 .section __ex_table,"a"
Ralf Baechle7928eb02015-07-08 04:49:10 +020076 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
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 .previous
81
Ralf Baechlee7f3b482013-05-29 01:02:18 +020082 li t1, _TIF_WORK_SYSCALL_ENTRY
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
84 and t0, t1, t0
85 bnez t0, trace_a_syscall
86
Markos Chandrasd218af72015-09-25 08:17:42 +010087syscall_common:
Matt Redfearna400bed2016-03-29 09:35:31 +010088 dsll t0, v0, 3 # offset into table
89 ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
90
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 jalr t2 # Do The Real Thing (TM)
92
93 li t0, -EMAXERRNO - 1 # error?
94 sltu t0, t0, v0
95 sd t0, PT_R7(sp) # set error flag
96 beqz t0, 1f
97
Al Viro8f5a00eb2010-09-28 18:50:37 +010098 ld t1, PT_R2(sp) # syscall number
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 dnegu v0 # error
Al Viro8f5a00eb2010-09-28 18:50:37 +0100100 sd t1, PT_R0(sp) # save it for syscall restarting
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011: sd v0, PT_R2(sp) # result
102
103o32_syscall_exit:
Al Viro02f884e2012-05-05 16:11:35 -0400104 j syscall_exit_partial
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106/* ------------------------------------------------------------------------ */
107
108trace_a_syscall:
109 SAVE_STATIC
110 sd a4, PT_R8(sp) # Save argument registers
111 sd a5, PT_R9(sp)
112 sd a6, PT_R10(sp)
113 sd a7, PT_R11(sp) # For indirect syscalls
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 move a0, sp
Markos Chandras4c21b8f2014-01-22 14:40:03 +0000116 /*
Markos Chandrasad61ba22014-07-24 12:10:02 +0100117 * absolute syscall number is in v0 unless we called syscall(__NR_###)
Markos Chandras4c21b8f2014-01-22 14:40:03 +0000118 * 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)
122 */
Markos Chandrasad61ba22014-07-24 12:10:02 +0100123 .set push
124 .set reorder
125 subu t1, v0, __NR_O32_Linux
126 move a1, v0
127 bnez t1, 1f /* __NR_syscall at offset 0 */
Aurelien Jarno79b4a9c2019-04-09 16:53:55 +0200128 ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
Markos Chandrasad61ba22014-07-24 12:10:02 +0100129 .set pop
Markos Chandras4c21b8f2014-01-22 14:40:03 +0000130
1311: jal syscall_trace_enter
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Markos Chandrasd218af72015-09-25 08:17:42 +0100133 bltz v0, 1f # seccomp failed? Skip syscall
Markos Chandras9d37c402014-01-22 14:40:02 +0000134
Ralf Baechle04a70522005-11-30 16:24:57 +0000135 RESTORE_STATIC
Matt Redfearna400bed2016-03-29 09:35:31 +0100136 ld v0, PT_R2(sp) # Restore syscall (maybe modified)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 ld a0, PT_R4(sp) # Restore argument registers
138 ld a1, PT_R5(sp)
139 ld a2, PT_R6(sp)
140 ld a3, PT_R7(sp)
141 ld a4, PT_R8(sp)
142 ld a5, PT_R9(sp)
143 ld a6, PT_R10(sp)
144 ld a7, PT_R11(sp) # For indirect syscalls
Matt Redfearna400bed2016-03-29 09:35:31 +0100145
146 dsubu t0, v0, __NR_O32_Linux # check (new) syscall number
Firoz Khanbe856432018-12-13 14:37:36 +0530147 sltiu t0, t0, __NR_O32_Linux_syscalls
Matt Redfearna400bed2016-03-29 09:35:31 +0100148 beqz t0, not_o32_scall
149
Markos Chandrasd218af72015-09-25 08:17:42 +0100150 j syscall_common
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
Markos Chandrasd218af72015-09-25 08:17:42 +01001521: j syscall_exit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
154/* ------------------------------------------------------------------------ */
155
156 /*
157 * The stackpointer for a call with more than 4 arguments is bad.
158 */
159bad_stack:
Al Viro5b89c002010-09-28 18:50:47 +0100160 li v0, EFAULT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 sd v0, PT_R2(sp)
162 li t0, 1 # set error flag
163 sd t0, PT_R7(sp)
164 j o32_syscall_exit
165
Ralf Baechle7928eb02015-07-08 04:49:10 +0200166bad_stack_a4:
167 li a4, 0
168 b load_a5
169
170bad_stack_a5:
171 li a5, 0
172 b load_a6
173
174bad_stack_a6:
175 li a6, 0
176 b load_a7
177
178bad_stack_a7:
179 li a7, 0
180 b loads_done
181
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182not_o32_scall:
183 /*
184 * This is not an o32 compatibility syscall, pass it on
185 * to the 64-bit syscall handlers.
186 */
187#ifdef CONFIG_MIPS32_N32
188 j handle_sysn32
189#else
190 j handle_sys64
191#endif
192 END(handle_sys)
193
194LEAF(sys32_syscall)
Vlad Malove807f952008-11-18 15:05:46 -0800195 subu t0, a0, __NR_O32_Linux # check syscall number
Firoz Khanbe856432018-12-13 14:37:36 +0530196 sltiu v0, t0, __NR_O32_Linux_syscalls
Vlad Malove807f952008-11-18 15:05:46 -0800197 beqz t0, einval # do not recurse
198 dsll t1, t0, 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 beqz v0, einval
Ralf Baechle2a9c2752012-07-12 14:01:31 +0200200 ld t2, sys32_call_table(t1) # syscall routine
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202 move a0, a1 # shift argument registers
203 move a1, a2
204 move a2, a3
205 move a3, a4
206 move a4, a5
207 move a5, a6
208 move a6, a7
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 jr t2
210 /* Unreached */
211
Ralf Baechle70342282013-01-22 12:59:30 +0100212einval: li v0, -ENOSYS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 jr ra
214 END(sys32_syscall)
215
Masahiro Yamadaecbba302021-03-01 23:48:24 +0900216#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, compat)
Firoz Khandc7077f2019-01-02 20:26:17 +0530217#define __SYSCALL(nr, entry) PTR entry
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 .align 3
Ralf Baechle2a9c2752012-07-12 14:01:31 +0200219 .type sys32_call_table,@object
220EXPORT(sys32_call_table)
Masahiro Yamadaecbba302021-03-01 23:48:24 +0900221#include <asm/syscall_table_o32.h>