entry.S 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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. #ifdef CONFIG_SMP
  47. mov.l $cpuid,r3
  48. mov.l @r3,r3
  49. mov.l @r3,r3
  50. shll2 r3
  51. add r3,r2
  52. #endif
  53. mov.l @r2,r0
  54. mov.l @(5*4,r15),r3 ! previous SR
  55. or r0,r3 ! set MD
  56. tst r0,r0
  57. bf/s 1f ! previous mode check
  58. mov.l r3,@(5*4,r15) ! update SR
  59. ! switch to kernel mode
  60. mov.l __md_bit,r0
  61. mov.l r0,@r2 ! enter kernel mode
  62. mov.l $current_thread_info,r2
  63. #ifdef CONFIG_SMP
  64. mov.l $cpuid,r0
  65. mov.l @r0,r0
  66. mov.l @r0,r0
  67. shll2 r0
  68. add r0,r2
  69. #endif
  70. mov.l @r2,r2
  71. mov #(THREAD_SIZE >> 8),r0
  72. shll8 r0
  73. add r2,r0
  74. mov r15,r2 ! r2 = user stack top
  75. mov r0,r15 ! switch kernel stack
  76. mov.l r1,@-r15 ! TRA
  77. sts.l macl, @-r15
  78. sts.l mach, @-r15
  79. stc.l gbr, @-r15
  80. mov.l @(5*4,r2),r0
  81. mov.l r0,@-r15 ! original SR
  82. sts.l pr,@-r15
  83. mov.l @(4*4,r2),r0
  84. mov.l r0,@-r15 ! original PC
  85. mov r2,r3
  86. add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame
  87. mov.l r3,@-r15 ! original SP
  88. mov.l r14,@-r15
  89. mov.l r13,@-r15
  90. mov.l r12,@-r15
  91. mov.l r11,@-r15
  92. mov.l r10,@-r15
  93. mov.l r9,@-r15
  94. mov.l r8,@-r15
  95. mov.l r7,@-r15
  96. mov.l r6,@-r15
  97. mov.l r5,@-r15
  98. mov.l r4,@-r15
  99. mov r1,r9 ! save TRA
  100. mov r2,r8 ! copy user -> kernel stack
  101. mov.l @(0,r8),r3
  102. mov.l r3,@-r15
  103. mov.l @(4,r8),r2
  104. mov.l r2,@-r15
  105. mov.l @(12,r8),r1
  106. mov.l r1,@-r15
  107. mov.l @(8,r8),r0
  108. bra 2f
  109. mov.l r0,@-r15
  110. 1:
  111. ! in kernel exception
  112. mov #(22-4-4-1)*4+4,r0
  113. mov r15,r2
  114. sub r0,r15
  115. mov.l @r2+,r0 ! old R3
  116. mov.l r0,@-r15
  117. mov.l @r2+,r0 ! old R2
  118. mov.l r0,@-r15
  119. mov.l @(4,r2),r0 ! old R1
  120. mov.l r0,@-r15
  121. mov.l @r2,r0 ! old R0
  122. mov.l r0,@-r15
  123. add #8,r2
  124. mov.l @r2+,r3 ! old PC
  125. mov.l @r2+,r0 ! old SR
  126. add #-4,r2 ! exception frame stub (sr)
  127. mov.l r1,@-r2 ! TRA
  128. sts.l macl, @-r2
  129. sts.l mach, @-r2
  130. stc.l gbr, @-r2
  131. mov.l r0,@-r2 ! save old SR
  132. sts.l pr,@-r2
  133. mov.l r3,@-r2 ! save old PC
  134. mov r2,r0
  135. add #8*4,r0
  136. mov.l r0,@-r2 ! save old SP
  137. mov.l r14,@-r2
  138. mov.l r13,@-r2
  139. mov.l r12,@-r2
  140. mov.l r11,@-r2
  141. mov.l r10,@-r2
  142. mov.l r9,@-r2
  143. mov.l r8,@-r2
  144. mov.l r7,@-r2
  145. mov.l r6,@-r2
  146. mov.l r5,@-r2
  147. mov.l r4,@-r2
  148. mov r1,r9
  149. mov.l @(OFF_R0,r15),r0
  150. mov.l @(OFF_R1,r15),r1
  151. mov.l @(OFF_R2,r15),r2
  152. mov.l @(OFF_R3,r15),r3
  153. 2:
  154. mov #64,r8
  155. cmp/hs r8,r9
  156. bt interrupt_entry ! vec >= 64 is interrupt
  157. mov #31,r8
  158. cmp/hs r8,r9
  159. bt trap_entry ! 64 > vec >= 31 is trap
  160. #ifdef CONFIG_CPU_J2
  161. mov #16,r8
  162. cmp/hs r8,r9
  163. bt interrupt_entry ! 31 > vec >= 16 is interrupt
  164. #endif
  165. mov.l 4f,r8
  166. mov r9,r4
  167. shll2 r9
  168. add r9,r8
  169. mov.l @r8,r8 ! exception handler address
  170. tst r8,r8
  171. bf 3f
  172. mov.l 8f,r8 ! unhandled exception
  173. 3:
  174. mov.l 5f,r10
  175. jmp @r8
  176. lds r10,pr
  177. interrupt_entry:
  178. mov r9,r4
  179. mov r15,r5
  180. mov.l 6f,r9
  181. mov.l 7f,r8
  182. jmp @r8
  183. lds r9,pr
  184. .align 2
  185. 4: .long exception_handling_table
  186. 5: .long ret_from_exception
  187. 6: .long ret_from_irq
  188. 7: .long do_IRQ
  189. 8: .long exception_error
  190. trap_entry:
  191. mov #0x30,r8
  192. cmp/ge r8,r9 ! vector 0x1f-0x2f is systemcall
  193. bt 1f
  194. mov #0x1f,r9 ! convert to unified SH2/3/4 trap number
  195. 1:
  196. shll2 r9 ! TRA
  197. bra system_call ! jump common systemcall entry
  198. mov r9,r8
  199. #if defined(CONFIG_SH_STANDARD_BIOS)
  200. /* Unwind the stack and jmp to the debug entry */
  201. ENTRY(sh_bios_handler)
  202. mov r15,r0
  203. add #(22-4)*4-4,r0
  204. ldc.l @r0+,gbr
  205. lds.l @r0+,mach
  206. lds.l @r0+,macl
  207. mov r15,r0
  208. mov.l @(OFF_SP,r0),r1
  209. mov #OFF_SR,r2
  210. mov.l @(r0,r2),r3
  211. mov.l r3,@-r1
  212. mov #OFF_SP,r2
  213. mov.l @(r0,r2),r3
  214. mov.l r3,@-r1
  215. mov r15,r0
  216. add #(22-4)*4-8,r0
  217. mov.l 1f,r2
  218. mov.l @r2,r2
  219. stc sr,r3
  220. mov.l r2,@r0
  221. mov.l r3,@(4,r0)
  222. mov.l r1,@(8,r0)
  223. mov.l @r15+, r0
  224. mov.l @r15+, r1
  225. mov.l @r15+, r2
  226. mov.l @r15+, r3
  227. mov.l @r15+, r4
  228. mov.l @r15+, r5
  229. mov.l @r15+, r6
  230. mov.l @r15+, r7
  231. mov.l @r15+, r8
  232. mov.l @r15+, r9
  233. mov.l @r15+, r10
  234. mov.l @r15+, r11
  235. mov.l @r15+, r12
  236. mov.l @r15+, r13
  237. mov.l @r15+, r14
  238. add #8,r15
  239. lds.l @r15+, pr
  240. mov.l @r15+,r15
  241. rte
  242. nop
  243. .align 2
  244. 1: .long gdb_vbr_vector
  245. #endif /* CONFIG_SH_STANDARD_BIOS */
  246. ENTRY(address_error_trap_handler)
  247. mov r15,r4 ! regs
  248. mov #OFF_PC,r0
  249. mov.l @(r0,r15),r6 ! pc
  250. mov.l 1f,r0
  251. jmp @r0
  252. mov #0,r5 ! writeaccess is unknown
  253. .align 2
  254. 1: .long do_address_error
  255. restore_all:
  256. stc sr,r0
  257. or #0xf0,r0
  258. ldc r0,sr ! all interrupt block (same BL = 1)
  259. ! restore special register
  260. ! overlap exception frame
  261. mov r15,r0
  262. add #17*4,r0
  263. lds.l @r0+,pr
  264. add #4,r0
  265. ldc.l @r0+,gbr
  266. lds.l @r0+,mach
  267. lds.l @r0+,macl
  268. mov r15,r0
  269. mov.l $cpu_mode,r2
  270. #ifdef CONFIG_SMP
  271. mov.l $cpuid,r3
  272. mov.l @r3,r3
  273. mov.l @r3,r3
  274. shll2 r3
  275. add r3,r2
  276. #endif
  277. mov #OFF_SR,r3
  278. mov.l @(r0,r3),r1
  279. mov.l __md_bit,r3
  280. and r1,r3 ! copy MD bit
  281. mov.l r3,@r2
  282. shll2 r1 ! clear MD bit
  283. shlr2 r1
  284. mov.l @(OFF_SP,r0),r2
  285. add #-8,r2
  286. mov.l r2,@(OFF_SP,r0) ! point exception frame top
  287. mov.l r1,@(4,r2) ! set sr
  288. mov #OFF_PC,r3
  289. mov.l @(r0,r3),r1
  290. mov.l r1,@r2 ! set pc
  291. get_current_thread_info r0, r1
  292. mov.l $current_thread_info,r1
  293. #ifdef CONFIG_SMP
  294. mov.l $cpuid,r3
  295. mov.l @r3,r3
  296. mov.l @r3,r3
  297. shll2 r3
  298. add r3,r1
  299. #endif
  300. mov.l r0,@r1
  301. mov.l @r15+,r0
  302. mov.l @r15+,r1
  303. mov.l @r15+,r2
  304. mov.l @r15+,r3
  305. mov.l @r15+,r4
  306. mov.l @r15+,r5
  307. mov.l @r15+,r6
  308. mov.l @r15+,r7
  309. mov.l @r15+,r8
  310. mov.l @r15+,r9
  311. mov.l @r15+,r10
  312. mov.l @r15+,r11
  313. mov.l @r15+,r12
  314. mov.l @r15+,r13
  315. mov.l @r15+,r14
  316. mov.l @r15,r15
  317. rte
  318. nop
  319. .align 2
  320. __md_bit:
  321. .long 0x40000000
  322. $current_thread_info:
  323. .long __current_thread_info
  324. $cpu_mode:
  325. .long __cpu_mode
  326. #ifdef CONFIG_SMP
  327. $cpuid:
  328. .long sh2_cpuid_addr
  329. #endif
  330. ! common exception handler
  331. #include "../../entry-common.S"
  332. #ifdef CONFIG_NR_CPUS
  333. #define NR_CPUS CONFIG_NR_CPUS
  334. #else
  335. #define NR_CPUS 1
  336. #endif
  337. .data
  338. ! cpu operation mode
  339. ! bit30 = MD (compatible SH3/4)
  340. __cpu_mode:
  341. .rept NR_CPUS
  342. .long 0x40000000
  343. .endr
  344. #ifdef CONFIG_SMP
  345. .global sh2_cpuid_addr
  346. sh2_cpuid_addr:
  347. .long dummy_cpuid
  348. dummy_cpuid:
  349. .long 0
  350. #endif
  351. .section .bss
  352. __current_thread_info:
  353. .rept NR_CPUS
  354. .long 0
  355. .endr
  356. ENTRY(exception_handling_table)
  357. .space 4*32