locore.S 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Main entry point for the guest, exception handling.
  7. *
  8. * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
  9. * Authors: Sanjay Lal <sanjayl@kymasys.com>
  10. */
  11. #include <asm/asm.h>
  12. #include <asm/asmmacro.h>
  13. #include <asm/regdef.h>
  14. #include <asm/mipsregs.h>
  15. #include <asm/stackframe.h>
  16. #include <asm/asm-offsets.h>
  17. #define _C_LABEL(x) x
  18. #define MIPSX(name) mips32_ ## name
  19. #define CALLFRAME_SIZ 32
  20. /*
  21. * VECTOR
  22. * exception vector entrypoint
  23. */
  24. #define VECTOR(x, regmask) \
  25. .ent _C_LABEL(x),0; \
  26. EXPORT(x);
  27. #define VECTOR_END(x) \
  28. EXPORT(x);
  29. /* Overload, Danger Will Robinson!! */
  30. #define PT_HOST_ASID PT_BVADDR
  31. #define PT_HOST_USERLOCAL PT_EPC
  32. #define CP0_DDATA_LO $28,3
  33. #define CP0_CONFIG3 $16,3
  34. #define CP0_CONFIG5 $16,5
  35. #define CP0_EBASE $15,1
  36. #define CP0_INTCTL $12,1
  37. #define CP0_SRSCTL $12,2
  38. #define CP0_SRSMAP $12,3
  39. #define CP0_HWRENA $7,0
  40. /* Resume Flags */
  41. #define RESUME_FLAG_HOST (1<<1) /* Resume host? */
  42. #define RESUME_GUEST 0
  43. #define RESUME_HOST RESUME_FLAG_HOST
  44. /*
  45. * __kvm_mips_vcpu_run: entry point to the guest
  46. * a0: run
  47. * a1: vcpu
  48. */
  49. .set noreorder
  50. .set noat
  51. FEXPORT(__kvm_mips_vcpu_run)
  52. /* k0/k1 not being used in host kernel context */
  53. INT_ADDIU k1, sp, -PT_SIZE
  54. LONG_S $0, PT_R0(k1)
  55. LONG_S $1, PT_R1(k1)
  56. LONG_S $2, PT_R2(k1)
  57. LONG_S $3, PT_R3(k1)
  58. LONG_S $4, PT_R4(k1)
  59. LONG_S $5, PT_R5(k1)
  60. LONG_S $6, PT_R6(k1)
  61. LONG_S $7, PT_R7(k1)
  62. LONG_S $8, PT_R8(k1)
  63. LONG_S $9, PT_R9(k1)
  64. LONG_S $10, PT_R10(k1)
  65. LONG_S $11, PT_R11(k1)
  66. LONG_S $12, PT_R12(k1)
  67. LONG_S $13, PT_R13(k1)
  68. LONG_S $14, PT_R14(k1)
  69. LONG_S $15, PT_R15(k1)
  70. LONG_S $16, PT_R16(k1)
  71. LONG_S $17, PT_R17(k1)
  72. LONG_S $18, PT_R18(k1)
  73. LONG_S $19, PT_R19(k1)
  74. LONG_S $20, PT_R20(k1)
  75. LONG_S $21, PT_R21(k1)
  76. LONG_S $22, PT_R22(k1)
  77. LONG_S $23, PT_R23(k1)
  78. LONG_S $24, PT_R24(k1)
  79. LONG_S $25, PT_R25(k1)
  80. /*
  81. * XXXKYMA k0/k1 not saved, not being used if we got here through
  82. * an ioctl()
  83. */
  84. LONG_S $28, PT_R28(k1)
  85. LONG_S $29, PT_R29(k1)
  86. LONG_S $30, PT_R30(k1)
  87. LONG_S $31, PT_R31(k1)
  88. /* Save hi/lo */
  89. mflo v0
  90. LONG_S v0, PT_LO(k1)
  91. mfhi v1
  92. LONG_S v1, PT_HI(k1)
  93. /* Save host status */
  94. mfc0 v0, CP0_STATUS
  95. LONG_S v0, PT_STATUS(k1)
  96. /* Save host ASID, shove it into the BVADDR location */
  97. mfc0 v1, CP0_ENTRYHI
  98. andi v1, 0xff
  99. LONG_S v1, PT_HOST_ASID(k1)
  100. /* Save DDATA_LO, will be used to store pointer to vcpu */
  101. mfc0 v1, CP0_DDATA_LO
  102. LONG_S v1, PT_HOST_USERLOCAL(k1)
  103. /* DDATA_LO has pointer to vcpu */
  104. mtc0 a1, CP0_DDATA_LO
  105. /* Offset into vcpu->arch */
  106. INT_ADDIU k1, a1, VCPU_HOST_ARCH
  107. /*
  108. * Save the host stack to VCPU, used for exception processing
  109. * when we exit from the Guest
  110. */
  111. LONG_S sp, VCPU_HOST_STACK(k1)
  112. /* Save the kernel gp as well */
  113. LONG_S gp, VCPU_HOST_GP(k1)
  114. /*
  115. * Setup status register for running the guest in UM, interrupts
  116. * are disabled
  117. */
  118. li k0, (ST0_EXL | KSU_USER | ST0_BEV)
  119. mtc0 k0, CP0_STATUS
  120. ehb
  121. /* load up the new EBASE */
  122. LONG_L k0, VCPU_GUEST_EBASE(k1)
  123. mtc0 k0, CP0_EBASE
  124. /*
  125. * Now that the new EBASE has been loaded, unset BEV, set
  126. * interrupt mask as it was but make sure that timer interrupts
  127. * are enabled
  128. */
  129. li k0, (ST0_EXL | KSU_USER | ST0_IE)
  130. andi v0, v0, ST0_IM
  131. or k0, k0, v0
  132. mtc0 k0, CP0_STATUS
  133. ehb
  134. /* Set Guest EPC */
  135. LONG_L t0, VCPU_PC(k1)
  136. mtc0 t0, CP0_EPC
  137. FEXPORT(__kvm_mips_load_asid)
  138. /* Set the ASID for the Guest Kernel */
  139. INT_SLL t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
  140. /* addresses shift to 0x80000000 */
  141. bltz t0, 1f /* If kernel */
  142. INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
  143. INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
  144. 1:
  145. /* t1: contains the base of the ASID array, need to get the cpu id */
  146. LONG_L t2, TI_CPU($28) /* smp_processor_id */
  147. INT_SLL t2, t2, 2 /* x4 */
  148. REG_ADDU t3, t1, t2
  149. LONG_L k0, (t3)
  150. andi k0, k0, 0xff
  151. mtc0 k0, CP0_ENTRYHI
  152. ehb
  153. /* Disable RDHWR access */
  154. mtc0 zero, CP0_HWRENA
  155. /* Now load up the Guest Context from VCPU */
  156. LONG_L $1, VCPU_R1(k1)
  157. LONG_L $2, VCPU_R2(k1)
  158. LONG_L $3, VCPU_R3(k1)
  159. LONG_L $4, VCPU_R4(k1)
  160. LONG_L $5, VCPU_R5(k1)
  161. LONG_L $6, VCPU_R6(k1)
  162. LONG_L $7, VCPU_R7(k1)
  163. LONG_L $8, VCPU_R8(k1)
  164. LONG_L $9, VCPU_R9(k1)
  165. LONG_L $10, VCPU_R10(k1)
  166. LONG_L $11, VCPU_R11(k1)
  167. LONG_L $12, VCPU_R12(k1)
  168. LONG_L $13, VCPU_R13(k1)
  169. LONG_L $14, VCPU_R14(k1)
  170. LONG_L $15, VCPU_R15(k1)
  171. LONG_L $16, VCPU_R16(k1)
  172. LONG_L $17, VCPU_R17(k1)
  173. LONG_L $18, VCPU_R18(k1)
  174. LONG_L $19, VCPU_R19(k1)
  175. LONG_L $20, VCPU_R20(k1)
  176. LONG_L $21, VCPU_R21(k1)
  177. LONG_L $22, VCPU_R22(k1)
  178. LONG_L $23, VCPU_R23(k1)
  179. LONG_L $24, VCPU_R24(k1)
  180. LONG_L $25, VCPU_R25(k1)
  181. /* k0/k1 loaded up later */
  182. LONG_L $28, VCPU_R28(k1)
  183. LONG_L $29, VCPU_R29(k1)
  184. LONG_L $30, VCPU_R30(k1)
  185. LONG_L $31, VCPU_R31(k1)
  186. /* Restore hi/lo */
  187. LONG_L k0, VCPU_LO(k1)
  188. mtlo k0
  189. LONG_L k0, VCPU_HI(k1)
  190. mthi k0
  191. FEXPORT(__kvm_mips_load_k0k1)
  192. /* Restore the guest's k0/k1 registers */
  193. LONG_L k0, VCPU_R26(k1)
  194. LONG_L k1, VCPU_R27(k1)
  195. /* Jump to guest */
  196. eret
  197. VECTOR(MIPSX(exception), unknown)
  198. /* Find out what mode we came from and jump to the proper handler. */
  199. mtc0 k0, CP0_ERROREPC #01: Save guest k0
  200. ehb #02:
  201. mfc0 k0, CP0_EBASE #02: Get EBASE
  202. INT_SRL k0, k0, 10 #03: Get rid of CPUNum
  203. INT_SLL k0, k0, 10 #04
  204. LONG_S k1, 0x3000(k0) #05: Save k1 @ offset 0x3000
  205. INT_ADDIU k0, k0, 0x2000 #06: Exception handler is
  206. # installed @ offset 0x2000
  207. j k0 #07: jump to the function
  208. nop #08: branch delay slot
  209. VECTOR_END(MIPSX(exceptionEnd))
  210. .end MIPSX(exception)
  211. /*
  212. * Generic Guest exception handler. We end up here when the guest
  213. * does something that causes a trap to kernel mode.
  214. */
  215. NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
  216. /* Get the VCPU pointer from DDTATA_LO */
  217. mfc0 k1, CP0_DDATA_LO
  218. INT_ADDIU k1, k1, VCPU_HOST_ARCH
  219. /* Start saving Guest context to VCPU */
  220. LONG_S $0, VCPU_R0(k1)
  221. LONG_S $1, VCPU_R1(k1)
  222. LONG_S $2, VCPU_R2(k1)
  223. LONG_S $3, VCPU_R3(k1)
  224. LONG_S $4, VCPU_R4(k1)
  225. LONG_S $5, VCPU_R5(k1)
  226. LONG_S $6, VCPU_R6(k1)
  227. LONG_S $7, VCPU_R7(k1)
  228. LONG_S $8, VCPU_R8(k1)
  229. LONG_S $9, VCPU_R9(k1)
  230. LONG_S $10, VCPU_R10(k1)
  231. LONG_S $11, VCPU_R11(k1)
  232. LONG_S $12, VCPU_R12(k1)
  233. LONG_S $13, VCPU_R13(k1)
  234. LONG_S $14, VCPU_R14(k1)
  235. LONG_S $15, VCPU_R15(k1)
  236. LONG_S $16, VCPU_R16(k1)
  237. LONG_S $17, VCPU_R17(k1)
  238. LONG_S $18, VCPU_R18(k1)
  239. LONG_S $19, VCPU_R19(k1)
  240. LONG_S $20, VCPU_R20(k1)
  241. LONG_S $21, VCPU_R21(k1)
  242. LONG_S $22, VCPU_R22(k1)
  243. LONG_S $23, VCPU_R23(k1)
  244. LONG_S $24, VCPU_R24(k1)
  245. LONG_S $25, VCPU_R25(k1)
  246. /* Guest k0/k1 saved later */
  247. LONG_S $28, VCPU_R28(k1)
  248. LONG_S $29, VCPU_R29(k1)
  249. LONG_S $30, VCPU_R30(k1)
  250. LONG_S $31, VCPU_R31(k1)
  251. /* We need to save hi/lo and restore them on the way out */
  252. mfhi t0
  253. LONG_S t0, VCPU_HI(k1)
  254. mflo t0
  255. LONG_S t0, VCPU_LO(k1)
  256. /* Finally save guest k0/k1 to VCPU */
  257. mfc0 t0, CP0_ERROREPC
  258. LONG_S t0, VCPU_R26(k1)
  259. /* Get GUEST k1 and save it in VCPU */
  260. PTR_LI t1, ~0x2ff
  261. mfc0 t0, CP0_EBASE
  262. and t0, t0, t1
  263. LONG_L t0, 0x3000(t0)
  264. LONG_S t0, VCPU_R27(k1)
  265. /* Now that context has been saved, we can use other registers */
  266. /* Restore vcpu */
  267. mfc0 a1, CP0_DDATA_LO
  268. move s1, a1
  269. /* Restore run (vcpu->run) */
  270. LONG_L a0, VCPU_RUN(a1)
  271. /* Save pointer to run in s0, will be saved by the compiler */
  272. move s0, a0
  273. /*
  274. * Save Host level EPC, BadVaddr and Cause to VCPU, useful to
  275. * process the exception
  276. */
  277. mfc0 k0,CP0_EPC
  278. LONG_S k0, VCPU_PC(k1)
  279. mfc0 k0, CP0_BADVADDR
  280. LONG_S k0, VCPU_HOST_CP0_BADVADDR(k1)
  281. mfc0 k0, CP0_CAUSE
  282. LONG_S k0, VCPU_HOST_CP0_CAUSE(k1)
  283. mfc0 k0, CP0_ENTRYHI
  284. LONG_S k0, VCPU_HOST_ENTRYHI(k1)
  285. /* Now restore the host state just enough to run the handlers */
  286. /* Swtich EBASE to the one used by Linux */
  287. /* load up the host EBASE */
  288. mfc0 v0, CP0_STATUS
  289. .set at
  290. or k0, v0, ST0_BEV
  291. .set noat
  292. mtc0 k0, CP0_STATUS
  293. ehb
  294. LONG_L k0, VCPU_HOST_EBASE(k1)
  295. mtc0 k0,CP0_EBASE
  296. /*
  297. * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
  298. * trigger FPE for pending exceptions.
  299. */
  300. .set at
  301. and v1, v0, ST0_CU1
  302. beqz v1, 1f
  303. nop
  304. .set push
  305. SET_HARDFLOAT
  306. cfc1 t0, fcr31
  307. sw t0, VCPU_FCR31(k1)
  308. ctc1 zero,fcr31
  309. .set pop
  310. .set noat
  311. 1:
  312. #ifdef CONFIG_CPU_HAS_MSA
  313. /*
  314. * If MSA is enabled, save MSACSR and clear it so that later
  315. * instructions don't trigger MSAFPE for pending exceptions.
  316. */
  317. mfc0 t0, CP0_CONFIG3
  318. ext t0, t0, 28, 1 /* MIPS_CONF3_MSAP */
  319. beqz t0, 1f
  320. nop
  321. mfc0 t0, CP0_CONFIG5
  322. ext t0, t0, 27, 1 /* MIPS_CONF5_MSAEN */
  323. beqz t0, 1f
  324. nop
  325. _cfcmsa t0, MSA_CSR
  326. sw t0, VCPU_MSA_CSR(k1)
  327. _ctcmsa MSA_CSR, zero
  328. 1:
  329. #endif
  330. /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
  331. .set at
  332. and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
  333. or v0, v0, ST0_CU0
  334. .set noat
  335. mtc0 v0, CP0_STATUS
  336. ehb
  337. /* Load up host GP */
  338. LONG_L gp, VCPU_HOST_GP(k1)
  339. /* Need a stack before we can jump to "C" */
  340. LONG_L sp, VCPU_HOST_STACK(k1)
  341. /* Saved host state */
  342. INT_ADDIU sp, sp, -PT_SIZE
  343. /*
  344. * XXXKYMA do we need to load the host ASID, maybe not because the
  345. * kernel entries are marked GLOBAL, need to verify
  346. */
  347. /* Restore host DDATA_LO */
  348. LONG_L k0, PT_HOST_USERLOCAL(sp)
  349. mtc0 k0, CP0_DDATA_LO
  350. /* Restore RDHWR access */
  351. PTR_LI k0, 0x2000000F
  352. mtc0 k0, CP0_HWRENA
  353. /* Jump to handler */
  354. FEXPORT(__kvm_mips_jump_to_handler)
  355. /*
  356. * XXXKYMA: not sure if this is safe, how large is the stack??
  357. * Now jump to the kvm_mips_handle_exit() to see if we can deal
  358. * with this in the kernel
  359. */
  360. PTR_LA t9, kvm_mips_handle_exit
  361. jalr.hb t9
  362. INT_ADDIU sp, sp, -CALLFRAME_SIZ /* BD Slot */
  363. /* Return from handler Make sure interrupts are disabled */
  364. di
  365. ehb
  366. /*
  367. * XXXKYMA: k0/k1 could have been blown away if we processed
  368. * an exception while we were handling the exception from the
  369. * guest, reload k1
  370. */
  371. move k1, s1
  372. INT_ADDIU k1, k1, VCPU_HOST_ARCH
  373. /*
  374. * Check return value, should tell us if we are returning to the
  375. * host (handle I/O etc)or resuming the guest
  376. */
  377. andi t0, v0, RESUME_HOST
  378. bnez t0, __kvm_mips_return_to_host
  379. nop
  380. __kvm_mips_return_to_guest:
  381. /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
  382. mtc0 s1, CP0_DDATA_LO
  383. /* Load up the Guest EBASE to minimize the window where BEV is set */
  384. LONG_L t0, VCPU_GUEST_EBASE(k1)
  385. /* Switch EBASE back to the one used by KVM */
  386. mfc0 v1, CP0_STATUS
  387. .set at
  388. or k0, v1, ST0_BEV
  389. .set noat
  390. mtc0 k0, CP0_STATUS
  391. ehb
  392. mtc0 t0, CP0_EBASE
  393. /* Setup status register for running guest in UM */
  394. .set at
  395. or v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
  396. and v1, v1, ~(ST0_CU0 | ST0_MX)
  397. .set noat
  398. mtc0 v1, CP0_STATUS
  399. ehb
  400. /* Set Guest EPC */
  401. LONG_L t0, VCPU_PC(k1)
  402. mtc0 t0, CP0_EPC
  403. /* Set the ASID for the Guest Kernel */
  404. INT_SLL t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
  405. /* addresses shift to 0x80000000 */
  406. bltz t0, 1f /* If kernel */
  407. INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
  408. INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
  409. 1:
  410. /* t1: contains the base of the ASID array, need to get the cpu id */
  411. LONG_L t2, TI_CPU($28) /* smp_processor_id */
  412. INT_SLL t2, t2, 2 /* x4 */
  413. REG_ADDU t3, t1, t2
  414. LONG_L k0, (t3)
  415. andi k0, k0, 0xff
  416. mtc0 k0,CP0_ENTRYHI
  417. ehb
  418. /* Disable RDHWR access */
  419. mtc0 zero, CP0_HWRENA
  420. /* load the guest context from VCPU and return */
  421. LONG_L $0, VCPU_R0(k1)
  422. LONG_L $1, VCPU_R1(k1)
  423. LONG_L $2, VCPU_R2(k1)
  424. LONG_L $3, VCPU_R3(k1)
  425. LONG_L $4, VCPU_R4(k1)
  426. LONG_L $5, VCPU_R5(k1)
  427. LONG_L $6, VCPU_R6(k1)
  428. LONG_L $7, VCPU_R7(k1)
  429. LONG_L $8, VCPU_R8(k1)
  430. LONG_L $9, VCPU_R9(k1)
  431. LONG_L $10, VCPU_R10(k1)
  432. LONG_L $11, VCPU_R11(k1)
  433. LONG_L $12, VCPU_R12(k1)
  434. LONG_L $13, VCPU_R13(k1)
  435. LONG_L $14, VCPU_R14(k1)
  436. LONG_L $15, VCPU_R15(k1)
  437. LONG_L $16, VCPU_R16(k1)
  438. LONG_L $17, VCPU_R17(k1)
  439. LONG_L $18, VCPU_R18(k1)
  440. LONG_L $19, VCPU_R19(k1)
  441. LONG_L $20, VCPU_R20(k1)
  442. LONG_L $21, VCPU_R21(k1)
  443. LONG_L $22, VCPU_R22(k1)
  444. LONG_L $23, VCPU_R23(k1)
  445. LONG_L $24, VCPU_R24(k1)
  446. LONG_L $25, VCPU_R25(k1)
  447. /* $/k1 loaded later */
  448. LONG_L $28, VCPU_R28(k1)
  449. LONG_L $29, VCPU_R29(k1)
  450. LONG_L $30, VCPU_R30(k1)
  451. LONG_L $31, VCPU_R31(k1)
  452. FEXPORT(__kvm_mips_skip_guest_restore)
  453. LONG_L k0, VCPU_HI(k1)
  454. mthi k0
  455. LONG_L k0, VCPU_LO(k1)
  456. mtlo k0
  457. LONG_L k0, VCPU_R26(k1)
  458. LONG_L k1, VCPU_R27(k1)
  459. eret
  460. __kvm_mips_return_to_host:
  461. /* EBASE is already pointing to Linux */
  462. LONG_L k1, VCPU_HOST_STACK(k1)
  463. INT_ADDIU k1,k1, -PT_SIZE
  464. /* Restore host DDATA_LO */
  465. LONG_L k0, PT_HOST_USERLOCAL(k1)
  466. mtc0 k0, CP0_DDATA_LO
  467. /* Restore host ASID */
  468. LONG_L k0, PT_HOST_ASID(sp)
  469. andi k0, 0xff
  470. mtc0 k0,CP0_ENTRYHI
  471. ehb
  472. /* Load context saved on the host stack */
  473. LONG_L $0, PT_R0(k1)
  474. LONG_L $1, PT_R1(k1)
  475. /*
  476. * r2/v0 is the return code, shift it down by 2 (arithmetic)
  477. * to recover the err code
  478. */
  479. INT_SRA k0, v0, 2
  480. move $2, k0
  481. LONG_L $3, PT_R3(k1)
  482. LONG_L $4, PT_R4(k1)
  483. LONG_L $5, PT_R5(k1)
  484. LONG_L $6, PT_R6(k1)
  485. LONG_L $7, PT_R7(k1)
  486. LONG_L $8, PT_R8(k1)
  487. LONG_L $9, PT_R9(k1)
  488. LONG_L $10, PT_R10(k1)
  489. LONG_L $11, PT_R11(k1)
  490. LONG_L $12, PT_R12(k1)
  491. LONG_L $13, PT_R13(k1)
  492. LONG_L $14, PT_R14(k1)
  493. LONG_L $15, PT_R15(k1)
  494. LONG_L $16, PT_R16(k1)
  495. LONG_L $17, PT_R17(k1)
  496. LONG_L $18, PT_R18(k1)
  497. LONG_L $19, PT_R19(k1)
  498. LONG_L $20, PT_R20(k1)
  499. LONG_L $21, PT_R21(k1)
  500. LONG_L $22, PT_R22(k1)
  501. LONG_L $23, PT_R23(k1)
  502. LONG_L $24, PT_R24(k1)
  503. LONG_L $25, PT_R25(k1)
  504. /* Host k0/k1 were not saved */
  505. LONG_L $28, PT_R28(k1)
  506. LONG_L $29, PT_R29(k1)
  507. LONG_L $30, PT_R30(k1)
  508. LONG_L k0, PT_HI(k1)
  509. mthi k0
  510. LONG_L k0, PT_LO(k1)
  511. mtlo k0
  512. /* Restore RDHWR access */
  513. PTR_LI k0, 0x2000000F
  514. mtc0 k0, CP0_HWRENA
  515. /* Restore RA, which is the address we will return to */
  516. LONG_L ra, PT_R31(k1)
  517. j ra
  518. nop
  519. VECTOR_END(MIPSX(GuestExceptionEnd))
  520. .end MIPSX(GuestException)
  521. MIPSX(exceptions):
  522. ####
  523. ##### The exception handlers.
  524. #####
  525. .word _C_LABEL(MIPSX(GuestException)) # 0
  526. .word _C_LABEL(MIPSX(GuestException)) # 1
  527. .word _C_LABEL(MIPSX(GuestException)) # 2
  528. .word _C_LABEL(MIPSX(GuestException)) # 3
  529. .word _C_LABEL(MIPSX(GuestException)) # 4
  530. .word _C_LABEL(MIPSX(GuestException)) # 5
  531. .word _C_LABEL(MIPSX(GuestException)) # 6
  532. .word _C_LABEL(MIPSX(GuestException)) # 7
  533. .word _C_LABEL(MIPSX(GuestException)) # 8
  534. .word _C_LABEL(MIPSX(GuestException)) # 9
  535. .word _C_LABEL(MIPSX(GuestException)) # 10
  536. .word _C_LABEL(MIPSX(GuestException)) # 11
  537. .word _C_LABEL(MIPSX(GuestException)) # 12
  538. .word _C_LABEL(MIPSX(GuestException)) # 13
  539. .word _C_LABEL(MIPSX(GuestException)) # 14
  540. .word _C_LABEL(MIPSX(GuestException)) # 15
  541. .word _C_LABEL(MIPSX(GuestException)) # 16
  542. .word _C_LABEL(MIPSX(GuestException)) # 17
  543. .word _C_LABEL(MIPSX(GuestException)) # 18
  544. .word _C_LABEL(MIPSX(GuestException)) # 19
  545. .word _C_LABEL(MIPSX(GuestException)) # 20
  546. .word _C_LABEL(MIPSX(GuestException)) # 21
  547. .word _C_LABEL(MIPSX(GuestException)) # 22
  548. .word _C_LABEL(MIPSX(GuestException)) # 23
  549. .word _C_LABEL(MIPSX(GuestException)) # 24
  550. .word _C_LABEL(MIPSX(GuestException)) # 25
  551. .word _C_LABEL(MIPSX(GuestException)) # 26
  552. .word _C_LABEL(MIPSX(GuestException)) # 27
  553. .word _C_LABEL(MIPSX(GuestException)) # 28
  554. .word _C_LABEL(MIPSX(GuestException)) # 29
  555. .word _C_LABEL(MIPSX(GuestException)) # 30
  556. .word _C_LABEL(MIPSX(GuestException)) # 31