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 222