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