entry.S 6.6 KB

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