/arch/mips/kernel/scall32-o32.S

http://github.com/mirrors/linux · Assembly · 225 lines · 145 code · 37 blank · 43 comment · 2 complexity · ce858a07473050273614e77355020848 MD5 · raw file

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