entry-common.S 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
  2. *
  3. * linux/arch/sh/entry.S
  4. *
  5. * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
  6. * Copyright (C) 2003 Paul Mundt
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. *
  12. */
  13. ! NOTE:
  14. ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
  15. ! to be jumped is too far, but it causes illegal slot exception.
  16. /*
  17. * entry.S contains the system-call and fault low-level handling routines.
  18. * This also contains the timer-interrupt handler, as well as all interrupts
  19. * and faults that can result in a task-switch.
  20. *
  21. * NOTE: This code handles signal-recognition, which happens every time
  22. * after a timer-interrupt and after each system call.
  23. *
  24. * NOTE: This code uses a convention that instructions in the delay slot
  25. * of a transfer-control instruction are indented by an extra space, thus:
  26. *
  27. * jmp @k0 ! control-transfer instruction
  28. * ldc k1, ssr ! delay slot
  29. *
  30. * Stack layout in 'ret_from_syscall':
  31. * ptrace needs to have all regs on the stack.
  32. * if the order here is changed, it needs to be
  33. * updated in ptrace.c and ptrace.h
  34. *
  35. * r0
  36. * ...
  37. * r15 = stack pointer
  38. * spc
  39. * pr
  40. * ssr
  41. * gbr
  42. * mach
  43. * macl
  44. * syscall #
  45. *
  46. */
  47. #if defined(CONFIG_PREEMPT)
  48. # define preempt_stop() cli
  49. #else
  50. # define preempt_stop()
  51. # define resume_kernel __restore_all
  52. #endif
  53. #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
  54. ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
  55. ! If both are configured, handle the debug traps (breakpoints) in SW,
  56. ! but still allow BIOS traps to FW.
  57. .align 2
  58. debug_kernel:
  59. #if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
  60. /* Force BIOS call to FW (debug_trap put TRA in r8) */
  61. mov r8,r0
  62. shlr2 r0
  63. cmp/eq #0x3f,r0
  64. bt debug_kernel_fw
  65. #endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
  66. debug_enter:
  67. #if defined(CONFIG_SH_KGDB)
  68. /* Jump to kgdb, pass stacked regs as arg */
  69. debug_kernel_sw:
  70. mov.l 3f, r0
  71. jmp @r0
  72. mov r15, r4
  73. .align 2
  74. 3: .long kgdb_handle_exception
  75. #endif /* CONFIG_SH_KGDB */
  76. #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
  77. .align 2
  78. debug_trap:
  79. #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
  80. mov #OFF_SR, r0
  81. mov.l @(r0,r15), r0 ! get status register
  82. shll r0
  83. shll r0 ! kernel space?
  84. bt/s debug_kernel
  85. #endif
  86. mov.l @r15, r0 ! Restore R0 value
  87. mov.l 1f, r8
  88. jmp @r8
  89. nop
  90. .align 2
  91. ENTRY(exception_error)
  92. !
  93. sti
  94. mov.l 2f, r0
  95. jmp @r0
  96. nop
  97. !
  98. .align 2
  99. 1: .long break_point_trap_software
  100. 2: .long do_exception_error
  101. .align 2
  102. ret_from_exception:
  103. preempt_stop()
  104. ENTRY(ret_from_irq)
  105. !
  106. mov #OFF_SR, r0
  107. mov.l @(r0,r15), r0 ! get status register
  108. shll r0
  109. shll r0 ! kernel space?
  110. get_current_thread_info r8, r0
  111. bt resume_kernel ! Yes, it's from kernel, go back soon
  112. #ifdef CONFIG_PREEMPT
  113. bra resume_userspace
  114. nop
  115. ENTRY(resume_kernel)
  116. mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
  117. tst r0, r0
  118. bf noresched
  119. need_resched:
  120. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  121. tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
  122. bt noresched
  123. mov #OFF_SR, r0
  124. mov.l @(r0,r15), r0 ! get status register
  125. and #0xf0, r0 ! interrupts off (exception path)?
  126. cmp/eq #0xf0, r0
  127. bt noresched
  128. mov.l 1f, r0
  129. mov.l r0, @(TI_PRE_COUNT,r8)
  130. sti
  131. mov.l 2f, r0
  132. jsr @r0
  133. nop
  134. mov #0, r0
  135. mov.l r0, @(TI_PRE_COUNT,r8)
  136. cli
  137. bra need_resched
  138. nop
  139. noresched:
  140. bra __restore_all
  141. nop
  142. .align 2
  143. 1: .long PREEMPT_ACTIVE
  144. 2: .long schedule
  145. #endif
  146. ENTRY(resume_userspace)
  147. ! r8: current_thread_info
  148. cli
  149. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  150. tst #_TIF_WORK_MASK, r0
  151. bt/s __restore_all
  152. tst #_TIF_NEED_RESCHED, r0
  153. .align 2
  154. work_pending:
  155. ! r0: current_thread_info->flags
  156. ! r8: current_thread_info
  157. ! t: result of "tst #_TIF_NEED_RESCHED, r0"
  158. bf/s work_resched
  159. tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
  160. work_notifysig:
  161. bt/s __restore_all
  162. mov r15, r4
  163. mov r12, r5 ! set arg1(save_r0)
  164. mov r0, r6
  165. mov.l 2f, r1
  166. mov.l 3f, r0
  167. jmp @r1
  168. lds r0, pr
  169. work_resched:
  170. #ifndef CONFIG_PREEMPT
  171. ! gUSA handling
  172. mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
  173. mov r0, r1
  174. shll r0
  175. bf/s 1f
  176. shll r0
  177. bf/s 1f
  178. mov #OFF_PC, r0
  179. ! SP >= 0xc0000000 : gUSA mark
  180. mov.l @(r0,r15), r2 ! get user space PC (program counter)
  181. mov.l @(OFF_R0,r15), r3 ! end point
  182. cmp/hs r3, r2 ! r2 >= r3?
  183. bt 1f
  184. add r3, r1 ! rewind point #2
  185. mov.l r1, @(r0,r15) ! reset PC to rewind point #2
  186. !
  187. 1:
  188. #endif
  189. mov.l 1f, r1
  190. jsr @r1 ! schedule
  191. nop
  192. cli
  193. !
  194. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  195. tst #_TIF_WORK_MASK, r0
  196. bt __restore_all
  197. bra work_pending
  198. tst #_TIF_NEED_RESCHED, r0
  199. .align 2
  200. 1: .long schedule
  201. 2: .long do_notify_resume
  202. 3: .long restore_all
  203. .align 2
  204. syscall_exit_work:
  205. ! r0: current_thread_info->flags
  206. ! r8: current_thread_info
  207. tst #_TIF_SYSCALL_TRACE, r0
  208. bt/s work_pending
  209. tst #_TIF_NEED_RESCHED, r0
  210. sti
  211. ! XXX setup arguments...
  212. mov.l 4f, r0 ! do_syscall_trace
  213. jsr @r0
  214. nop
  215. bra resume_userspace
  216. nop
  217. .align 2
  218. syscall_trace_entry:
  219. ! Yes it is traced.
  220. ! XXX setup arguments...
  221. mov.l 4f, r11 ! Call do_syscall_trace which notifies
  222. jsr @r11 ! superior (will chomp R[0-7])
  223. nop
  224. ! Reload R0-R4 from kernel stack, where the
  225. ! parent may have modified them using
  226. ! ptrace(POKEUSR). (Note that R0-R2 are
  227. ! used by the system call handler directly
  228. ! from the kernel stack anyway, so don't need
  229. ! to be reloaded here.) This allows the parent
  230. ! to rewrite system calls and args on the fly.
  231. mov.l @(OFF_R4,r15), r4 ! arg0
  232. mov.l @(OFF_R5,r15), r5
  233. mov.l @(OFF_R6,r15), r6
  234. mov.l @(OFF_R7,r15), r7 ! arg3
  235. mov.l @(OFF_R3,r15), r3 ! syscall_nr
  236. !
  237. mov.l 2f, r10 ! Number of syscalls
  238. cmp/hs r10, r3
  239. bf syscall_call
  240. mov #-ENOSYS, r0
  241. bra syscall_exit
  242. mov.l r0, @(OFF_R0,r15) ! Return value
  243. __restore_all:
  244. mov.l 1f,r0
  245. jmp @r0
  246. nop
  247. .align 2
  248. 1: .long restore_all
  249. .align 2
  250. not_syscall_tra:
  251. bra debug_trap
  252. nop
  253. .align 2
  254. syscall_badsys: ! Bad syscall number
  255. mov #-ENOSYS, r0
  256. bra resume_userspace
  257. mov.l r0, @(OFF_R0,r15) ! Return value
  258. /*
  259. * Syscall interface:
  260. *
  261. * Syscall #: R3
  262. * Arguments #0 to #3: R4--R7
  263. * Arguments #4 to #6: R0, R1, R2
  264. * TRA: (number of arguments + 0x10) x 4
  265. *
  266. * This code also handles delegating other traps to the BIOS/gdb stub
  267. * according to:
  268. *
  269. * Trap number
  270. * (TRA>>2) Purpose
  271. * -------- -------
  272. * 0x0-0xf old syscall ABI
  273. * 0x10-0x1f new syscall ABI
  274. * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
  275. *
  276. * Note: When we're first called, the TRA value must be shifted
  277. * right 2 bits in order to get the value that was used as the "trapa"
  278. * argument.
  279. */
  280. .align 2
  281. .globl ret_from_fork
  282. ret_from_fork:
  283. mov.l 1f, r8
  284. jsr @r8
  285. mov r0, r4
  286. bra syscall_exit
  287. nop
  288. .align 2
  289. 1: .long schedule_tail
  290. !
  291. ENTRY(system_call)
  292. #if !defined(CONFIG_CPU_SH2)
  293. mov.l 1f, r9
  294. mov.l @r9, r8 ! Read from TRA (Trap Address) Register
  295. #endif
  296. !
  297. ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
  298. mov #0x7f, r9
  299. cmp/hi r9, r8
  300. bt/s not_syscall_tra
  301. mov #OFF_TRA, r9
  302. add r15, r9
  303. mov.l r8, @r9 ! set TRA value to tra
  304. sti
  305. !
  306. get_current_thread_info r8, r10
  307. mov.l @(TI_FLAGS,r8), r8
  308. mov #_TIF_SYSCALL_TRACE, r10
  309. tst r10, r8
  310. bf syscall_trace_entry
  311. !
  312. mov.l 2f, r8 ! Number of syscalls
  313. cmp/hs r8, r3
  314. bt syscall_badsys
  315. !
  316. syscall_call:
  317. shll2 r3 ! x4
  318. mov.l 3f, r8 ! Load the address of sys_call_table
  319. add r8, r3
  320. mov.l @r3, r8
  321. jsr @r8 ! jump to specific syscall handler
  322. nop
  323. mov.l @(OFF_R0,r15), r12 ! save r0
  324. mov.l r0, @(OFF_R0,r15) ! save the return value
  325. !
  326. syscall_exit:
  327. cli
  328. !
  329. get_current_thread_info r8, r0
  330. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  331. tst #_TIF_ALLWORK_MASK, r0
  332. bf syscall_exit_work
  333. bra __restore_all
  334. nop
  335. .align 2
  336. #if !defined(CONFIG_CPU_SH2)
  337. 1: .long TRA
  338. #endif
  339. 2: .long NR_syscalls
  340. 3: .long sys_call_table
  341. 4: .long do_syscall_trace