0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/errno.h>
0017 #include <asm/asm.h>
0018 #include <asm/asmmacro.h>
0019 #include <asm/irqflags.h>
0020 #include <asm/mipsregs.h>
0021 #include <asm/regdef.h>
0022 #include <asm/stackframe.h>
0023 #include <asm/thread_info.h>
0024 #include <asm/unistd.h>
0025 #include <asm/sysmips.h>
0026
0027 .align 5
0028 NESTED(handle_sys, PT_SIZE, sp)
0029 .set noat
0030 SAVE_SOME
0031 TRACE_IRQS_ON_RELOAD
0032 STI
0033 .set at
0034 ld t1, PT_EPC(sp) # skip syscall on return
0035
0036 dsubu t0, v0, __NR_O32_Linux # check syscall number
0037 sltiu t0, t0, __NR_O32_Linux_syscalls
0038 daddiu t1, 4 # skip to next instruction
0039 sd t1, PT_EPC(sp)
0040 beqz t0, not_o32_scall
0041 #if 0
0042 SAVE_ALL
0043 move a1, v0
0044 ASM_PRINT("Scall %ld\n")
0045 RESTORE_ALL
0046 #endif
0047
0048
0049
0050 sll a0, a0, 0
0051 sll a1, a1, 0
0052 sll a2, a2, 0
0053 sll a3, a3, 0
0054
0055 sd a3, PT_R26(sp) # save a3 for syscall restarting
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 ld t0, PT_R29(sp) # get old user stack pointer
0066 daddu t1, t0, 32
0067 bltz t1, bad_stack
0068
0069 load_a4: lw a4, 16(t0) # argument #5 from usp
0070 load_a5: lw a5, 20(t0) # argument #6 from usp
0071 load_a6: lw a6, 24(t0) # argument #7 from usp
0072 load_a7: lw a7, 28(t0) # argument #8 from usp
0073 loads_done:
0074
0075 .section __ex_table,"a"
0076 PTR_WD load_a4, bad_stack_a4
0077 PTR_WD load_a5, bad_stack_a5
0078 PTR_WD load_a6, bad_stack_a6
0079 PTR_WD load_a7, bad_stack_a7
0080 .previous
0081
0082 li t1, _TIF_WORK_SYSCALL_ENTRY
0083 LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
0084 and t0, t1, t0
0085 bnez t0, trace_a_syscall
0086
0087 syscall_common:
0088 dsll t0, v0, 3 # offset into table
0089 ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
0090
0091 jalr t2 # Do The Real Thing (TM)
0092
0093 li t0, -EMAXERRNO - 1 # error?
0094 sltu t0, t0, v0
0095 sd t0, PT_R7(sp) # set error flag
0096 beqz t0, 1f
0097
0098 ld t1, PT_R2(sp) # syscall number
0099 dnegu v0 # error
0100 sd t1, PT_R0(sp) # save it for syscall restarting
0101 1: sd v0, PT_R2(sp) # result
0102
0103 o32_syscall_exit:
0104 j syscall_exit_partial
0105
0106
0107
0108 trace_a_syscall:
0109 SAVE_STATIC
0110 sd a4, PT_R8(sp) # Save argument registers
0111 sd a5, PT_R9(sp)
0112 sd a6, PT_R10(sp)
0113 sd a7, PT_R11(sp) # For indirect syscalls
0114
0115 move a0, sp
0116
0117
0118
0119
0120
0121
0122
0123 .set push
0124 .set reorder
0125 subu t1, v0, __NR_O32_Linux
0126 move a1, v0
0127 bnez t1, 1f
0128 ld a1, PT_R4(sp)
0129 .set pop
0130
0131 1: jal syscall_trace_enter
0132
0133 bltz v0, 1f # seccomp failed? Skip syscall
0134
0135 RESTORE_STATIC
0136 ld v0, PT_R2(sp) # Restore syscall (maybe modified)
0137 ld a0, PT_R4(sp) # Restore argument registers
0138 ld a1, PT_R5(sp)
0139 ld a2, PT_R6(sp)
0140 ld a3, PT_R7(sp)
0141 ld a4, PT_R8(sp)
0142 ld a5, PT_R9(sp)
0143 ld a6, PT_R10(sp)
0144 ld a7, PT_R11(sp) # For indirect syscalls
0145
0146 dsubu t0, v0, __NR_O32_Linux # check (new) syscall number
0147 sltiu t0, t0, __NR_O32_Linux_syscalls
0148 beqz t0, not_o32_scall
0149
0150 j syscall_common
0151
0152 1: j syscall_exit
0153
0154
0155
0156
0157
0158
0159 bad_stack:
0160 li v0, EFAULT
0161 sd v0, PT_R2(sp)
0162 li t0, 1 # set error flag
0163 sd t0, PT_R7(sp)
0164 j o32_syscall_exit
0165
0166 bad_stack_a4:
0167 li a4, 0
0168 b load_a5
0169
0170 bad_stack_a5:
0171 li a5, 0
0172 b load_a6
0173
0174 bad_stack_a6:
0175 li a6, 0
0176 b load_a7
0177
0178 bad_stack_a7:
0179 li a7, 0
0180 b loads_done
0181
0182 not_o32_scall:
0183
0184
0185
0186
0187 #ifdef CONFIG_MIPS32_N32
0188 j handle_sysn32
0189 #else
0190 j handle_sys64
0191 #endif
0192 END(handle_sys)
0193
0194 LEAF(sys32_syscall)
0195 subu t0, a0, __NR_O32_Linux # check syscall number
0196 sltiu v0, t0, __NR_O32_Linux_syscalls
0197 beqz t0, einval # do not recurse
0198 dsll t1, t0, 3
0199 beqz v0, einval
0200 ld t2, sys32_call_table(t1) # syscall routine
0201
0202 move a0, a1 # shift argument registers
0203 move a1, a2
0204 move a2, a3
0205 move a3, a4
0206 move a4, a5
0207 move a5, a6
0208 move a6, a7
0209 jr t2
0210
0211
0212 einval: li v0, -ENOSYS
0213 jr ra
0214 END(sys32_syscall)
0215
0216 #define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, compat)
0217 #define __SYSCALL(nr, entry) PTR_WD entry
0218 .align 3
0219 .type sys32_call_table,@object
0220 EXPORT(sys32_call_table)
0221 #include <asm/syscall_table_o32.h>