entry.S 5.0 KB

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