entry.S 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. * arch/sh/kernel/cpu/sh2/entry.S
  3. *
  4. * The SH-2 exception entry
  5. *
  6. * Copyright (C) 2005,2006 Yoshinori Sato
  7. * Copyright (C) 2005 AXE,Inc.
  8. *
  9. * This file is subject to the terms and conditions of the GNU General Public
  10. * License. See the file "COPYING" in the main directory of this archive
  11. * for more details.
  12. */
  13. #include <linux/linkage.h>
  14. #include <asm/asm-offsets.h>
  15. #include <asm/thread_info.h>
  16. #include <asm/cpu/mmu_context.h>
  17. #include <asm/unistd.h>
  18. #include <asm/errno.h>
  19. #include <asm/page.h>
  20. /* Offsets to the stack */
  21. OFF_R0 = 0 /* Return value. New ABI also arg4 */
  22. OFF_R1 = 4 /* New ABI: arg5 */
  23. OFF_R2 = 8 /* New ABI: arg6 */
  24. OFF_R3 = 12 /* New ABI: syscall_nr */
  25. OFF_R4 = 16 /* New ABI: arg0 */
  26. OFF_R5 = 20 /* New ABI: arg1 */
  27. OFF_R6 = 24 /* New ABI: arg2 */
  28. OFF_R7 = 28 /* New ABI: arg3 */
  29. OFF_SP = (15*4)
  30. OFF_PC = (16*4)
  31. OFF_SR = (16*4+2*4)
  32. OFF_TRA = (16*4+6*4)
  33. #include <asm/entry-macros.S>
  34. ENTRY(exception_handler)
  35. ! already saved r0/r1
  36. mov.l r2,@-sp
  37. mov.l r3,@-sp
  38. mov r0,r1
  39. cli
  40. mov.l $cpu_mode,r2
  41. mov.l @r2,r0
  42. mov.l @(5*4,r15),r3 ! previous SR
  43. shll2 r3 ! set "S" flag
  44. rotl r0 ! T <- "S" flag
  45. rotl r0 ! "S" flag is LSB
  46. rotcr r3 ! T -> r3:b30
  47. shlr r3
  48. shlr r0
  49. bt/s 1f
  50. mov.l r3,@(5*4,r15) ! copy cpu mode to SR
  51. ! switch to kernel mode
  52. mov #1,r0
  53. rotr r0
  54. rotr r0
  55. mov.l r0,@r2 ! enter kernel mode
  56. mov.l $current_thread_info,r2
  57. mov.l @r2,r2
  58. mov #0x20,r0
  59. shll8 r0
  60. add r2,r0
  61. mov r15,r2 ! r2 = user stack top
  62. mov r0,r15 ! switch kernel stack
  63. add #-4,r15 ! dummy
  64. mov.l r1,@-r15 ! TRA
  65. sts.l macl, @-r15
  66. sts.l mach, @-r15
  67. stc.l gbr, @-r15
  68. mov.l @(4*4,r2),r0
  69. mov.l @(5*4,r2),r1
  70. mov.l r1,@-r15 ! original SR
  71. sts.l pr,@-r15
  72. mov.l r0,@-r15 ! original PC
  73. mov r2,r3
  74. add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame
  75. mov.l r3,@-r15 ! original SP
  76. mov.l r14,@-r15
  77. mov.l r13,@-r15
  78. mov.l r12,@-r15
  79. mov.l r11,@-r15
  80. mov.l r10,@-r15
  81. mov.l r9,@-r15
  82. mov.l r8,@-r15
  83. mov.l r7,@-r15
  84. mov.l r6,@-r15
  85. mov.l r5,@-r15
  86. mov.l r4,@-r15
  87. mov r2,r8 ! copy user -> kernel stack
  88. mov.l @r8+,r3
  89. mov.l r3,@-r15
  90. mov.l @r8+,r2
  91. mov.l r2,@-r15
  92. mov.l @r8+,r1
  93. mov.l r1,@-r15
  94. mov.l @r8+,r0
  95. bra 2f
  96. mov.l r0,@-r15
  97. 1:
  98. ! in kernel exception
  99. mov #(22-4-4-1)*4+4,r0
  100. mov r15,r2
  101. sub r0,r15
  102. mov.l @r2+,r0 ! old R3
  103. mov.l r0,@-r15
  104. mov.l @r2+,r0 ! old R2
  105. mov.l r0,@-r15
  106. mov.l @r2+,r0 ! old R1
  107. mov.l r0,@-r15
  108. mov.l @r2+,r0 ! old R0
  109. mov.l r0,@-r15
  110. mov.l @r2+,r3 ! old PC
  111. mov.l @r2+,r0 ! old SR
  112. add #-4,r2 ! exception frame stub (sr)
  113. mov.l r1,@-r2 ! TRA
  114. sts.l macl, @-r2
  115. sts.l mach, @-r2
  116. stc.l gbr, @-r2
  117. mov.l r0,@-r2 ! save old SR
  118. sts.l pr,@-r2
  119. mov.l r3,@-r2 ! save old PC
  120. mov r2,r0
  121. add #8*4,r0
  122. mov.l r0,@-r2 ! save old SP
  123. mov.l r14,@-r2
  124. mov.l r13,@-r2
  125. mov.l r12,@-r2
  126. mov.l r11,@-r2
  127. mov.l r10,@-r2
  128. mov.l r9,@-r2
  129. mov.l r8,@-r2
  130. mov.l r7,@-r2
  131. mov.l r6,@-r2
  132. mov.l r5,@-r2
  133. mov.l r4,@-r2
  134. mov.l @(OFF_R0,r15),r0
  135. mov.l @(OFF_R1,r15),r1
  136. mov.l @(OFF_R2,r15),r2
  137. mov.l @(OFF_R3,r15),r3
  138. 2:
  139. mov #OFF_TRA,r8
  140. add r15,r8
  141. mov.l @r8,r9
  142. mov #64,r8
  143. cmp/hs r8,r9
  144. bt interrupt_entry ! vec >= 64 is interrupt
  145. mov #32,r8
  146. cmp/hs r8,r9
  147. bt trap_entry ! 64 > vec >= 32 is trap
  148. #if defined(CONFIG_SH_FPU)
  149. mov #13,r8
  150. cmp/eq r8,r9
  151. bt 10f ! fpu
  152. nop
  153. #endif
  154. mov.l 4f,r8
  155. mov r9,r4
  156. shll2 r9
  157. add r9,r8
  158. mov.l @r8,r8
  159. mov #0,r9
  160. cmp/eq r9,r8
  161. bf 3f
  162. mov.l 8f,r8 ! unhandled exception
  163. #if defined(CONFIG_SH_FPU)
  164. 10:
  165. mov.l 9f, r8 ! unhandled exception
  166. #endif
  167. 3:
  168. mov.l 5f,r10
  169. jmp @r8
  170. lds r10,pr
  171. interrupt_entry:
  172. mov r9,r4
  173. mov r15,r5
  174. mov.l 6f,r9
  175. mov.l 7f,r8
  176. jmp @r8
  177. lds r9,pr
  178. .align 2
  179. 4: .long exception_handling_table
  180. 5: .long ret_from_exception
  181. 6: .long ret_from_irq
  182. 7: .long do_IRQ
  183. 8: .long do_exception_error
  184. #ifdef CONFIG_SH_FPU
  185. 9: .long fpu_error_trap_handler
  186. #endif
  187. trap_entry:
  188. mov #0x30,r8
  189. cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall
  190. bt 1f
  191. add #-0x10,r9 ! convert SH2 to SH3/4 ABI
  192. 1:
  193. shll2 r9 ! TRA
  194. mov #OFF_TRA,r8
  195. add r15,r8
  196. mov.l r9,@r8
  197. mov r9,r8
  198. #ifdef CONFIG_TRACE_IRQFLAGS
  199. mov.l 2f, r9
  200. jsr @r9
  201. nop
  202. #endif
  203. sti
  204. bra system_call
  205. nop
  206. .align 2
  207. #ifdef CONFIG_TRACE_IRQFLAGS
  208. 2: .long trace_hardirqs_on
  209. #endif
  210. #if defined(CONFIG_SH_STANDARD_BIOS)
  211. /* Unwind the stack and jmp to the debug entry */
  212. ENTRY(sh_bios_handler)
  213. mov r15,r0
  214. add #(22-4)*4-4,r0
  215. ldc.l @r0+,gbr
  216. lds.l @r0+,mach
  217. lds.l @r0+,macl
  218. mov r15,r0
  219. mov.l @(OFF_SP,r0),r1
  220. mov #OFF_SR,r2
  221. mov.l @(r0,r2),r3
  222. mov.l r3,@-r1
  223. mov #OFF_SP,r2
  224. mov.l @(r0,r2),r3
  225. mov.l r3,@-r1
  226. mov r15,r0
  227. add #(22-4)*4-8,r0
  228. mov.l 1f,r2
  229. mov.l @r2,r2
  230. stc sr,r3
  231. mov.l r2,@r0
  232. mov.l r3,@r0
  233. mov.l r1,@(8,r0)
  234. mov.l @r15+, r0
  235. mov.l @r15+, r1
  236. mov.l @r15+, r2
  237. mov.l @r15+, r3
  238. mov.l @r15+, r4
  239. mov.l @r15+, r5
  240. mov.l @r15+, r6
  241. mov.l @r15+, r7
  242. mov.l @r15+, r8
  243. mov.l @r15+, r9
  244. mov.l @r15+, r10
  245. mov.l @r15+, r11
  246. mov.l @r15+, r12
  247. mov.l @r15+, r13
  248. mov.l @r15+, r14
  249. add #8,r15
  250. lds.l @r15+, pr
  251. rte
  252. mov.l @r15+,r15
  253. .align 2
  254. 1: .long gdb_vbr_vector
  255. #endif /* CONFIG_SH_STANDARD_BIOS */
  256. ENTRY(address_error_trap_handler)
  257. mov r15,r4 ! regs
  258. add #4,r4
  259. mov #OFF_PC,r0
  260. mov.l @(r0,r15),r6 ! pc
  261. mov.l 1f,r0
  262. jmp @r0
  263. mov #0,r5 ! writeaccess is unknown
  264. .align 2
  265. 1: .long do_address_error
  266. restore_all:
  267. cli
  268. #ifdef CONFIG_TRACE_IRQFLAGS
  269. mov.l 1f, r0
  270. jsr @r0
  271. nop
  272. #endif
  273. mov r15,r0
  274. mov.l $cpu_mode,r2
  275. mov #OFF_SR,r3
  276. mov.l @(r0,r3),r1
  277. mov.l r1,@r2
  278. shll2 r1 ! clear MD bit
  279. shlr2 r1
  280. mov.l @(OFF_SP,r0),r2
  281. add #-8,r2
  282. mov.l r2,@(OFF_SP,r0) ! point exception frame top
  283. mov.l r1,@(4,r2) ! set sr
  284. mov #OFF_PC,r3
  285. mov.l @(r0,r3),r1
  286. mov.l r1,@r2 ! set pc
  287. add #4*16+4,r0
  288. lds.l @r0+,pr
  289. add #4,r0 ! skip sr
  290. ldc.l @r0+,gbr
  291. lds.l @r0+,mach
  292. lds.l @r0+,macl
  293. get_current_thread_info r0, r1
  294. mov.l $current_thread_info,r1
  295. mov.l r0,@r1
  296. mov.l @r15+,r0
  297. mov.l @r15+,r1
  298. mov.l @r15+,r2
  299. mov.l @r15+,r3
  300. mov.l @r15+,r4
  301. mov.l @r15+,r5
  302. mov.l @r15+,r6
  303. mov.l @r15+,r7
  304. mov.l @r15+,r8
  305. mov.l @r15+,r9
  306. mov.l @r15+,r10
  307. mov.l @r15+,r11
  308. mov.l @r15+,r12
  309. mov.l @r15+,r13
  310. mov.l @r15+,r14
  311. mov.l @r15,r15
  312. rte
  313. nop
  314. .align 2
  315. #ifdef CONFIG_TRACE_IRQFLAGS
  316. 1: .long trace_hardirqs_off
  317. #endif
  318. $current_thread_info:
  319. .long __current_thread_info
  320. $cpu_mode:
  321. .long __cpu_mode
  322. ! common exception handler
  323. #include "../../entry-common.S"
  324. .data
  325. ! cpu operation mode
  326. ! bit30 = MD (compatible SH3/4)
  327. __cpu_mode:
  328. .long 0x40000000
  329. .section .bss
  330. __current_thread_info:
  331. .long 0
  332. ENTRY(exception_handling_table)
  333. .space 4*32