entry.S 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * arch/sh/kernel/cpu/sh2/entry.S
  3. *
  4. * The SH-2 exception entry
  5. *
  6. * Copyright (C) 2005-2008 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 <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. ! stack
  36. ! r0 <- point sp
  37. ! r1
  38. ! pc
  39. ! sr
  40. ! r0 = temporary
  41. ! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
  42. mov.l r2,@-sp
  43. mov.l r3,@-sp
  44. cli
  45. mov.l $cpu_mode,r2
  46. mov.l @r2,r0
  47. mov.l @(5*4,r15),r3 ! previous SR
  48. or r0,r3 ! set MD
  49. tst r0,r0
  50. bf/s 1f ! previous mode check
  51. mov.l r3,@(5*4,r15) ! update SR
  52. ! switch to kernel mode
  53. mov.l __md_bit,r0
  54. mov.l r0,@r2 ! enter kernel mode
  55. mov.l $current_thread_info,r2
  56. mov.l @r2,r2
  57. mov #(THREAD_SIZE >> 8),r0
  58. shll8 r0
  59. add r2,r0
  60. mov r15,r2 ! r2 = user stack top
  61. mov r0,r15 ! switch kernel stack
  62. mov.l r1,@-r15 ! TRA
  63. sts.l macl, @-r15
  64. sts.l mach, @-r15
  65. stc.l gbr, @-r15
  66. mov.l @(5*4,r2),r0
  67. mov.l r0,@-r15 ! original SR
  68. sts.l pr,@-r15
  69. mov.l @(4*4,r2),r0
  70. mov.l r0,@-r15 ! original PC
  71. mov r2,r3
  72. add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame
  73. mov.l r3,@-r15 ! original SP
  74. mov.l r14,@-r15
  75. mov.l r13,@-r15
  76. mov.l r12,@-r15
  77. mov.l r11,@-r15
  78. mov.l r10,@-r15
  79. mov.l r9,@-r15
  80. mov.l r8,@-r15
  81. mov.l r7,@-r15
  82. mov.l r6,@-r15
  83. mov.l r5,@-r15
  84. mov.l r4,@-r15
  85. mov r1,r9 ! save TRA
  86. mov r2,r8 ! copy user -> kernel stack
  87. mov.l @(0,r8),r3
  88. mov.l r3,@-r15
  89. mov.l @(4,r8),r2
  90. mov.l r2,@-r15
  91. mov.l @(12,r8),r1
  92. mov.l r1,@-r15
  93. mov.l @(8,r8),r0
  94. bra 2f
  95. mov.l r0,@-r15
  96. 1:
  97. ! in kernel exception
  98. mov #(22-4-4-1)*4+4,r0
  99. mov r15,r2
  100. sub r0,r15
  101. mov.l @r2+,r0 ! old R3
  102. mov.l r0,@-r15
  103. mov.l @r2+,r0 ! old R2
  104. mov.l r0,@-r15
  105. mov.l @(4,r2),r0 ! old R1
  106. mov.l r0,@-r15
  107. mov.l @r2,r0 ! old R0
  108. mov.l r0,@-r15
  109. add #8,r2
  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 r1,r9
  135. mov.l @(OFF_R0,r15),r0
  136. mov.l @(OFF_R1,r15),r1
  137. mov.l @(OFF_R2,r15),r2
  138. mov.l @(OFF_R3,r15),r3
  139. 2:
  140. mov #64,r8
  141. cmp/hs r8,r9
  142. bt interrupt_entry ! vec >= 64 is interrupt
  143. mov #32,r8
  144. cmp/hs r8,r9
  145. bt trap_entry ! 64 > vec >= 32 is trap
  146. mov.l 4f,r8
  147. mov r9,r4
  148. shll2 r9
  149. add r9,r8
  150. mov.l @r8,r8 ! exception handler address
  151. tst r8,r8
  152. bf 3f
  153. mov.l 8f,r8 ! unhandled exception
  154. 3:
  155. mov.l 5f,r10
  156. jmp @r8
  157. lds r10,pr
  158. interrupt_entry:
  159. mov r9,r4
  160. mov r15,r5
  161. mov.l 6f,r9
  162. mov.l 7f,r8
  163. jmp @r8
  164. lds r9,pr
  165. .align 2
  166. 4: .long exception_handling_table
  167. 5: .long ret_from_exception
  168. 6: .long ret_from_irq
  169. 7: .long do_IRQ
  170. 8: .long exception_error
  171. trap_entry:
  172. mov #0x30,r8
  173. cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall
  174. bt 1f
  175. add #-0x10,r9 ! convert SH2 to SH3/4 ABI
  176. 1:
  177. shll2 r9 ! TRA
  178. bra system_call ! jump common systemcall entry
  179. mov r9,r8
  180. #if defined(CONFIG_SH_STANDARD_BIOS)
  181. /* Unwind the stack and jmp to the debug entry */
  182. ENTRY(sh_bios_handler)
  183. mov r15,r0
  184. add #(22-4)*4-4,r0
  185. ldc.l @r0+,gbr
  186. lds.l @r0+,mach
  187. lds.l @r0+,macl
  188. mov r15,r0
  189. mov.l @(OFF_SP,r0),r1
  190. mov #OFF_SR,r2
  191. mov.l @(r0,r2),r3
  192. mov.l r3,@-r1
  193. mov #OFF_SP,r2
  194. mov.l @(r0,r2),r3
  195. mov.l r3,@-r1
  196. mov r15,r0
  197. add #(22-4)*4-8,r0
  198. mov.l 1f,r2
  199. mov.l @r2,r2
  200. stc sr,r3
  201. mov.l r2,@r0
  202. mov.l r3,@(4,r0)
  203. mov.l r1,@(8,r0)
  204. mov.l @r15+, r0
  205. mov.l @r15+, r1
  206. mov.l @r15+, r2
  207. mov.l @r15+, r3
  208. mov.l @r15+, r4
  209. mov.l @r15+, r5
  210. mov.l @r15+, r6
  211. mov.l @r15+, r7
  212. mov.l @r15+, r8
  213. mov.l @r15+, r9
  214. mov.l @r15+, r10
  215. mov.l @r15+, r11
  216. mov.l @r15+, r12
  217. mov.l @r15+, r13
  218. mov.l @r15+, r14
  219. add #8,r15
  220. lds.l @r15+, pr
  221. rte
  222. mov.l @r15+,r15
  223. .align 2
  224. 1: .long gdb_vbr_vector
  225. #endif /* CONFIG_SH_STANDARD_BIOS */
  226. ENTRY(address_error_trap_handler)
  227. mov r15,r4 ! regs
  228. mov #OFF_PC,r0
  229. mov.l @(r0,r15),r6 ! pc
  230. mov.l 1f,r0
  231. jmp @r0
  232. mov #0,r5 ! writeaccess is unknown
  233. .align 2
  234. 1: .long do_address_error
  235. restore_all:
  236. stc sr,r0
  237. or #0xf0,r0
  238. ldc r0,sr ! all interrupt block (same BL = 1)
  239. ! restore special register
  240. ! overlap exception frame
  241. mov r15,r0
  242. add #17*4,r0
  243. lds.l @r0+,pr
  244. add #4,r0
  245. ldc.l @r0+,gbr
  246. lds.l @r0+,mach
  247. lds.l @r0+,macl
  248. mov r15,r0
  249. mov.l $cpu_mode,r2
  250. mov #OFF_SR,r3
  251. mov.l @(r0,r3),r1
  252. mov.l __md_bit,r3
  253. and r1,r3 ! copy MD bit
  254. mov.l r3,@r2
  255. shll2 r1 ! clear MD bit
  256. shlr2 r1
  257. mov.l @(OFF_SP,r0),r2
  258. add #-8,r2
  259. mov.l r2,@(OFF_SP,r0) ! point exception frame top
  260. mov.l r1,@(4,r2) ! set sr
  261. mov #OFF_PC,r3
  262. mov.l @(r0,r3),r1
  263. mov.l r1,@r2 ! set pc
  264. get_current_thread_info r0, r1
  265. mov.l $current_thread_info,r1
  266. mov.l r0,@r1
  267. mov.l @r15+,r0
  268. mov.l @r15+,r1
  269. mov.l @r15+,r2
  270. mov.l @r15+,r3
  271. mov.l @r15+,r4
  272. mov.l @r15+,r5
  273. mov.l @r15+,r6
  274. mov.l @r15+,r7
  275. mov.l @r15+,r8
  276. mov.l @r15+,r9
  277. mov.l @r15+,r10
  278. mov.l @r15+,r11
  279. mov.l @r15+,r12
  280. mov.l @r15+,r13
  281. mov.l @r15+,r14
  282. mov.l @r15,r15
  283. rte
  284. nop
  285. .align 2
  286. __md_bit:
  287. .long 0x40000000
  288. $current_thread_info:
  289. .long __current_thread_info
  290. $cpu_mode:
  291. .long __cpu_mode
  292. ! common exception handler
  293. #include "../../entry-common.S"
  294. .data
  295. ! cpu operation mode
  296. ! bit30 = MD (compatible SH3/4)
  297. __cpu_mode:
  298. .long 0x40000000
  299. .section .bss
  300. __current_thread_info:
  301. .long 0
  302. ENTRY(exception_handling_table)
  303. .space 4*32