entry.S 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. mov.l 4f,r8
  149. mov r9,r4
  150. shll2 r9
  151. add r9,r8
  152. mov.l @r8,r8
  153. mov #0,r9
  154. cmp/eq r9,r8
  155. bf 3f
  156. mov.l 8f,r8 ! unhandled exception
  157. 3:
  158. mov.l 5f,r10
  159. jmp @r8
  160. lds r10,pr
  161. interrupt_entry:
  162. mov r9,r4
  163. mov r15,r5
  164. mov.l 6f,r9
  165. mov.l 7f,r8
  166. jmp @r8
  167. lds r9,pr
  168. .align 2
  169. 4: .long exception_handling_table
  170. 5: .long ret_from_exception
  171. 6: .long ret_from_irq
  172. 7: .long do_IRQ
  173. 8: .long do_exception_error
  174. trap_entry:
  175. mov #0x30,r8
  176. cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall
  177. bt 1f
  178. add #-0x10,r9 ! convert SH2 to SH3/4 ABI
  179. 1:
  180. shll2 r9 ! TRA
  181. mov #OFF_TRA,r8
  182. add r15,r8
  183. mov.l r9,@r8
  184. mov r9,r8
  185. #ifdef CONFIG_TRACE_IRQFLAGS
  186. mov.l 2f, r9
  187. jsr @r9
  188. nop
  189. #endif
  190. sti
  191. bra system_call
  192. nop
  193. .align 2
  194. #ifdef CONFIG_TRACE_IRQFLAGS
  195. 2: .long trace_hardirqs_on
  196. #endif
  197. #if defined(CONFIG_SH_STANDARD_BIOS)
  198. /* Unwind the stack and jmp to the debug entry */
  199. ENTRY(sh_bios_handler)
  200. mov r15,r0
  201. add #(22-4)*4-4,r0
  202. ldc.l @r0+,gbr
  203. lds.l @r0+,mach
  204. lds.l @r0+,macl
  205. mov r15,r0
  206. mov.l @(OFF_SP,r0),r1
  207. mov #OFF_SR,r2
  208. mov.l @(r0,r2),r3
  209. mov.l r3,@-r1
  210. mov #OFF_SP,r2
  211. mov.l @(r0,r2),r3
  212. mov.l r3,@-r1
  213. mov r15,r0
  214. add #(22-4)*4-8,r0
  215. mov.l 1f,r2
  216. mov.l @r2,r2
  217. stc sr,r3
  218. mov.l r2,@r0
  219. mov.l r3,@r0
  220. mov.l r1,@(8,r0)
  221. mov.l @r15+, r0
  222. mov.l @r15+, r1
  223. mov.l @r15+, r2
  224. mov.l @r15+, r3
  225. mov.l @r15+, r4
  226. mov.l @r15+, r5
  227. mov.l @r15+, r6
  228. mov.l @r15+, r7
  229. mov.l @r15+, r8
  230. mov.l @r15+, r9
  231. mov.l @r15+, r10
  232. mov.l @r15+, r11
  233. mov.l @r15+, r12
  234. mov.l @r15+, r13
  235. mov.l @r15+, r14
  236. add #8,r15
  237. lds.l @r15+, pr
  238. rte
  239. mov.l @r15+,r15
  240. .align 2
  241. 1: .long gdb_vbr_vector
  242. #endif /* CONFIG_SH_STANDARD_BIOS */
  243. ENTRY(address_error_handler)
  244. mov r15,r4 ! regs
  245. add #4,r4
  246. mov #OFF_PC,r0
  247. mov.l @(r0,r15),r6 ! pc
  248. mov.l 1f,r0
  249. jmp @r0
  250. mov #0,r5 ! writeaccess is unknown
  251. .align 2
  252. 1: .long do_address_error
  253. restore_all:
  254. cli
  255. #ifdef CONFIG_TRACE_IRQFLAGS
  256. mov.l 1f, r0
  257. jsr @r0
  258. nop
  259. #endif
  260. mov r15,r0
  261. mov.l $cpu_mode,r2
  262. mov #OFF_SR,r3
  263. mov.l @(r0,r3),r1
  264. mov.l r1,@r2
  265. shll2 r1 ! clear MD bit
  266. shlr2 r1
  267. mov.l @(OFF_SP,r0),r2
  268. add #-8,r2
  269. mov.l r2,@(OFF_SP,r0) ! point exception frame top
  270. mov.l r1,@(4,r2) ! set sr
  271. mov #OFF_PC,r3
  272. mov.l @(r0,r3),r1
  273. mov.l r1,@r2 ! set pc
  274. add #4*16+4,r0
  275. lds.l @r0+,pr
  276. add #4,r0 ! skip sr
  277. ldc.l @r0+,gbr
  278. lds.l @r0+,mach
  279. lds.l @r0+,macl
  280. get_current_thread_info r0, r1
  281. mov.l $current_thread_info,r1
  282. mov.l r0,@r1
  283. mov.l @r15+,r0
  284. mov.l @r15+,r1
  285. mov.l @r15+,r2
  286. mov.l @r15+,r3
  287. mov.l @r15+,r4
  288. mov.l @r15+,r5
  289. mov.l @r15+,r6
  290. mov.l @r15+,r7
  291. mov.l @r15+,r8
  292. mov.l @r15+,r9
  293. mov.l @r15+,r10
  294. mov.l @r15+,r11
  295. mov.l @r15+,r12
  296. mov.l @r15+,r13
  297. mov.l @r15+,r14
  298. mov.l @r15,r15
  299. rte
  300. nop
  301. .align 2
  302. #ifdef CONFIG_TRACE_IRQFLAGS
  303. 1: .long trace_hardirqs_off
  304. #endif
  305. $current_thread_info:
  306. .long __current_thread_info
  307. $cpu_mode:
  308. .long __cpu_mode
  309. ! common exception handler
  310. #include "../../entry-common.S"
  311. .data
  312. ! cpu operation mode
  313. ! bit30 = MD (compatible SH3/4)
  314. __cpu_mode:
  315. .long 0x40000000
  316. .section .bss
  317. __current_thread_info:
  318. .long 0
  319. ENTRY(exception_handling_table)
  320. .space 4*32