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-99, 2000- 02, 06 Ralf Baechle <ralf@linux-mips.org> 7 * Copyright (C) 2001 MIPS Technologies, Inc. 8 * Copyright (C) 2004 Thiemo Seufer 9 * Copyright (C) 2014 Imagination Technologies Ltd. 10 */ 11#include <linux/errno.h> 12#include <asm/asm.h> 13#include <asm/asmmacro.h> 14#include <asm/irqflags.h> 15#include <asm/mipsregs.h> 16#include <asm/regdef.h> 17#include <asm/stackframe.h> 18#include <asm/isadep.h> 19#include <asm/sysmips.h> 20#include <asm/thread_info.h> 21#include <asm/unistd.h> 22#include <asm/asm-offsets.h> 23 24 .align 5 25NESTED(handle_sys, PT_SIZE, sp) 26 .set noat 27 SAVE_SOME 28 TRACE_IRQS_ON_RELOAD 29 STI 30 .set at 31 32 lw t1, PT_EPC(sp) # skip syscall on return 33 34 addiu t1, 4 # skip to next instruction 35 sw t1, PT_EPC(sp) 36 37 sw a3, PT_R26(sp) # save a3 for syscall restarting 38 39 /* 40 * More than four arguments. Try to deal with it by copying the 41 * stack arguments from the user stack to the kernel stack. 42 * This Sucks (TM). 43 */ 44 lw t0, PT_R29(sp) # get old user stack pointer 45 46 /* 47 * We intentionally keep the kernel stack a little below the top of 48 * userspace so we don't have to do a slower byte accurate check here. 49 */ 50 addu t4, t0, 32 51 bltz t4, bad_stack # -> sp is bad 52 53 /* 54 * Ok, copy the args from the luser stack to the kernel stack. 55 */ 56 57 .set push 58 .set noreorder 59 .set nomacro 60 61load_a4: user_lw(t5, 16(t0)) # argument #5 from usp 62load_a5: user_lw(t6, 20(t0)) # argument #6 from usp 63load_a6: user_lw(t7, 24(t0)) # argument #7 from usp 64load_a7: user_lw(t8, 28(t0)) # argument #8 from usp 65loads_done: 66 67 sw t5, 16(sp) # argument #5 to ksp 68 sw t6, 20(sp) # argument #6 to ksp 69 sw t7, 24(sp) # argument #7 to ksp 70 sw t8, 28(sp) # argument #8 to ksp 71 .set pop 72 73 .section __ex_table,"a" 74 PTR_WD load_a4, bad_stack_a4 75 PTR_WD load_a5, bad_stack_a5 76 PTR_WD load_a6, bad_stack_a6 77 PTR_WD load_a7, bad_stack_a7 78 .previous 79 80 /* 81 * syscall number is in v0 unless we called syscall(__NR_###) 82 * where the real syscall number is in a0 83 */ 84 subu t2, v0, __NR_O32_Linux 85 bnez t2, 1f /* __NR_syscall at offset 0 */ 86 LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number 87 b 2f 881: 89 LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number 902: 91 92 lw t0, TI_FLAGS($28) # syscall tracing enabled? 93 li t1, _TIF_WORK_SYSCALL_ENTRY 94 and t0, t1 95 bnez t0, syscall_trace_entry # -> yes 96syscall_common: 97 subu v0, v0, __NR_O32_Linux # check syscall number 98 sltiu t0, v0, __NR_O32_Linux_syscalls 99 beqz t0, illegal_syscall 100 101 sll t0, v0, 2 102 la t1, sys_call_table 103 addu t1, t0 104 lw t2, (t1) # syscall routine 105 106 beqz t2, illegal_syscall 107 108 jalr t2 # Do The Real Thing (TM) 109 110 li t0, -EMAXERRNO - 1 # error? 111 sltu t0, t0, v0 112 sw t0, PT_R7(sp) # set error flag 113 beqz t0, 1f 114 115 lw t1, PT_R2(sp) # syscall number 116 negu v0 # error 117 sw t1, PT_R0(sp) # save it for syscall restarting 1181: sw v0, PT_R2(sp) # result 119 120o32_syscall_exit: 121 j syscall_exit_partial 122 123/* ------------------------------------------------------------------------ */ 124 125syscall_trace_entry: 126 SAVE_STATIC 127 move a0, sp 128 129 jal syscall_trace_enter 130 131 bltz v0, 1f # seccomp failed? Skip syscall 132 133 RESTORE_STATIC 134 lw v0, PT_R2(sp) # Restore syscall (maybe modified) 135 lw a0, PT_R4(sp) # Restore argument registers 136 lw a1, PT_R5(sp) 137 lw a2, PT_R6(sp) 138 lw a3, PT_R7(sp) 139 j syscall_common 140 1411: j syscall_exit 142 143/* ------------------------------------------------------------------------ */ 144 145 /* 146 * Our open-coded access area sanity test for the stack pointer 147 * failed. We probably should handle this case a bit more drastic. 148 */ 149bad_stack: 150 li v0, EFAULT 151 sw v0, PT_R2(sp) 152 li t0, 1 # set error flag 153 sw t0, PT_R7(sp) 154 j o32_syscall_exit 155 156bad_stack_a4: 157 li t5, 0 158 b load_a5 159 160bad_stack_a5: 161 li t6, 0 162 b load_a6 163 164bad_stack_a6: 165 li t7, 0 166 b load_a7 167 168bad_stack_a7: 169 li t8, 0 170 b loads_done 171 172 /* 173 * The system call does not exist in this kernel 174 */ 175illegal_syscall: 176 li v0, ENOSYS # error 177 sw v0, PT_R2(sp) 178 li t0, 1 # set error flag 179 sw t0, PT_R7(sp) 180 j o32_syscall_exit 181 END(handle_sys) 182 183 LEAF(sys_syscall) 184 subu t0, a0, __NR_O32_Linux # check syscall number 185 sltiu v0, t0, __NR_O32_Linux_syscalls 186 beqz t0, einval # do not recurse 187 sll t1, t0, 2 188 beqz v0, einval 189 lw t2, sys_call_table(t1) # syscall routine 190 191 move a0, a1 # shift argument registers 192 move a1, a2 193 move a2, a3 194 lw a3, 16(sp) 195 lw t4, 20(sp) 196 lw t5, 24(sp) 197 lw t6, 28(sp) 198 sw t4, 16(sp) 199 sw t5, 20(sp) 200 sw t6, 24(sp) 201 jr t2 202 /* Unreached */ 203 204einval: li v0, -ENOSYS 205 jr ra 206 END(sys_syscall) 207 208#ifdef CONFIG_MIPS_MT_FPAFF 209 /* 210 * For FPU affinity scheduling on MIPS MT processors, we need to 211 * intercept sys_sched_xxxaffinity() calls until we get a proper hook 212 * in kernel/sched/core.c. Considered only temporary we only support 213 * these hooks for the 32-bit kernel - there is no MIPS64 MT processor 214 * atm. 215 */ 216#define sys_sched_setaffinity mipsmt_sys_sched_setaffinity 217#define sys_sched_getaffinity mipsmt_sys_sched_getaffinity 218#endif /* CONFIG_MIPS_MT_FPAFF */ 219 220#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native) 221#define __SYSCALL(nr, entry) PTR_WD entry 222 .align 2 223 .type sys_call_table, @object 224EXPORT(sys_call_table) 225#include <asm/syscall_table_o32.h> 226