entry.S 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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. mov.l @r15+,r15
  222. rte
  223. nop
  224. .align 2
  225. 1: .long gdb_vbr_vector
  226. #endif /* CONFIG_SH_STANDARD_BIOS */
  227. ENTRY(address_error_trap_handler)
  228. mov r15,r4 ! regs
  229. mov #OFF_PC,r0
  230. mov.l @(r0,r15),r6 ! pc
  231. mov.l 1f,r0
  232. jmp @r0
  233. mov #0,r5 ! writeaccess is unknown
  234. .align 2
  235. 1: .long do_address_error
  236. restore_all:
  237. stc sr,r0
  238. or #0xf0,r0
  239. ldc r0,sr ! all interrupt block (same BL = 1)
  240. ! restore special register
  241. ! overlap exception frame
  242. mov r15,r0
  243. add #17*4,r0
  244. lds.l @r0+,pr
  245. add #4,r0
  246. ldc.l @r0+,gbr
  247. lds.l @r0+,mach
  248. lds.l @r0+,macl
  249. mov r15,r0
  250. mov.l $cpu_mode,r2
  251. mov #OFF_SR,r3
  252. mov.l @(r0,r3),r1
  253. mov.l __md_bit,r3
  254. and r1,r3 ! copy MD bit
  255. mov.l r3,@r2
  256. shll2 r1 ! clear MD bit
  257. shlr2 r1
  258. mov.l @(OFF_SP,r0),r2
  259. add #-8,r2
  260. mov.l r2,@(OFF_SP,r0) ! point exception frame top
  261. mov.l r1,@(4,r2) ! set sr
  262. mov #OFF_PC,r3
  263. mov.l @(r0,r3),r1
  264. mov.l r1,@r2 ! set pc
  265. get_current_thread_info r0, r1
  266. mov.l $current_thread_info,r1
  267. mov.l r0,@r1
  268. mov.l @r15+,r0
  269. mov.l @r15+,r1
  270. mov.l @r15+,r2
  271. mov.l @r15+,r3
  272. mov.l @r15+,r4
  273. mov.l @r15+,r5
  274. mov.l @r15+,r6
  275. mov.l @r15+,r7
  276. mov.l @r15+,r8
  277. mov.l @r15+,r9
  278. mov.l @r15+,r10
  279. mov.l @r15+,r11
  280. mov.l @r15+,r12
  281. mov.l @r15+,r13
  282. mov.l @r15+,r14
  283. mov.l @r15,r15
  284. rte
  285. nop
  286. .align 2
  287. __md_bit:
  288. .long 0x40000000
  289. $current_thread_info:
  290. .long __current_thread_info
  291. $cpu_mode:
  292. .long __cpu_mode
  293. ! common exception handler
  294. #include "../../entry-common.S"
  295. .data
  296. ! cpu operation mode
  297. ! bit30 = MD (compatible SH3/4)
  298. __cpu_mode:
  299. .long 0x40000000
  300. .section .bss
  301. __current_thread_info:
  302. .long 0
  303. ENTRY(exception_handling_table)
  304. .space 4*32