blob: f5594049c0c3ab0e238091262fcbd2e28fb05cf4 [file] [log] [blame]
Sanjay Lalb680f702012-11-21 18:34:01 -08001/*
David Daney2c07ebb2013-08-01 13:22:33 -07002 * 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 */
Sanjay Lalb680f702012-11-21 18:34:01 -080011
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
Sanjay Lalb680f702012-11-21 18:34:01 -080019#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!! */
35#define PT_HOST_ASID PT_BVADDR
36#define PT_HOST_USERLOCAL PT_EPC
37
38#define CP0_DDATA_LO $28,3
39#define CP0_EBASE $15,1
40
41#define CP0_INTCTL $12,1
42#define CP0_SRSCTL $12,2
43#define CP0_SRSMAP $12,3
44#define CP0_HWRENA $7,0
45
46/* Resume Flags */
47#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
48
49#define RESUME_GUEST 0
50#define RESUME_HOST RESUME_FLAG_HOST
51
52/*
53 * __kvm_mips_vcpu_run: entry point to the guest
54 * a0: run
55 * a1: vcpu
56 */
David Daney2c07ebb2013-08-01 13:22:33 -070057 .set noreorder
58 .set noat
Sanjay Lalb680f702012-11-21 18:34:01 -080059
David Daneybb48c2f2013-08-01 13:22:34 -070060FEXPORT(__kvm_mips_vcpu_run)
David Daney2c07ebb2013-08-01 13:22:33 -070061 /* k0/k1 not being used in host kernel context */
David Daneyea69f282013-08-01 13:22:35 -070062 INT_ADDIU k1, sp, -PT_SIZE
David Daney2c07ebb2013-08-01 13:22:33 -070063 LONG_S $0, PT_R0(k1)
64 LONG_S $1, PT_R1(k1)
65 LONG_S $2, PT_R2(k1)
66 LONG_S $3, PT_R3(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080067
David Daney2c07ebb2013-08-01 13:22:33 -070068 LONG_S $4, PT_R4(k1)
69 LONG_S $5, PT_R5(k1)
70 LONG_S $6, PT_R6(k1)
71 LONG_S $7, PT_R7(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080072
David Daney2c07ebb2013-08-01 13:22:33 -070073 LONG_S $8, PT_R8(k1)
74 LONG_S $9, PT_R9(k1)
75 LONG_S $10, PT_R10(k1)
76 LONG_S $11, PT_R11(k1)
77 LONG_S $12, PT_R12(k1)
78 LONG_S $13, PT_R13(k1)
79 LONG_S $14, PT_R14(k1)
80 LONG_S $15, PT_R15(k1)
81 LONG_S $16, PT_R16(k1)
82 LONG_S $17, PT_R17(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080083
David Daney2c07ebb2013-08-01 13:22:33 -070084 LONG_S $18, PT_R18(k1)
85 LONG_S $19, PT_R19(k1)
86 LONG_S $20, PT_R20(k1)
87 LONG_S $21, PT_R21(k1)
88 LONG_S $22, PT_R22(k1)
89 LONG_S $23, PT_R23(k1)
90 LONG_S $24, PT_R24(k1)
91 LONG_S $25, PT_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080092
Deng-Cheng Zhud116e812014-06-26 12:11:34 -070093 /*
94 * XXXKYMA k0/k1 not saved, not being used if we got here through
95 * an ioctl()
96 */
Sanjay Lalb680f702012-11-21 18:34:01 -080097
David Daney2c07ebb2013-08-01 13:22:33 -070098 LONG_S $28, PT_R28(k1)
99 LONG_S $29, PT_R29(k1)
100 LONG_S $30, PT_R30(k1)
101 LONG_S $31, PT_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800102
David Daney2c07ebb2013-08-01 13:22:33 -0700103 /* Save hi/lo */
104 mflo v0
105 LONG_S v0, PT_LO(k1)
106 mfhi v1
107 LONG_S v1, PT_HI(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800108
109 /* Save host status */
David Daney2c07ebb2013-08-01 13:22:33 -0700110 mfc0 v0, CP0_STATUS
111 LONG_S v0, PT_STATUS(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800112
113 /* Save host ASID, shove it into the BVADDR location */
David Daney2c07ebb2013-08-01 13:22:33 -0700114 mfc0 v1, CP0_ENTRYHI
115 andi v1, 0xff
116 LONG_S v1, PT_HOST_ASID(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800117
David Daney2c07ebb2013-08-01 13:22:33 -0700118 /* Save DDATA_LO, will be used to store pointer to vcpu */
119 mfc0 v1, CP0_DDATA_LO
120 LONG_S v1, PT_HOST_USERLOCAL(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800121
David Daney2c07ebb2013-08-01 13:22:33 -0700122 /* DDATA_LO has pointer to vcpu */
123 mtc0 a1, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800124
David Daney2c07ebb2013-08-01 13:22:33 -0700125 /* Offset into vcpu->arch */
David Daneyea69f282013-08-01 13:22:35 -0700126 INT_ADDIU k1, a1, VCPU_HOST_ARCH
Sanjay Lalb680f702012-11-21 18:34:01 -0800127
David Daney2c07ebb2013-08-01 13:22:33 -0700128 /*
129 * Save the host stack to VCPU, used for exception processing
130 * when we exit from the Guest
131 */
132 LONG_S sp, VCPU_HOST_STACK(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800133
David Daney2c07ebb2013-08-01 13:22:33 -0700134 /* Save the kernel gp as well */
135 LONG_S gp, VCPU_HOST_GP(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800136
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700137 /*
138 * Setup status register for running the guest in UM, interrupts
139 * are disabled
140 */
David Daney2c07ebb2013-08-01 13:22:33 -0700141 li k0, (ST0_EXL | KSU_USER | ST0_BEV)
142 mtc0 k0, CP0_STATUS
143 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800144
David Daney2c07ebb2013-08-01 13:22:33 -0700145 /* load up the new EBASE */
146 LONG_L k0, VCPU_GUEST_EBASE(k1)
147 mtc0 k0, CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800148
David Daney2c07ebb2013-08-01 13:22:33 -0700149 /*
150 * Now that the new EBASE has been loaded, unset BEV, set
151 * interrupt mask as it was but make sure that timer interrupts
152 * are enabled
153 */
154 li k0, (ST0_EXL | KSU_USER | ST0_IE)
155 andi v0, v0, ST0_IM
156 or k0, k0, v0
157 mtc0 k0, CP0_STATUS
158 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800159
Sanjay Lalb680f702012-11-21 18:34:01 -0800160 /* Set Guest EPC */
David Daney2c07ebb2013-08-01 13:22:33 -0700161 LONG_L t0, VCPU_PC(k1)
162 mtc0 t0, CP0_EPC
Sanjay Lalb680f702012-11-21 18:34:01 -0800163
164FEXPORT(__kvm_mips_load_asid)
David Daney2c07ebb2013-08-01 13:22:33 -0700165 /* Set the ASID for the Guest Kernel */
David Daneyea69f282013-08-01 13:22:35 -0700166 INT_SLL t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
David Daney2c07ebb2013-08-01 13:22:33 -0700167 /* addresses shift to 0x80000000 */
168 bltz t0, 1f /* If kernel */
David Daneyea69f282013-08-01 13:22:35 -0700169 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
170 INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
Sanjay Lalb680f702012-11-21 18:34:01 -08001711:
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700172 /* t1: contains the base of the ASID array, need to get the cpu id */
David Daney2c07ebb2013-08-01 13:22:33 -0700173 LONG_L t2, TI_CPU($28) /* smp_processor_id */
David Daneyea69f282013-08-01 13:22:35 -0700174 INT_SLL t2, t2, 2 /* x4 */
175 REG_ADDU t3, t1, t2
David Daney2c07ebb2013-08-01 13:22:33 -0700176 LONG_L k0, (t3)
177 andi k0, k0, 0xff
178 mtc0 k0, CP0_ENTRYHI
179 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800180
David Daney2c07ebb2013-08-01 13:22:33 -0700181 /* Disable RDHWR access */
182 mtc0 zero, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800183
David Daney2c07ebb2013-08-01 13:22:33 -0700184 /* Now load up the Guest Context from VCPU */
185 LONG_L $1, VCPU_R1(k1)
186 LONG_L $2, VCPU_R2(k1)
187 LONG_L $3, VCPU_R3(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800188
David Daney2c07ebb2013-08-01 13:22:33 -0700189 LONG_L $4, VCPU_R4(k1)
190 LONG_L $5, VCPU_R5(k1)
191 LONG_L $6, VCPU_R6(k1)
192 LONG_L $7, VCPU_R7(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800193
David Daney2c07ebb2013-08-01 13:22:33 -0700194 LONG_L $8, VCPU_R8(k1)
195 LONG_L $9, VCPU_R9(k1)
196 LONG_L $10, VCPU_R10(k1)
197 LONG_L $11, VCPU_R11(k1)
198 LONG_L $12, VCPU_R12(k1)
199 LONG_L $13, VCPU_R13(k1)
200 LONG_L $14, VCPU_R14(k1)
201 LONG_L $15, VCPU_R15(k1)
202 LONG_L $16, VCPU_R16(k1)
203 LONG_L $17, VCPU_R17(k1)
204 LONG_L $18, VCPU_R18(k1)
205 LONG_L $19, VCPU_R19(k1)
206 LONG_L $20, VCPU_R20(k1)
207 LONG_L $21, VCPU_R21(k1)
208 LONG_L $22, VCPU_R22(k1)
209 LONG_L $23, VCPU_R23(k1)
210 LONG_L $24, VCPU_R24(k1)
211 LONG_L $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800212
David Daney2c07ebb2013-08-01 13:22:33 -0700213 /* k0/k1 loaded up later */
Sanjay Lalb680f702012-11-21 18:34:01 -0800214
David Daney2c07ebb2013-08-01 13:22:33 -0700215 LONG_L $28, VCPU_R28(k1)
216 LONG_L $29, VCPU_R29(k1)
217 LONG_L $30, VCPU_R30(k1)
218 LONG_L $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800219
David Daney2c07ebb2013-08-01 13:22:33 -0700220 /* Restore hi/lo */
221 LONG_L k0, VCPU_LO(k1)
222 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800223
David Daney2c07ebb2013-08-01 13:22:33 -0700224 LONG_L k0, VCPU_HI(k1)
225 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800226
227FEXPORT(__kvm_mips_load_k0k1)
228 /* Restore the guest's k0/k1 registers */
David Daney2c07ebb2013-08-01 13:22:33 -0700229 LONG_L k0, VCPU_R26(k1)
230 LONG_L k1, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800231
David Daney2c07ebb2013-08-01 13:22:33 -0700232 /* Jump to guest */
Sanjay Lalb680f702012-11-21 18:34:01 -0800233 eret
Sanjay Lalb680f702012-11-21 18:34:01 -0800234
235VECTOR(MIPSX(exception), unknown)
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700236/* Find out what mode we came from and jump to the proper handler. */
David Daney2c07ebb2013-08-01 13:22:33 -0700237 mtc0 k0, CP0_ERROREPC #01: Save guest k0
238 ehb #02:
Sanjay Lalb680f702012-11-21 18:34:01 -0800239
David Daney2c07ebb2013-08-01 13:22:33 -0700240 mfc0 k0, CP0_EBASE #02: Get EBASE
David Daneyea69f282013-08-01 13:22:35 -0700241 INT_SRL k0, k0, 10 #03: Get rid of CPUNum
242 INT_SLL k0, k0, 10 #04
David Daney2c07ebb2013-08-01 13:22:33 -0700243 LONG_S k1, 0x3000(k0) #05: Save k1 @ offset 0x3000
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700244 INT_ADDIU k0, k0, 0x2000 #06: Exception handler is
245 # installed @ offset 0x2000
David Daney2c07ebb2013-08-01 13:22:33 -0700246 j k0 #07: jump to the function
247 nop #08: branch delay slot
Sanjay Lalb680f702012-11-21 18:34:01 -0800248VECTOR_END(MIPSX(exceptionEnd))
249.end MIPSX(exception)
250
251/*
252 * Generic Guest exception handler. We end up here when the guest
253 * does something that causes a trap to kernel mode.
Sanjay Lalb680f702012-11-21 18:34:01 -0800254 */
255NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
David Daney2c07ebb2013-08-01 13:22:33 -0700256 /* Get the VCPU pointer from DDTATA_LO */
257 mfc0 k1, CP0_DDATA_LO
David Daneyea69f282013-08-01 13:22:35 -0700258 INT_ADDIU k1, k1, VCPU_HOST_ARCH
Sanjay Lalb680f702012-11-21 18:34:01 -0800259
David Daney2c07ebb2013-08-01 13:22:33 -0700260 /* Start saving Guest context to VCPU */
261 LONG_S $0, VCPU_R0(k1)
262 LONG_S $1, VCPU_R1(k1)
263 LONG_S $2, VCPU_R2(k1)
264 LONG_S $3, VCPU_R3(k1)
265 LONG_S $4, VCPU_R4(k1)
266 LONG_S $5, VCPU_R5(k1)
267 LONG_S $6, VCPU_R6(k1)
268 LONG_S $7, VCPU_R7(k1)
269 LONG_S $8, VCPU_R8(k1)
270 LONG_S $9, VCPU_R9(k1)
271 LONG_S $10, VCPU_R10(k1)
272 LONG_S $11, VCPU_R11(k1)
273 LONG_S $12, VCPU_R12(k1)
274 LONG_S $13, VCPU_R13(k1)
275 LONG_S $14, VCPU_R14(k1)
276 LONG_S $15, VCPU_R15(k1)
277 LONG_S $16, VCPU_R16(k1)
278 LONG_S $17, VCPU_R17(k1)
279 LONG_S $18, VCPU_R18(k1)
280 LONG_S $19, VCPU_R19(k1)
281 LONG_S $20, VCPU_R20(k1)
282 LONG_S $21, VCPU_R21(k1)
283 LONG_S $22, VCPU_R22(k1)
284 LONG_S $23, VCPU_R23(k1)
285 LONG_S $24, VCPU_R24(k1)
286 LONG_S $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800287
David Daney2c07ebb2013-08-01 13:22:33 -0700288 /* Guest k0/k1 saved later */
Sanjay Lalb680f702012-11-21 18:34:01 -0800289
David Daney2c07ebb2013-08-01 13:22:33 -0700290 LONG_S $28, VCPU_R28(k1)
291 LONG_S $29, VCPU_R29(k1)
292 LONG_S $30, VCPU_R30(k1)
293 LONG_S $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800294
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700295 /* We need to save hi/lo and restore them on the way out */
David Daney2c07ebb2013-08-01 13:22:33 -0700296 mfhi t0
297 LONG_S t0, VCPU_HI(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800298
David Daney2c07ebb2013-08-01 13:22:33 -0700299 mflo t0
300 LONG_S t0, VCPU_LO(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800301
David Daney2c07ebb2013-08-01 13:22:33 -0700302 /* Finally save guest k0/k1 to VCPU */
303 mfc0 t0, CP0_ERROREPC
304 LONG_S t0, VCPU_R26(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800305
David Daney2c07ebb2013-08-01 13:22:33 -0700306 /* Get GUEST k1 and save it in VCPU */
David Daneyea69f282013-08-01 13:22:35 -0700307 PTR_LI t1, ~0x2ff
David Daney2c07ebb2013-08-01 13:22:33 -0700308 mfc0 t0, CP0_EBASE
309 and t0, t0, t1
310 LONG_L t0, 0x3000(t0)
311 LONG_S t0, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800312
David Daney2c07ebb2013-08-01 13:22:33 -0700313 /* Now that context has been saved, we can use other registers */
Sanjay Lalb680f702012-11-21 18:34:01 -0800314
David Daney2c07ebb2013-08-01 13:22:33 -0700315 /* Restore vcpu */
316 mfc0 a1, CP0_DDATA_LO
317 move s1, a1
Sanjay Lalb680f702012-11-21 18:34:01 -0800318
David Daney2c07ebb2013-08-01 13:22:33 -0700319 /* Restore run (vcpu->run) */
320 LONG_L a0, VCPU_RUN(a1)
321 /* Save pointer to run in s0, will be saved by the compiler */
322 move s0, a0
323
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700324 /*
325 * Save Host level EPC, BadVaddr and Cause to VCPU, useful to
326 * process the exception
327 */
David Daney2c07ebb2013-08-01 13:22:33 -0700328 mfc0 k0,CP0_EPC
329 LONG_S k0, VCPU_PC(k1)
330
331 mfc0 k0, CP0_BADVADDR
332 LONG_S k0, VCPU_HOST_CP0_BADVADDR(k1)
333
334 mfc0 k0, CP0_CAUSE
335 LONG_S k0, VCPU_HOST_CP0_CAUSE(k1)
336
337 mfc0 k0, CP0_ENTRYHI
338 LONG_S k0, VCPU_HOST_ENTRYHI(k1)
339
340 /* Now restore the host state just enough to run the handlers */
341
342 /* Swtich EBASE to the one used by Linux */
343 /* load up the host EBASE */
344 mfc0 v0, CP0_STATUS
345
346 .set at
347 or k0, v0, ST0_BEV
348 .set noat
349
350 mtc0 k0, CP0_STATUS
351 ehb
352
353 LONG_L k0, VCPU_HOST_EBASE(k1)
354 mtc0 k0,CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800355
James Hogan98e91b82014-11-18 14:09:12 +0000356 /*
357 * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
358 * trigger FPE for pending exceptions.
359 */
360 .set at
361 and v1, v0, ST0_CU1
362 beqz v1, 1f
363 nop
364 .set push
365 SET_HARDFLOAT
366 cfc1 t0, fcr31
367 sw t0, VCPU_FCR31(k1)
368 ctc1 zero,fcr31
369 .set pop
370 .set noat
3711:
372
David Daney2c07ebb2013-08-01 13:22:33 -0700373 /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
374 .set at
375 and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
376 or v0, v0, ST0_CU0
377 .set noat
378 mtc0 v0, CP0_STATUS
379 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800380
David Daney2c07ebb2013-08-01 13:22:33 -0700381 /* Load up host GP */
382 LONG_L gp, VCPU_HOST_GP(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800383
David Daney2c07ebb2013-08-01 13:22:33 -0700384 /* Need a stack before we can jump to "C" */
385 LONG_L sp, VCPU_HOST_STACK(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800386
David Daney2c07ebb2013-08-01 13:22:33 -0700387 /* Saved host state */
David Daneyea69f282013-08-01 13:22:35 -0700388 INT_ADDIU sp, sp, -PT_SIZE
Sanjay Lalb680f702012-11-21 18:34:01 -0800389
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700390 /*
391 * XXXKYMA do we need to load the host ASID, maybe not because the
David Daney2c07ebb2013-08-01 13:22:33 -0700392 * kernel entries are marked GLOBAL, need to verify
393 */
Sanjay Lalb680f702012-11-21 18:34:01 -0800394
David Daney2c07ebb2013-08-01 13:22:33 -0700395 /* Restore host DDATA_LO */
396 LONG_L k0, PT_HOST_USERLOCAL(sp)
397 mtc0 k0, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800398
David Daney2c07ebb2013-08-01 13:22:33 -0700399 /* Restore RDHWR access */
David Daneyea69f282013-08-01 13:22:35 -0700400 PTR_LI k0, 0x2000000F
David Daney2c07ebb2013-08-01 13:22:33 -0700401 mtc0 k0, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800402
David Daney2c07ebb2013-08-01 13:22:33 -0700403 /* Jump to handler */
Sanjay Lalb680f702012-11-21 18:34:01 -0800404FEXPORT(__kvm_mips_jump_to_handler)
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700405 /*
406 * XXXKYMA: not sure if this is safe, how large is the stack??
David Daney2c07ebb2013-08-01 13:22:33 -0700407 * Now jump to the kvm_mips_handle_exit() to see if we can deal
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700408 * with this in the kernel
409 */
David Daneyea69f282013-08-01 13:22:35 -0700410 PTR_LA t9, kvm_mips_handle_exit
David Daney2c07ebb2013-08-01 13:22:33 -0700411 jalr.hb t9
David Daneyea69f282013-08-01 13:22:35 -0700412 INT_ADDIU sp, sp, -CALLFRAME_SIZ /* BD Slot */
Sanjay Lalb680f702012-11-21 18:34:01 -0800413
David Daney2c07ebb2013-08-01 13:22:33 -0700414 /* Return from handler Make sure interrupts are disabled */
415 di
416 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800417
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700418 /*
419 * XXXKYMA: k0/k1 could have been blown away if we processed
David Daney2c07ebb2013-08-01 13:22:33 -0700420 * an exception while we were handling the exception from the
421 * guest, reload k1
422 */
Sanjay Lalb680f702012-11-21 18:34:01 -0800423
David Daney2c07ebb2013-08-01 13:22:33 -0700424 move k1, s1
David Daneyea69f282013-08-01 13:22:35 -0700425 INT_ADDIU k1, k1, VCPU_HOST_ARCH
David Daney2c07ebb2013-08-01 13:22:33 -0700426
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700427 /*
428 * Check return value, should tell us if we are returning to the
David Daney2c07ebb2013-08-01 13:22:33 -0700429 * host (handle I/O etc)or resuming the guest
430 */
431 andi t0, v0, RESUME_HOST
432 bnez t0, __kvm_mips_return_to_host
433 nop
Sanjay Lalb680f702012-11-21 18:34:01 -0800434
435__kvm_mips_return_to_guest:
David Daney2c07ebb2013-08-01 13:22:33 -0700436 /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
437 mtc0 s1, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800438
David Daney2c07ebb2013-08-01 13:22:33 -0700439 /* Load up the Guest EBASE to minimize the window where BEV is set */
440 LONG_L t0, VCPU_GUEST_EBASE(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800441
David Daney2c07ebb2013-08-01 13:22:33 -0700442 /* Switch EBASE back to the one used by KVM */
443 mfc0 v1, CP0_STATUS
444 .set at
445 or k0, v1, ST0_BEV
446 .set noat
447 mtc0 k0, CP0_STATUS
448 ehb
449 mtc0 t0, CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800450
David Daney2c07ebb2013-08-01 13:22:33 -0700451 /* Setup status register for running guest in UM */
452 .set at
453 or v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
James Hoganf7982172015-02-04 17:06:37 +0000454 and v1, v1, ~(ST0_CU0 | ST0_MX)
David Daney2c07ebb2013-08-01 13:22:33 -0700455 .set noat
456 mtc0 v1, CP0_STATUS
457 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800458
459 /* Set Guest EPC */
David Daney2c07ebb2013-08-01 13:22:33 -0700460 LONG_L t0, VCPU_PC(k1)
461 mtc0 t0, CP0_EPC
Sanjay Lalb680f702012-11-21 18:34:01 -0800462
David Daney2c07ebb2013-08-01 13:22:33 -0700463 /* Set the ASID for the Guest Kernel */
David Daneyea69f282013-08-01 13:22:35 -0700464 INT_SLL t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
David Daney2c07ebb2013-08-01 13:22:33 -0700465 /* addresses shift to 0x80000000 */
466 bltz t0, 1f /* If kernel */
David Daneyea69f282013-08-01 13:22:35 -0700467 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
468 INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
Sanjay Lalb680f702012-11-21 18:34:01 -08004691:
David Daney2c07ebb2013-08-01 13:22:33 -0700470 /* t1: contains the base of the ASID array, need to get the cpu id */
471 LONG_L t2, TI_CPU($28) /* smp_processor_id */
David Daneyea69f282013-08-01 13:22:35 -0700472 INT_SLL t2, t2, 2 /* x4 */
473 REG_ADDU t3, t1, t2
David Daney2c07ebb2013-08-01 13:22:33 -0700474 LONG_L k0, (t3)
475 andi k0, k0, 0xff
476 mtc0 k0,CP0_ENTRYHI
477 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800478
David Daney2c07ebb2013-08-01 13:22:33 -0700479 /* Disable RDHWR access */
480 mtc0 zero, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800481
David Daney2c07ebb2013-08-01 13:22:33 -0700482 /* load the guest context from VCPU and return */
483 LONG_L $0, VCPU_R0(k1)
484 LONG_L $1, VCPU_R1(k1)
485 LONG_L $2, VCPU_R2(k1)
486 LONG_L $3, VCPU_R3(k1)
487 LONG_L $4, VCPU_R4(k1)
488 LONG_L $5, VCPU_R5(k1)
489 LONG_L $6, VCPU_R6(k1)
490 LONG_L $7, VCPU_R7(k1)
491 LONG_L $8, VCPU_R8(k1)
492 LONG_L $9, VCPU_R9(k1)
493 LONG_L $10, VCPU_R10(k1)
494 LONG_L $11, VCPU_R11(k1)
495 LONG_L $12, VCPU_R12(k1)
496 LONG_L $13, VCPU_R13(k1)
497 LONG_L $14, VCPU_R14(k1)
498 LONG_L $15, VCPU_R15(k1)
499 LONG_L $16, VCPU_R16(k1)
500 LONG_L $17, VCPU_R17(k1)
501 LONG_L $18, VCPU_R18(k1)
502 LONG_L $19, VCPU_R19(k1)
503 LONG_L $20, VCPU_R20(k1)
504 LONG_L $21, VCPU_R21(k1)
505 LONG_L $22, VCPU_R22(k1)
506 LONG_L $23, VCPU_R23(k1)
507 LONG_L $24, VCPU_R24(k1)
508 LONG_L $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800509
David Daney2c07ebb2013-08-01 13:22:33 -0700510 /* $/k1 loaded later */
511 LONG_L $28, VCPU_R28(k1)
512 LONG_L $29, VCPU_R29(k1)
513 LONG_L $30, VCPU_R30(k1)
514 LONG_L $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800515
516FEXPORT(__kvm_mips_skip_guest_restore)
David Daney2c07ebb2013-08-01 13:22:33 -0700517 LONG_L k0, VCPU_HI(k1)
518 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800519
David Daney2c07ebb2013-08-01 13:22:33 -0700520 LONG_L k0, VCPU_LO(k1)
521 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800522
David Daney2c07ebb2013-08-01 13:22:33 -0700523 LONG_L k0, VCPU_R26(k1)
524 LONG_L k1, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800525
David Daney2c07ebb2013-08-01 13:22:33 -0700526 eret
Sanjay Lalb680f702012-11-21 18:34:01 -0800527
528__kvm_mips_return_to_host:
David Daney2c07ebb2013-08-01 13:22:33 -0700529 /* EBASE is already pointing to Linux */
530 LONG_L k1, VCPU_HOST_STACK(k1)
David Daneyea69f282013-08-01 13:22:35 -0700531 INT_ADDIU k1,k1, -PT_SIZE
Sanjay Lalb680f702012-11-21 18:34:01 -0800532
David Daney2c07ebb2013-08-01 13:22:33 -0700533 /* Restore host DDATA_LO */
534 LONG_L k0, PT_HOST_USERLOCAL(k1)
535 mtc0 k0, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800536
David Daney2c07ebb2013-08-01 13:22:33 -0700537 /* Restore host ASID */
538 LONG_L k0, PT_HOST_ASID(sp)
539 andi k0, 0xff
540 mtc0 k0,CP0_ENTRYHI
541 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800542
David Daney2c07ebb2013-08-01 13:22:33 -0700543 /* Load context saved on the host stack */
544 LONG_L $0, PT_R0(k1)
545 LONG_L $1, PT_R1(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800546
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700547 /*
548 * r2/v0 is the return code, shift it down by 2 (arithmetic)
549 * to recover the err code
550 */
David Daneyea69f282013-08-01 13:22:35 -0700551 INT_SRA k0, v0, 2
David Daney2c07ebb2013-08-01 13:22:33 -0700552 move $2, k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800553
David Daney2c07ebb2013-08-01 13:22:33 -0700554 LONG_L $3, PT_R3(k1)
555 LONG_L $4, PT_R4(k1)
556 LONG_L $5, PT_R5(k1)
557 LONG_L $6, PT_R6(k1)
558 LONG_L $7, PT_R7(k1)
559 LONG_L $8, PT_R8(k1)
560 LONG_L $9, PT_R9(k1)
561 LONG_L $10, PT_R10(k1)
562 LONG_L $11, PT_R11(k1)
563 LONG_L $12, PT_R12(k1)
564 LONG_L $13, PT_R13(k1)
565 LONG_L $14, PT_R14(k1)
566 LONG_L $15, PT_R15(k1)
567 LONG_L $16, PT_R16(k1)
568 LONG_L $17, PT_R17(k1)
569 LONG_L $18, PT_R18(k1)
570 LONG_L $19, PT_R19(k1)
571 LONG_L $20, PT_R20(k1)
572 LONG_L $21, PT_R21(k1)
573 LONG_L $22, PT_R22(k1)
574 LONG_L $23, PT_R23(k1)
575 LONG_L $24, PT_R24(k1)
576 LONG_L $25, PT_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800577
David Daney2c07ebb2013-08-01 13:22:33 -0700578 /* Host k0/k1 were not saved */
Sanjay Lalb680f702012-11-21 18:34:01 -0800579
David Daney2c07ebb2013-08-01 13:22:33 -0700580 LONG_L $28, PT_R28(k1)
581 LONG_L $29, PT_R29(k1)
582 LONG_L $30, PT_R30(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800583
David Daney2c07ebb2013-08-01 13:22:33 -0700584 LONG_L k0, PT_HI(k1)
585 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800586
David Daney2c07ebb2013-08-01 13:22:33 -0700587 LONG_L k0, PT_LO(k1)
588 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800589
David Daney2c07ebb2013-08-01 13:22:33 -0700590 /* Restore RDHWR access */
David Daneyea69f282013-08-01 13:22:35 -0700591 PTR_LI k0, 0x2000000F
David Daney2c07ebb2013-08-01 13:22:33 -0700592 mtc0 k0, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800593
David Daney2c07ebb2013-08-01 13:22:33 -0700594 /* Restore RA, which is the address we will return to */
595 LONG_L ra, PT_R31(k1)
596 j ra
597 nop
Sanjay Lalb680f702012-11-21 18:34:01 -0800598
Sanjay Lalb680f702012-11-21 18:34:01 -0800599VECTOR_END(MIPSX(GuestExceptionEnd))
600.end MIPSX(GuestException)
601
602MIPSX(exceptions):
603 ####
604 ##### The exception handlers.
605 #####
606 .word _C_LABEL(MIPSX(GuestException)) # 0
607 .word _C_LABEL(MIPSX(GuestException)) # 1
608 .word _C_LABEL(MIPSX(GuestException)) # 2
609 .word _C_LABEL(MIPSX(GuestException)) # 3
610 .word _C_LABEL(MIPSX(GuestException)) # 4
611 .word _C_LABEL(MIPSX(GuestException)) # 5
612 .word _C_LABEL(MIPSX(GuestException)) # 6
613 .word _C_LABEL(MIPSX(GuestException)) # 7
614 .word _C_LABEL(MIPSX(GuestException)) # 8
615 .word _C_LABEL(MIPSX(GuestException)) # 9
616 .word _C_LABEL(MIPSX(GuestException)) # 10
617 .word _C_LABEL(MIPSX(GuestException)) # 11
618 .word _C_LABEL(MIPSX(GuestException)) # 12
619 .word _C_LABEL(MIPSX(GuestException)) # 13
620 .word _C_LABEL(MIPSX(GuestException)) # 14
621 .word _C_LABEL(MIPSX(GuestException)) # 15
622 .word _C_LABEL(MIPSX(GuestException)) # 16
623 .word _C_LABEL(MIPSX(GuestException)) # 17
624 .word _C_LABEL(MIPSX(GuestException)) # 18
625 .word _C_LABEL(MIPSX(GuestException)) # 19
626 .word _C_LABEL(MIPSX(GuestException)) # 20
627 .word _C_LABEL(MIPSX(GuestException)) # 21
628 .word _C_LABEL(MIPSX(GuestException)) # 22
629 .word _C_LABEL(MIPSX(GuestException)) # 23
630 .word _C_LABEL(MIPSX(GuestException)) # 24
631 .word _C_LABEL(MIPSX(GuestException)) # 25
632 .word _C_LABEL(MIPSX(GuestException)) # 26
633 .word _C_LABEL(MIPSX(GuestException)) # 27
634 .word _C_LABEL(MIPSX(GuestException)) # 28
635 .word _C_LABEL(MIPSX(GuestException)) # 29
636 .word _C_LABEL(MIPSX(GuestException)) # 30
637 .word _C_LABEL(MIPSX(GuestException)) # 31