entry-common.S 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /* SPDX-License-Identifier: GPL-2.0
  2. *
  3. * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
  4. * Copyright (C) 2003 - 2008 Paul Mundt
  5. */
  6. ! NOTE:
  7. ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
  8. ! to be jumped is too far, but it causes illegal slot exception.
  9. /*
  10. * entry.S contains the system-call and fault low-level handling routines.
  11. * This also contains the timer-interrupt handler, as well as all interrupts
  12. * and faults that can result in a task-switch.
  13. *
  14. * NOTE: This code handles signal-recognition, which happens every time
  15. * after a timer-interrupt and after each system call.
  16. *
  17. * NOTE: This code uses a convention that instructions in the delay slot
  18. * of a transfer-control instruction are indented by an extra space, thus:
  19. *
  20. * jmp @k0 ! control-transfer instruction
  21. * ldc k1, ssr ! delay slot
  22. *
  23. * Stack layout in 'ret_from_syscall':
  24. * ptrace needs to have all regs on the stack.
  25. * if the order here is changed, it needs to be
  26. * updated in ptrace.c and ptrace.h
  27. *
  28. * r0
  29. * ...
  30. * r15 = stack pointer
  31. * spc
  32. * pr
  33. * ssr
  34. * gbr
  35. * mach
  36. * macl
  37. * syscall #
  38. *
  39. */
  40. #include <asm/dwarf.h>
  41. #if defined(CONFIG_PREEMPTION)
  42. # define preempt_stop() cli ; TRACE_IRQS_OFF
  43. #else
  44. # define preempt_stop()
  45. # define resume_kernel __restore_all
  46. #endif
  47. .align 2
  48. ENTRY(exception_error)
  49. !
  50. TRACE_IRQS_ON
  51. sti
  52. mov.l 1f, r0
  53. jmp @r0
  54. nop
  55. .align 2
  56. 1: .long do_exception_error
  57. .align 2
  58. ret_from_exception:
  59. CFI_STARTPROC simple
  60. CFI_DEF_CFA r14, 0
  61. CFI_REL_OFFSET 17, 64
  62. CFI_REL_OFFSET 15, 60
  63. CFI_REL_OFFSET 14, 56
  64. CFI_REL_OFFSET 13, 52
  65. CFI_REL_OFFSET 12, 48
  66. CFI_REL_OFFSET 11, 44
  67. CFI_REL_OFFSET 10, 40
  68. CFI_REL_OFFSET 9, 36
  69. CFI_REL_OFFSET 8, 32
  70. preempt_stop()
  71. ENTRY(ret_from_irq)
  72. !
  73. mov #OFF_SR, r0
  74. mov.l @(r0,r15), r0 ! get status register
  75. shll r0
  76. shll r0 ! kernel space?
  77. get_current_thread_info r8, r0
  78. bt resume_kernel ! Yes, it's from kernel, go back soon
  79. #ifdef CONFIG_PREEMPTION
  80. bra resume_userspace
  81. nop
  82. ENTRY(resume_kernel)
  83. cli
  84. TRACE_IRQS_OFF
  85. mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
  86. tst r0, r0
  87. bf noresched
  88. need_resched:
  89. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  90. tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
  91. bt noresched
  92. mov #OFF_SR, r0
  93. mov.l @(r0,r15), r0 ! get status register
  94. shlr r0
  95. and #(0xf0>>1), r0 ! interrupts off (exception path)?
  96. cmp/eq #(0xf0>>1), r0
  97. bt noresched
  98. mov.l 1f, r0
  99. jsr @r0 ! call preempt_schedule_irq
  100. nop
  101. bra need_resched
  102. nop
  103. noresched:
  104. bra __restore_all
  105. nop
  106. .align 2
  107. 1: .long preempt_schedule_irq
  108. #endif
  109. ENTRY(resume_userspace)
  110. ! r8: current_thread_info
  111. cli
  112. TRACE_IRQS_OFF
  113. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  114. tst #(_TIF_WORK_MASK & 0xff), r0
  115. bt/s __restore_all
  116. tst #_TIF_NEED_RESCHED, r0
  117. .align 2
  118. work_pending:
  119. ! r0: current_thread_info->flags
  120. ! r8: current_thread_info
  121. ! t: result of "tst #_TIF_NEED_RESCHED, r0"
  122. bf/s work_resched
  123. tst #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME), r0
  124. work_notifysig:
  125. bt/s __restore_all
  126. mov r15, r4
  127. mov r12, r5 ! set arg1(save_r0)
  128. mov r0, r6
  129. sti
  130. mov.l 2f, r1
  131. mov.l 3f, r0
  132. jmp @r1
  133. lds r0, pr
  134. work_resched:
  135. mov.l 1f, r1
  136. jsr @r1 ! schedule
  137. nop
  138. cli
  139. TRACE_IRQS_OFF
  140. !
  141. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  142. tst #(_TIF_WORK_MASK & 0xff), r0
  143. bt __restore_all
  144. bra work_pending
  145. tst #_TIF_NEED_RESCHED, r0
  146. .align 2
  147. 1: .long schedule
  148. 2: .long do_notify_resume
  149. 3: .long resume_userspace
  150. .align 2
  151. syscall_exit_work:
  152. ! r0: current_thread_info->flags
  153. ! r8: current_thread_info
  154. tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0
  155. bt/s work_pending
  156. tst #_TIF_NEED_RESCHED, r0
  157. TRACE_IRQS_ON
  158. sti
  159. mov r15, r4
  160. mov.l 8f, r0 ! do_syscall_trace_leave
  161. jsr @r0
  162. nop
  163. bra resume_userspace
  164. nop
  165. __restore_all:
  166. mov #OFF_SR, r0
  167. mov.l @(r0,r15), r0 ! get status register
  168. shlr2 r0
  169. and #0x3c, r0
  170. cmp/eq #0x3c, r0
  171. bt 1f
  172. TRACE_IRQS_ON
  173. bra 2f
  174. nop
  175. 1:
  176. TRACE_IRQS_OFF
  177. 2:
  178. mov.l 3f, r0
  179. jmp @r0
  180. nop
  181. .align 2
  182. 3: .long restore_all
  183. .align 2
  184. syscall_badsys: ! Bad syscall number
  185. get_current_thread_info r8, r0
  186. mov #-ENOSYS, r0
  187. bra resume_userspace
  188. mov.l r0, @(OFF_R0,r15) ! Return value
  189. /*
  190. * The main debug trap handler.
  191. *
  192. * r8=TRA (not the trap number!)
  193. *
  194. * Note: This assumes that the trapa value is left in its original
  195. * form (without the shlr2 shift) so the calculation for the jump
  196. * call table offset remains a simple in place mask.
  197. */
  198. debug_trap:
  199. mov r8, r0
  200. and #(0xf << 2), r0
  201. mov.l 1f, r8
  202. add r0, r8
  203. mov.l @r8, r8
  204. jsr @r8
  205. nop
  206. bra ret_from_exception
  207. nop
  208. CFI_ENDPROC
  209. .align 2
  210. 1: .long debug_trap_table
  211. /*
  212. * Syscall interface:
  213. *
  214. * Syscall #: R3
  215. * Arguments #0 to #3: R4--R7
  216. * Arguments #4 to #6: R0, R1, R2
  217. * TRA: See following table.
  218. *
  219. * (TRA>>2) Purpose
  220. * -------- -------
  221. * 0x00-0x0f original SH-3/4 syscall ABI (not in general use).
  222. * 0x10-0x1f general SH-3/4 syscall ABI.
  223. * 0x1f unified SH-2/3/4 syscall ABI (preferred).
  224. * 0x20-0x2f original SH-2 syscall ABI.
  225. * 0x30-0x3f debug traps used by the kernel.
  226. * 0x40-0xff Not supported by all parts, so left unhandled.
  227. *
  228. * For making system calls, any trap number in the range for the
  229. * given cpu model may be used, but the unified trap number 0x1f is
  230. * preferred for compatibility with all models.
  231. *
  232. * The low bits of the trap number were once documented as matching
  233. * the number of arguments, but they were never actually used as such
  234. * by the kernel. SH-2 originally used its own separate trap range
  235. * because several hardware exceptions fell in the range used for the
  236. * SH-3/4 syscall ABI.
  237. *
  238. * This code also handles delegating other traps to the BIOS/gdb stub.
  239. *
  240. * Note: When we're first called, the TRA value must be shifted
  241. * right 2 bits in order to get the value that was used as the "trapa"
  242. * argument.
  243. */
  244. .align 2
  245. .globl ret_from_fork
  246. ret_from_fork:
  247. mov.l 1f, r8
  248. jsr @r8
  249. mov r0, r4
  250. bra syscall_exit
  251. nop
  252. .align 2
  253. .globl ret_from_kernel_thread
  254. ret_from_kernel_thread:
  255. mov.l 1f, r8
  256. jsr @r8
  257. mov r0, r4
  258. mov.l @(OFF_R5,r15), r5 ! fn
  259. jsr @r5
  260. mov.l @(OFF_R4,r15), r4 ! arg
  261. bra syscall_exit
  262. nop
  263. .align 2
  264. 1: .long schedule_tail
  265. /*
  266. * The poorly named main trapa decode and dispatch routine, for
  267. * system calls and debug traps through their respective jump tables.
  268. */
  269. ENTRY(system_call)
  270. setup_frame_reg
  271. #if !defined(CONFIG_CPU_SH2)
  272. mov.l 1f, r9
  273. mov.l @r9, r8 ! Read from TRA (Trap Address) Register
  274. #endif
  275. mov #OFF_TRA, r10
  276. add r15, r10
  277. mov.l r8, @r10 ! set TRA value to tra
  278. /*
  279. * Check the trap type
  280. */
  281. mov #((0x20 << 2) - 1), r9
  282. cmp/hi r9, r8
  283. bt/s debug_trap ! it's a debug trap..
  284. nop
  285. TRACE_IRQS_ON
  286. sti
  287. !
  288. get_current_thread_info r8, r10
  289. mov.l @(TI_FLAGS,r8), r8
  290. mov #(_TIF_WORK_SYSCALL_MASK & 0xff), r10
  291. mov #(_TIF_WORK_SYSCALL_MASK >> 8), r9
  292. tst r10, r8
  293. shll8 r9
  294. bf syscall_trace_entry
  295. tst r9, r8
  296. bf syscall_trace_entry
  297. !
  298. mov.l 6f, r8 ! Number of syscalls
  299. cmp/hs r8, r3
  300. bt syscall_badsys
  301. !
  302. syscall_call:
  303. shll2 r3 ! x4
  304. mov.l 3f, r8 ! Load the address of sys_call_table
  305. add r8, r3
  306. mov.l @r3, r8
  307. mov.l @(OFF_R2,r15), r2
  308. mov.l @(OFF_R1,r15), r1
  309. mov.l @(OFF_R0,r15), r0
  310. mov.l r2, @-r15
  311. mov.l r1, @-r15
  312. mov.l r0, @-r15
  313. jsr @r8 ! jump to specific syscall handler
  314. nop
  315. add #12, r15
  316. mov.l @(OFF_R0,r15), r12 ! save r0
  317. mov.l r0, @(OFF_R0,r15) ! save the return value
  318. !
  319. syscall_exit:
  320. cli
  321. TRACE_IRQS_OFF
  322. !
  323. get_current_thread_info r8, r0
  324. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  325. tst #(_TIF_ALLWORK_MASK & 0xff), r0
  326. mov #(_TIF_ALLWORK_MASK >> 8), r1
  327. bf syscall_exit_work
  328. shlr8 r0
  329. tst r0, r1
  330. bf syscall_exit_work
  331. bra __restore_all
  332. nop
  333. .align 2
  334. syscall_trace_entry:
  335. ! Yes it is traced.
  336. mov r15, r4
  337. mov.l 7f, r11 ! Call do_syscall_trace_enter which notifies
  338. jsr @r11 ! superior (will chomp R[0-7])
  339. nop
  340. cmp/eq #-1, r0
  341. bt syscall_exit
  342. ! Reload R0-R4 from kernel stack, where the
  343. ! parent may have modified them using
  344. ! ptrace(POKEUSR). (Note that R0-R2 are
  345. ! reloaded from the kernel stack by syscall_call
  346. ! below, so don't need to be reloaded here.)
  347. ! This allows the parent to rewrite system calls
  348. ! and args on the fly.
  349. mov.l @(OFF_R4,r15), r4 ! arg0
  350. mov.l @(OFF_R5,r15), r5
  351. mov.l @(OFF_R6,r15), r6
  352. mov.l @(OFF_R7,r15), r7 ! arg3
  353. mov.l @(OFF_R3,r15), r3 ! syscall_nr
  354. !
  355. mov.l 6f, r10 ! Number of syscalls
  356. cmp/hs r10, r3
  357. bf syscall_call
  358. mov #-ENOSYS, r0
  359. bra syscall_exit
  360. mov.l r0, @(OFF_R0,r15) ! Return value
  361. .align 2
  362. #if !defined(CONFIG_CPU_SH2)
  363. 1: .long TRA
  364. #endif
  365. 6: .long NR_syscalls
  366. 3: .long sys_call_table
  367. 7: .long do_syscall_trace_enter
  368. 8: .long do_syscall_trace_leave