Loading...
1/*
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
13 * to ABI64 calling convention. 64-bit syscalls are also processed
14 * here for now.
15 */
16#include <linux/errno.h>
17#include <asm/asm.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>
26
27 .align 5
28NESTED(handle_sys, PT_SIZE, sp)
29 .set noat
30 SAVE_SOME
31 TRACE_IRQS_ON_RELOAD
32 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
37 sltiu t0, t0, __NR_O32_Linux_syscalls
38 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
44 PRINT("Scall %ld\n")
45 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
55 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
69load_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:
74
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
80 .previous
81
82 li t1, _TIF_WORK_SYSCALL_ENTRY
83 LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
84 and t0, t1, t0
85 bnez t0, trace_a_syscall
86
87syscall_common:
88 dsll t0, v0, 3 # offset into table
89 ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
90
91 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
98 ld t1, PT_R2(sp) # syscall number
99 dnegu v0 # error
100 sd t1, PT_R0(sp) # save it for syscall restarting
1011: sd v0, PT_R2(sp) # result
102
103o32_syscall_exit:
104 j syscall_exit_partial
105
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
115 move a0, sp
116 /*
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)
122 */
123 .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 */
128 ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
129 .set pop
130
1311: jal syscall_trace_enter
132
133 bltz v0, 1f # seccomp failed? Skip syscall
134
135 RESTORE_STATIC
136 ld v0, PT_R2(sp) # Restore syscall (maybe modified)
137 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
145
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
149
150 j syscall_common
151
1521: j syscall_exit
153
154/* ------------------------------------------------------------------------ */
155
156 /*
157 * The stackpointer for a call with more than 4 arguments is bad.
158 */
159bad_stack:
160 li v0, EFAULT
161 sd v0, PT_R2(sp)
162 li t0, 1 # set error flag
163 sd t0, PT_R7(sp)
164 j o32_syscall_exit
165
166bad_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
182not_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)
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
198 dsll t1, t0, 3
199 beqz v0, einval
200 ld t2, sys32_call_table(t1) # syscall routine
201
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
209 jr t2
210 /* Unreached */
211
212einval: li v0, -ENOSYS
213 jr ra
214 END(sys32_syscall)
215
216#define __SYSCALL(nr, entry) PTR entry
217 .align 3
218 .type sys32_call_table,@object
219EXPORT(sys32_call_table)
220#include <asm/syscall_table_64_o32.h>
221#undef __SYSCALL
1/*
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
13 * to ABI64 calling convention. 64-bit syscalls are also processed
14 * here for now.
15 */
16#include <linux/errno.h>
17#include <asm/asm.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>
26
27 .align 5
28NESTED(handle_sys, PT_SIZE, sp)
29 .set noat
30 SAVE_SOME
31 TRACE_IRQS_ON_RELOAD
32 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
37 sltiu t0, t0, __NR_O32_Linux_syscalls
38 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
44 ASM_PRINT("Scall %ld\n")
45 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
55 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
69load_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:
74
75 .section __ex_table,"a"
76 PTR_WD load_a4, bad_stack_a4
77 PTR_WD load_a5, bad_stack_a5
78 PTR_WD load_a6, bad_stack_a6
79 PTR_WD load_a7, bad_stack_a7
80 .previous
81
82 /*
83 * absolute syscall number is in v0 unless we called syscall(__NR_###)
84 * where the real syscall number is in a0
85 * note: NR_syscall is the first O32 syscall but the macro is
86 * only defined when compiling with -mabi=32 (CONFIG_32BIT)
87 * therefore __NR_O32_Linux is used (4000)
88 */
89
90 subu t2, v0, __NR_O32_Linux
91 bnez t2, 1f /* __NR_syscall at offset 0 */
92 LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number
93 b 2f
941:
95 LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number
962:
97
98 li t1, _TIF_WORK_SYSCALL_ENTRY
99 LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
100 and t0, t1, t0
101 bnez t0, trace_a_syscall
102
103syscall_common:
104 dsll t0, v0, 3 # offset into table
105 ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
106
107 jalr t2 # Do The Real Thing (TM)
108
109 li t0, -EMAXERRNO - 1 # error?
110 sltu t0, t0, v0
111 sd t0, PT_R7(sp) # set error flag
112 beqz t0, 1f
113
114 ld t1, PT_R2(sp) # syscall number
115 dnegu v0 # error
116 sd t1, PT_R0(sp) # save it for syscall restarting
1171: sd v0, PT_R2(sp) # result
118
119o32_syscall_exit:
120 j syscall_exit_partial
121
122/* ------------------------------------------------------------------------ */
123
124trace_a_syscall:
125 SAVE_STATIC
126 sd a4, PT_R8(sp) # Save argument registers
127 sd a5, PT_R9(sp)
128 sd a6, PT_R10(sp)
129 sd a7, PT_R11(sp) # For indirect syscalls
130
131 move a0, sp
132 jal syscall_trace_enter
133
134 bltz v0, 1f # seccomp failed? Skip syscall
135
136 RESTORE_STATIC
137 ld v0, PT_R2(sp) # Restore syscall (maybe modified)
138 ld a0, PT_R4(sp) # Restore argument registers
139 ld a1, PT_R5(sp)
140 ld a2, PT_R6(sp)
141 ld a3, PT_R7(sp)
142 ld a4, PT_R8(sp)
143 ld a5, PT_R9(sp)
144 ld a6, PT_R10(sp)
145 ld a7, PT_R11(sp) # For indirect syscalls
146
147 dsubu t0, v0, __NR_O32_Linux # check (new) syscall number
148 sltiu t0, t0, __NR_O32_Linux_syscalls
149 beqz t0, not_o32_scall
150
151 j syscall_common
152
1531: j syscall_exit
154
155/* ------------------------------------------------------------------------ */
156
157 /*
158 * The stackpointer for a call with more than 4 arguments is bad.
159 */
160bad_stack:
161 li v0, EFAULT
162 sd v0, PT_R2(sp)
163 li t0, 1 # set error flag
164 sd t0, PT_R7(sp)
165 j o32_syscall_exit
166
167bad_stack_a4:
168 li a4, 0
169 b load_a5
170
171bad_stack_a5:
172 li a5, 0
173 b load_a6
174
175bad_stack_a6:
176 li a6, 0
177 b load_a7
178
179bad_stack_a7:
180 li a7, 0
181 b loads_done
182
183not_o32_scall:
184 /*
185 * This is not an o32 compatibility syscall, pass it on
186 * to the 64-bit syscall handlers.
187 */
188#ifdef CONFIG_MIPS32_N32
189 j handle_sysn32
190#else
191 j handle_sys64
192#endif
193 END(handle_sys)
194
195LEAF(sys32_syscall)
196 subu t0, a0, __NR_O32_Linux # check syscall number
197 sltiu v0, t0, __NR_O32_Linux_syscalls
198 beqz t0, einval # do not recurse
199 dsll t1, t0, 3
200 beqz v0, einval
201 ld t2, sys32_call_table(t1) # syscall routine
202
203 move a0, a1 # shift argument registers
204 move a1, a2
205 move a2, a3
206 move a3, a4
207 move a4, a5
208 move a5, a6
209 move a6, a7
210 jr t2
211 /* Unreached */
212
213einval: li v0, -ENOSYS
214 jr ra
215 END(sys32_syscall)
216
217#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, compat)
218#define __SYSCALL(nr, entry) PTR_WD entry
219 .align 3
220 .type sys32_call_table,@object
221EXPORT(sys32_call_table)
222#include <asm/syscall_table_o32.h>