entry.S 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /* SPDX-License-Identifier: GPL-2.0
  2. *
  3. * arch/sh/kernel/cpu/sh2a/entry.S
  4. *
  5. * The SH-2A exception entry
  6. *
  7. * Copyright (C) 2008 Yoshinori Sato
  8. * Based on arch/sh/kernel/cpu/sh2/entry.S
  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. cli
  41. mov.l $cpu_mode,r2
  42. bld.b #6,@(0,r2) !previus SR.MD
  43. bst.b #6,@(4*4,r15) !set cpu mode to SR.MD
  44. bt 1f
  45. ! switch to kernel mode
  46. bset.b #6,@(0,r2) !set SR.MD
  47. mov.l $current_thread_info,r2
  48. mov.l @r2,r2
  49. mov #(THREAD_SIZE >> 8),r0
  50. shll8 r0
  51. add r2,r0 ! r0 = kernel stack tail
  52. mov r15,r2 ! r2 = user stack top
  53. mov r0,r15 ! switch kernel stack
  54. mov.l r1,@-r15 ! TRA
  55. sts.l macl, @-r15
  56. sts.l mach, @-r15
  57. stc.l gbr, @-r15
  58. mov.l @(4*4,r2),r0
  59. mov.l r0,@-r15 ! original SR
  60. sts.l pr,@-r15
  61. mov.l @(3*4,r2),r0
  62. mov.l r0,@-r15 ! original PC
  63. mov r2,r0
  64. add #(3+2)*4,r0 ! rewind r0 - r3 + exception frame
  65. lds r0,pr ! pr = original SP
  66. movmu.l r3,@-r15 ! save regs
  67. mov r2,r8 ! r8 = previus stack top
  68. mov r1,r9 ! r9 = interrupt vector
  69. ! restore previous stack
  70. mov.l @r8+,r2
  71. mov.l @r8+,r0
  72. mov.l @r8+,r1
  73. bra 2f
  74. movml.l r2,@-r15
  75. 1:
  76. ! in kernel exception
  77. mov r15,r2
  78. add #-((OFF_TRA + 4) - OFF_PC) + 5*4,r15
  79. movmu.l r3,@-r15
  80. mov r2,r8 ! r8 = previous stack top
  81. mov r1,r9 ! r9 = interrupt vector
  82. ! restore exception frame & regs
  83. mov.l @r8+,r2 ! old R2
  84. mov.l @r8+,r0 ! old R0
  85. mov.l @r8+,r1 ! old R1
  86. mov.l @r8+,r10 ! old PC
  87. mov.l @r8+,r11 ! old SR
  88. movml.l r2,@-r15
  89. mov.l r10,@(OFF_PC,r15)
  90. mov.l r11,@(OFF_SR,r15)
  91. mov.l r8,@(OFF_SP,r15) ! save old sp
  92. mov r15,r8
  93. add #OFF_TRA + 4,r8
  94. mov.l r9,@-r8
  95. sts.l macl,@-r8
  96. sts.l mach,@-r8
  97. stc.l gbr,@-r8
  98. add #-4,r8
  99. sts.l pr,@-r8
  100. 2:
  101. ! dispatch exception / interrupt
  102. mov #64,r8
  103. cmp/hs r8,r9
  104. bt interrupt_entry ! vec >= 64 is interrupt
  105. mov #31,r8
  106. cmp/hs r8,r9
  107. bt trap_entry ! 64 > vec >= 31 is trap
  108. mov.l 4f,r8
  109. mov r9,r4
  110. shll2 r9
  111. add r9,r8
  112. mov.l @r8,r8 ! exception handler address
  113. tst r8,r8
  114. bf 3f
  115. mov.l 8f,r8 ! unhandled exception
  116. 3:
  117. mov.l 5f,r10
  118. jmp @r8
  119. lds r10,pr
  120. interrupt_entry:
  121. mov r9,r4
  122. mov r15,r5
  123. mov.l 7f,r8
  124. mov.l 6f,r9
  125. jmp @r8
  126. lds r9,pr
  127. .align 2
  128. 4: .long exception_handling_table
  129. 5: .long ret_from_exception
  130. 6: .long ret_from_irq
  131. 7: .long do_IRQ
  132. 8: .long exception_error
  133. trap_entry:
  134. mov #0x30,r8
  135. cmp/ge r8,r9 ! vector 0x1f-0x2f is systemcall
  136. bt 1f
  137. mov #0x1f,r9 ! convert to unified SH2/3/4 trap number
  138. 1:
  139. shll2 r9 ! TRA
  140. bra system_call ! jump common systemcall entry
  141. mov r9,r8
  142. #if defined(CONFIG_SH_STANDARD_BIOS)
  143. /* Unwind the stack and jmp to the debug entry */
  144. ENTRY(sh_bios_handler)
  145. mov r15,r0
  146. add #(22-4)*4-4,r0
  147. ldc.l @r0+,gbr
  148. lds.l @r0+,mach
  149. lds.l @r0+,macl
  150. mov r15,r0
  151. mov.l @(OFF_SP,r0),r1
  152. mov.l @(OFF_SR,r2),r3
  153. mov.l r3,@-r1
  154. mov.l @(OFF_SP,r2),r3
  155. mov.l r3,@-r1
  156. mov r15,r0
  157. add #(22-4)*4-8,r0
  158. mov.l 1f,r2
  159. mov.l @r2,r2
  160. stc sr,r3
  161. mov.l r2,@r0
  162. mov.l r3,@(4,r0)
  163. mov.l r1,@(8,r0)
  164. movml.l @r15+,r14
  165. add #8,r15
  166. lds.l @r15+, pr
  167. mov.l @r15+,r15
  168. rte
  169. nop
  170. .align 2
  171. 1: .long gdb_vbr_vector
  172. #endif /* CONFIG_SH_STANDARD_BIOS */
  173. ENTRY(address_error_trap_handler)
  174. mov r15,r4 ! regs
  175. mov.l @(OFF_PC,r15),r6 ! pc
  176. mov.l 1f,r0
  177. jmp @r0
  178. mov #0,r5 ! writeaccess is unknown
  179. .align 2
  180. 1: .long do_address_error
  181. restore_all:
  182. stc sr,r0
  183. or #0xf0,r0
  184. ldc r0,sr ! all interrupt block (same BL = 1)
  185. ! restore special register
  186. ! overlap exception frame
  187. mov r15,r0
  188. add #17*4,r0
  189. lds.l @r0+,pr
  190. add #4,r0
  191. ldc.l @r0+,gbr
  192. lds.l @r0+,mach
  193. lds.l @r0+,macl
  194. mov r15,r0
  195. mov.l $cpu_mode,r2
  196. bld.b #6,@(OFF_SR,r15)
  197. bst.b #6,@(0,r2) ! save CPU mode
  198. mov.l @(OFF_SR,r0),r1
  199. shll2 r1
  200. shlr2 r1 ! clear MD bit
  201. mov.l @(OFF_SP,r0),r2
  202. add #-8,r2
  203. mov.l r2,@(OFF_SP,r0) ! point exception frame top
  204. mov.l r1,@(4,r2) ! set sr
  205. mov.l @(OFF_PC,r0),r1
  206. mov.l r1,@r2 ! set pc
  207. get_current_thread_info r0, r1
  208. mov.l $current_thread_info,r1
  209. mov.l r0,@r1
  210. movml.l @r15+,r14
  211. mov.l @r15,r15
  212. rte
  213. nop
  214. .align 2
  215. $current_thread_info:
  216. .long __current_thread_info
  217. $cpu_mode:
  218. .long __cpu_mode
  219. ! common exception handler
  220. #include "../../entry-common.S"
  221. .data
  222. ! cpu operation mode
  223. ! bit30 = MD (compatible SH3/4)
  224. __cpu_mode:
  225. .long 0x40000000
  226. .section .bss
  227. __current_thread_info:
  228. .long 0
  229. ENTRY(exception_handling_table)
  230. .space 4*32