entry.S 5.9 KB

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