scall32-o32.S 5.1 KB

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