exception-mips1.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
  3. * The President and Fellows of Harvard College.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #include <kern/mips/regdefs.h>
  30. #include <mips/specialreg.h>
  31. /*
  32. * Entry points for exceptions.
  33. *
  34. * MIPS-1 (r2000/r3000) style exception handling, with the "rfe"
  35. * instruction rather than "eret", and the three sets of status bits.
  36. */
  37. /*
  38. * Do not allow the assembler to use $1 (at), because we need to be
  39. * able to save it.
  40. */
  41. .set noat
  42. .set noreorder
  43. /*
  44. * UTLB exception handler.
  45. *
  46. * This code is copied to address 0x80000000, where the MIPS processor
  47. * automatically invokes it.
  48. *
  49. * To avoid colliding with the other exception code, it must not
  50. * exceed 128 bytes (32 instructions).
  51. *
  52. * This is the special entry point for the fast-path TLB refill for
  53. * faults in the user address space. We don't implement fast-path TLB
  54. * refill by default. Note that if you do, you either need to make
  55. * sure the refill code doesn't fault or write extra code in
  56. * common_exception to tidy up after such faults.
  57. */
  58. .text
  59. .globl mips_utlb_handler
  60. .type mips_utlb_handler,@function
  61. .ent mips_utlb_handler
  62. mips_utlb_handler:
  63. j common_exception /* Don't need to do anything special */
  64. nop /* Delay slot */
  65. .globl mips_utlb_end
  66. mips_utlb_end:
  67. .end mips_utlb_handler
  68. /*
  69. * General exception handler.
  70. *
  71. * This code is copied to address 0x80000080, where
  72. * the MIPS processor automatically invokes it.
  73. */
  74. .text
  75. .globl mips_general_handler
  76. .type mips_general_handler,@function
  77. .ent mips_general_handler
  78. mips_general_handler:
  79. j common_exception /* Don't need to do anything special */
  80. nop /* Delay slot */
  81. .globl mips_general_end
  82. mips_general_end:
  83. .end mips_general_handler
  84. /* This keeps gdb from conflating common_exception and mips_general_end */
  85. nop /* padding */
  86. /*
  87. * Shared exception code for both handlers.
  88. */
  89. .text
  90. .type common_exception,@function
  91. .ent common_exception
  92. common_exception:
  93. mfc0 k0, c0_status /* Get status register */
  94. andi k0, k0, CST_KUp /* Check the we-were-in-user-mode bit */
  95. beq k0, $0, 1f /* If clear, from kernel, already have stack */
  96. nop /* delay slot */
  97. /* Coming from user mode - find kernel stack */
  98. mfc0 k1, c0_context /* we keep the CPU number here */
  99. srl k1, k1, CTX_PTBASESHIFT /* shift it to get just the CPU number */
  100. sll k1, k1, 2 /* shift it back to make an array index */
  101. lui k0, %hi(cpustacks) /* get base address of cpustacks[] */
  102. addu k0, k0, k1 /* index it */
  103. move k1, sp /* Save previous stack pointer in k1 */
  104. b 2f /* Skip to common code */
  105. lw sp, %lo(cpustacks)(k0) /* Load kernel stack pointer (in delay slot) */
  106. 1:
  107. /* Coming from kernel mode - just save previous stuff */
  108. move k1, sp /* Save previous stack in k1 (delay slot) */
  109. 2:
  110. /*
  111. * At this point:
  112. * Interrupts are off. (The processor did this for us.)
  113. * k0 contains the value for curthread, to go into s7.
  114. * k1 contains the old stack pointer.
  115. * sp points into the kernel stack.
  116. * All other registers are untouched.
  117. */
  118. /*
  119. * Allocate stack space for 37 words to hold the trap frame,
  120. * plus four more words for a minimal argument block, plus
  121. * one more for proper (64-bit) stack alignment.
  122. */
  123. addi sp, sp, -168
  124. /*
  125. * Save general registers.
  126. * We exclude k0/k1, which the kernel is free to clobber (and which
  127. * we already have clobbered), and $0, whose value is fixed.
  128. *
  129. * The order here must match mips/include/trapframe.h.
  130. *
  131. * gdb disassembles this code to try to figure out what registers
  132. * are where, and it isn't very bright. So in order to make gdb be
  133. * able to trace the stack back through here, we play some silly
  134. * games.
  135. *
  136. * In particular:
  137. * (1) We store the return address register into the epc slot,
  138. * which makes gdb think it's the return address slot. Then
  139. * we store the real epc value over that.
  140. * (2) We store the current sp into the sp slot, which makes gdb
  141. * think it's the stack pointer slot. Then we store the real
  142. * value.
  143. * (3) gdb also assumes that saved registers in a function are
  144. * saved in order. This is why we put epc where it is, and
  145. * handle the real value of ra afterwards.
  146. * (4) Because gdb will think we're saving k0 and k1, we need to
  147. * leave slots for them in the trap frame, even though the
  148. * stuff we save there is useless.
  149. *
  150. * This logic has not been tested against a recent gdb and has
  151. * probably bitrotted. Someone(TM) should figure out what gdb
  152. * currently expects -- or maybe even patch gdb to understand a
  153. * better form of this that doesn't waste so many cycles.
  154. */
  155. sw ra, 160(sp) /* dummy for gdb */
  156. sw s8, 156(sp) /* save s8 */
  157. sw sp, 152(sp) /* dummy for gdb */
  158. sw gp, 148(sp) /* save gp */
  159. sw k1, 144(sp) /* dummy for gdb */
  160. sw k0, 140(sp) /* dummy for gdb */
  161. sw k1, 152(sp) /* real saved sp */
  162. nop /* delay slot for store */
  163. mfc0 k1, c0_epc /* Copr.0 reg 13 == PC for exception */
  164. sw k1, 160(sp) /* real saved PC */
  165. sw t9, 136(sp)
  166. sw t8, 132(sp)
  167. sw s7, 128(sp)
  168. sw s6, 124(sp)
  169. sw s5, 120(sp)
  170. sw s4, 116(sp)
  171. sw s3, 112(sp)
  172. sw s2, 108(sp)
  173. sw s1, 104(sp)
  174. sw s0, 100(sp)
  175. sw t7, 96(sp)
  176. sw t6, 92(sp)
  177. sw t5, 88(sp)
  178. sw t4, 84(sp)
  179. sw t3, 80(sp)
  180. sw t2, 76(sp)
  181. sw t1, 72(sp)
  182. sw t0, 68(sp)
  183. sw a3, 64(sp)
  184. sw a2, 60(sp)
  185. sw a1, 56(sp)
  186. sw a0, 52(sp)
  187. sw v1, 48(sp)
  188. sw v0, 44(sp)
  189. sw AT, 40(sp)
  190. sw ra, 36(sp)
  191. /*
  192. * Save special registers.
  193. */
  194. mfhi t0
  195. mflo t1
  196. sw t0, 32(sp)
  197. sw t1, 28(sp)
  198. /*
  199. * Save remaining exception context information.
  200. */
  201. mfc0 t2, c0_status /* Copr.0 reg 11 == status */
  202. sw t2, 20(sp)
  203. mfc0 t3, c0_vaddr /* Copr.0 reg 8 == faulting vaddr */
  204. sw t3, 16(sp)
  205. mfc0 t4, c0_cause
  206. sw t4, 24(sp) /* Copr.0 reg 13 == exception cause */
  207. /*
  208. * Pretend to save $0 for gdb's benefit.
  209. */
  210. sw $0, 12(sp)
  211. /*
  212. * Load the curthread register if coming from user mode.
  213. */
  214. andi k0, t2, CST_KUp /* Check the we-were-in-user-mode bit */
  215. beq k0, $0, 3f /* If clear, were in kernel, skip ahead */
  216. nop /* delay slot */
  217. mfc0 k1, c0_context /* we keep the CPU number here */
  218. srl k1, k1, CTX_PTBASESHIFT /* shift it to get just the CPU number */
  219. sll k1, k1, 2 /* shift it back to make an array index */
  220. lui k0, %hi(cputhreads) /* get base address of cputhreads[] */
  221. addu k0, k0, k1 /* index it */
  222. lw s7, %lo(cputhreads)(k0) /* Load curthread value */
  223. 3:
  224. /*
  225. * Load the kernel GP value.
  226. */
  227. la gp, _gp
  228. /*
  229. * Prepare to call mips_trap(struct trapframe *)
  230. */
  231. addiu a0, sp, 16 /* set argument - pointer to the trapframe */
  232. jal mips_trap /* call it */
  233. nop /* delay slot */
  234. /* Something must be here or gdb doesn't find the stack frame. */
  235. nop
  236. /*
  237. * Now restore stuff and return from the exception.
  238. * Interrupts should be off.
  239. */
  240. exception_return:
  241. /* 16(sp) no need to restore tf_vaddr */
  242. lw t0, 20(sp) /* load status register value into t0 */
  243. nop /* load delay slot */
  244. mtc0 t0, c0_status /* store it back to coprocessor 0 */
  245. /* 24(sp) no need to restore tf_cause */
  246. /* restore special registers */
  247. lw t1, 28(sp)
  248. lw t0, 32(sp)
  249. mtlo t1
  250. mthi t0
  251. /* load the general registers */
  252. lw ra, 36(sp)
  253. lw AT, 40(sp)
  254. lw v0, 44(sp)
  255. lw v1, 48(sp)
  256. lw a0, 52(sp)
  257. lw a1, 56(sp)
  258. lw a2, 60(sp)
  259. lw a3, 64(sp)
  260. lw t0, 68(sp)
  261. lw t1, 72(sp)
  262. lw t2, 76(sp)
  263. lw t3, 80(sp)
  264. lw t4, 84(sp)
  265. lw t5, 88(sp)
  266. lw t6, 92(sp)
  267. lw t7, 96(sp)
  268. lw s0, 100(sp)
  269. lw s1, 104(sp)
  270. lw s2, 108(sp)
  271. lw s3, 112(sp)
  272. lw s4, 116(sp)
  273. lw s5, 120(sp)
  274. lw s6, 124(sp)
  275. lw s7, 128(sp)
  276. lw t8, 132(sp)
  277. lw t9, 136(sp)
  278. /* 140(sp) "saved" k0 was dummy garbage anyway */
  279. /* 144(sp) "saved" k1 was dummy garbage anyway */
  280. lw gp, 148(sp) /* restore gp */
  281. /* 152(sp) stack pointer - below */
  282. lw s8, 156(sp) /* restore s8 */
  283. lw k0, 160(sp) /* fetch exception return PC into k0 */
  284. lw sp, 152(sp) /* fetch saved sp (must be last) */
  285. /* done */
  286. jr k0 /* jump back */
  287. rfe /* in delay slot */
  288. .end common_exception
  289. /*
  290. * Code to enter user mode for the first time.
  291. * Does not return.
  292. *
  293. * This is called from mips_usermode().
  294. * Interrupts on this processor should be off.
  295. */
  296. .text
  297. .globl asm_usermode
  298. .type asm_usermode,@function
  299. .ent asm_usermode
  300. asm_usermode:
  301. /*
  302. * a0 is the address of a trapframe to use for exception "return".
  303. * It's allocated on our stack.
  304. *
  305. * Move it to the stack pointer - we don't need the actual stack
  306. * position any more. (When we come back from usermode, cpustacks[]
  307. * will be used to reinitialize our stack pointer, and that was
  308. * set by mips_usermode.)
  309. *
  310. * Then just jump to the exception return code above.
  311. */
  312. j exception_return
  313. addiu sp, a0, -16 /* in delay slot */
  314. .end asm_usermode