blob: 3ea522e4954b0c15d38791dffb1cbb0e0cfb9fec [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!! */
Sanjay Lalb680f702012-11-21 18:34:01 -080035#define PT_HOST_USERLOCAL PT_EPC
36
37#define CP0_DDATA_LO $28,3
Sanjay Lalb680f702012-11-21 18:34:01 -080038
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 */
David Daney2c07ebb2013-08-01 13:22:33 -070050 .set noreorder
51 .set noat
Sanjay Lalb680f702012-11-21 18:34:01 -080052
David Daneybb48c2f2013-08-01 13:22:34 -070053FEXPORT(__kvm_mips_vcpu_run)
David Daney2c07ebb2013-08-01 13:22:33 -070054 /* k0/k1 not being used in host kernel context */
David Daneyea69f282013-08-01 13:22:35 -070055 INT_ADDIU k1, sp, -PT_SIZE
David Daney2c07ebb2013-08-01 13:22:33 -070056 LONG_S $16, PT_R16(k1)
57 LONG_S $17, PT_R17(k1)
David Daney2c07ebb2013-08-01 13:22:33 -070058 LONG_S $18, PT_R18(k1)
59 LONG_S $19, PT_R19(k1)
60 LONG_S $20, PT_R20(k1)
61 LONG_S $21, PT_R21(k1)
62 LONG_S $22, PT_R22(k1)
63 LONG_S $23, PT_R23(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080064
David Daney2c07ebb2013-08-01 13:22:33 -070065 LONG_S $28, PT_R28(k1)
66 LONG_S $29, PT_R29(k1)
67 LONG_S $30, PT_R30(k1)
68 LONG_S $31, PT_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080069
David Daney2c07ebb2013-08-01 13:22:33 -070070 /* Save hi/lo */
71 mflo v0
72 LONG_S v0, PT_LO(k1)
73 mfhi v1
74 LONG_S v1, PT_HI(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080075
76 /* Save host status */
David Daney2c07ebb2013-08-01 13:22:33 -070077 mfc0 v0, CP0_STATUS
78 LONG_S v0, PT_STATUS(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080079
David Daney2c07ebb2013-08-01 13:22:33 -070080 /* Save DDATA_LO, will be used to store pointer to vcpu */
81 mfc0 v1, CP0_DDATA_LO
82 LONG_S v1, PT_HOST_USERLOCAL(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080083
David Daney2c07ebb2013-08-01 13:22:33 -070084 /* DDATA_LO has pointer to vcpu */
85 mtc0 a1, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -080086
David Daney2c07ebb2013-08-01 13:22:33 -070087 /* Offset into vcpu->arch */
David Daneyea69f282013-08-01 13:22:35 -070088 INT_ADDIU k1, a1, VCPU_HOST_ARCH
Sanjay Lalb680f702012-11-21 18:34:01 -080089
David Daney2c07ebb2013-08-01 13:22:33 -070090 /*
91 * Save the host stack to VCPU, used for exception processing
92 * when we exit from the Guest
93 */
94 LONG_S sp, VCPU_HOST_STACK(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080095
David Daney2c07ebb2013-08-01 13:22:33 -070096 /* Save the kernel gp as well */
97 LONG_S gp, VCPU_HOST_GP(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080098
Deng-Cheng Zhud116e812014-06-26 12:11:34 -070099 /*
100 * Setup status register for running the guest in UM, interrupts
101 * are disabled
102 */
David Daney2c07ebb2013-08-01 13:22:33 -0700103 li k0, (ST0_EXL | KSU_USER | ST0_BEV)
104 mtc0 k0, CP0_STATUS
105 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800106
David Daney2c07ebb2013-08-01 13:22:33 -0700107 /* load up the new EBASE */
108 LONG_L k0, VCPU_GUEST_EBASE(k1)
109 mtc0 k0, CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800110
David Daney2c07ebb2013-08-01 13:22:33 -0700111 /*
112 * Now that the new EBASE has been loaded, unset BEV, set
113 * interrupt mask as it was but make sure that timer interrupts
114 * are enabled
115 */
116 li k0, (ST0_EXL | KSU_USER | ST0_IE)
117 andi v0, v0, ST0_IM
118 or k0, k0, v0
119 mtc0 k0, CP0_STATUS
120 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800121
Sanjay Lalb680f702012-11-21 18:34:01 -0800122 /* Set Guest EPC */
David Daney2c07ebb2013-08-01 13:22:33 -0700123 LONG_L t0, VCPU_PC(k1)
124 mtc0 t0, CP0_EPC
Sanjay Lalb680f702012-11-21 18:34:01 -0800125
126FEXPORT(__kvm_mips_load_asid)
David Daney2c07ebb2013-08-01 13:22:33 -0700127 /* Set the ASID for the Guest Kernel */
James Hogan002374f2015-11-11 14:21:18 +0000128 PTR_L t0, VCPU_COP0(k1)
129 LONG_L t0, COP0_STATUS(t0)
130 andi t0, KSU_USER | ST0_ERL | ST0_EXL
131 xori t0, KSU_USER
132 bnez t0, 1f /* If kernel */
David Daneyea69f282013-08-01 13:22:35 -0700133 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
134 INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
Sanjay Lalb680f702012-11-21 18:34:01 -08001351:
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700136 /* t1: contains the base of the ASID array, need to get the cpu id */
David Daney2c07ebb2013-08-01 13:22:33 -0700137 LONG_L t2, TI_CPU($28) /* smp_processor_id */
David Daneyea69f282013-08-01 13:22:35 -0700138 INT_SLL t2, t2, 2 /* x4 */
139 REG_ADDU t3, t1, t2
David Daney2c07ebb2013-08-01 13:22:33 -0700140 LONG_L k0, (t3)
James Hogan9b5c3392016-05-06 14:36:19 +0100141 andi k0, k0, MIPS_ENTRYHI_ASID
David Daney2c07ebb2013-08-01 13:22:33 -0700142 mtc0 k0, CP0_ENTRYHI
143 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800144
David Daney2c07ebb2013-08-01 13:22:33 -0700145 /* Disable RDHWR access */
146 mtc0 zero, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800147
David Daney2c07ebb2013-08-01 13:22:33 -0700148 /* Now load up the Guest Context from VCPU */
149 LONG_L $1, VCPU_R1(k1)
150 LONG_L $2, VCPU_R2(k1)
151 LONG_L $3, VCPU_R3(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800152
David Daney2c07ebb2013-08-01 13:22:33 -0700153 LONG_L $4, VCPU_R4(k1)
154 LONG_L $5, VCPU_R5(k1)
155 LONG_L $6, VCPU_R6(k1)
156 LONG_L $7, VCPU_R7(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800157
David Daney2c07ebb2013-08-01 13:22:33 -0700158 LONG_L $8, VCPU_R8(k1)
159 LONG_L $9, VCPU_R9(k1)
160 LONG_L $10, VCPU_R10(k1)
161 LONG_L $11, VCPU_R11(k1)
162 LONG_L $12, VCPU_R12(k1)
163 LONG_L $13, VCPU_R13(k1)
164 LONG_L $14, VCPU_R14(k1)
165 LONG_L $15, VCPU_R15(k1)
166 LONG_L $16, VCPU_R16(k1)
167 LONG_L $17, VCPU_R17(k1)
168 LONG_L $18, VCPU_R18(k1)
169 LONG_L $19, VCPU_R19(k1)
170 LONG_L $20, VCPU_R20(k1)
171 LONG_L $21, VCPU_R21(k1)
172 LONG_L $22, VCPU_R22(k1)
173 LONG_L $23, VCPU_R23(k1)
174 LONG_L $24, VCPU_R24(k1)
175 LONG_L $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800176
David Daney2c07ebb2013-08-01 13:22:33 -0700177 /* k0/k1 loaded up later */
Sanjay Lalb680f702012-11-21 18:34:01 -0800178
David Daney2c07ebb2013-08-01 13:22:33 -0700179 LONG_L $28, VCPU_R28(k1)
180 LONG_L $29, VCPU_R29(k1)
181 LONG_L $30, VCPU_R30(k1)
182 LONG_L $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800183
David Daney2c07ebb2013-08-01 13:22:33 -0700184 /* Restore hi/lo */
185 LONG_L k0, VCPU_LO(k1)
186 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800187
David Daney2c07ebb2013-08-01 13:22:33 -0700188 LONG_L k0, VCPU_HI(k1)
189 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800190
191FEXPORT(__kvm_mips_load_k0k1)
192 /* Restore the guest's k0/k1 registers */
David Daney2c07ebb2013-08-01 13:22:33 -0700193 LONG_L k0, VCPU_R26(k1)
194 LONG_L k1, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800195
David Daney2c07ebb2013-08-01 13:22:33 -0700196 /* Jump to guest */
Sanjay Lalb680f702012-11-21 18:34:01 -0800197 eret
Sanjay Lalb680f702012-11-21 18:34:01 -0800198
199VECTOR(MIPSX(exception), unknown)
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700200/* Find out what mode we came from and jump to the proper handler. */
David Daney2c07ebb2013-08-01 13:22:33 -0700201 mtc0 k0, CP0_ERROREPC #01: Save guest k0
202 ehb #02:
Sanjay Lalb680f702012-11-21 18:34:01 -0800203
David Daney2c07ebb2013-08-01 13:22:33 -0700204 mfc0 k0, CP0_EBASE #02: Get EBASE
David Daneyea69f282013-08-01 13:22:35 -0700205 INT_SRL k0, k0, 10 #03: Get rid of CPUNum
206 INT_SLL k0, k0, 10 #04
David Daney2c07ebb2013-08-01 13:22:33 -0700207 LONG_S k1, 0x3000(k0) #05: Save k1 @ offset 0x3000
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700208 INT_ADDIU k0, k0, 0x2000 #06: Exception handler is
209 # installed @ offset 0x2000
David Daney2c07ebb2013-08-01 13:22:33 -0700210 j k0 #07: jump to the function
211 nop #08: branch delay slot
Sanjay Lalb680f702012-11-21 18:34:01 -0800212VECTOR_END(MIPSX(exceptionEnd))
213.end MIPSX(exception)
214
215/*
216 * Generic Guest exception handler. We end up here when the guest
217 * does something that causes a trap to kernel mode.
Sanjay Lalb680f702012-11-21 18:34:01 -0800218 */
219NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
David Daney2c07ebb2013-08-01 13:22:33 -0700220 /* Get the VCPU pointer from DDTATA_LO */
221 mfc0 k1, CP0_DDATA_LO
David Daneyea69f282013-08-01 13:22:35 -0700222 INT_ADDIU k1, k1, VCPU_HOST_ARCH
Sanjay Lalb680f702012-11-21 18:34:01 -0800223
David Daney2c07ebb2013-08-01 13:22:33 -0700224 /* Start saving Guest context to VCPU */
225 LONG_S $0, VCPU_R0(k1)
226 LONG_S $1, VCPU_R1(k1)
227 LONG_S $2, VCPU_R2(k1)
228 LONG_S $3, VCPU_R3(k1)
229 LONG_S $4, VCPU_R4(k1)
230 LONG_S $5, VCPU_R5(k1)
231 LONG_S $6, VCPU_R6(k1)
232 LONG_S $7, VCPU_R7(k1)
233 LONG_S $8, VCPU_R8(k1)
234 LONG_S $9, VCPU_R9(k1)
235 LONG_S $10, VCPU_R10(k1)
236 LONG_S $11, VCPU_R11(k1)
237 LONG_S $12, VCPU_R12(k1)
238 LONG_S $13, VCPU_R13(k1)
239 LONG_S $14, VCPU_R14(k1)
240 LONG_S $15, VCPU_R15(k1)
241 LONG_S $16, VCPU_R16(k1)
242 LONG_S $17, VCPU_R17(k1)
243 LONG_S $18, VCPU_R18(k1)
244 LONG_S $19, VCPU_R19(k1)
245 LONG_S $20, VCPU_R20(k1)
246 LONG_S $21, VCPU_R21(k1)
247 LONG_S $22, VCPU_R22(k1)
248 LONG_S $23, VCPU_R23(k1)
249 LONG_S $24, VCPU_R24(k1)
250 LONG_S $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800251
David Daney2c07ebb2013-08-01 13:22:33 -0700252 /* Guest k0/k1 saved later */
Sanjay Lalb680f702012-11-21 18:34:01 -0800253
David Daney2c07ebb2013-08-01 13:22:33 -0700254 LONG_S $28, VCPU_R28(k1)
255 LONG_S $29, VCPU_R29(k1)
256 LONG_S $30, VCPU_R30(k1)
257 LONG_S $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800258
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700259 /* We need to save hi/lo and restore them on the way out */
David Daney2c07ebb2013-08-01 13:22:33 -0700260 mfhi t0
261 LONG_S t0, VCPU_HI(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800262
David Daney2c07ebb2013-08-01 13:22:33 -0700263 mflo t0
264 LONG_S t0, VCPU_LO(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800265
David Daney2c07ebb2013-08-01 13:22:33 -0700266 /* Finally save guest k0/k1 to VCPU */
267 mfc0 t0, CP0_ERROREPC
268 LONG_S t0, VCPU_R26(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800269
David Daney2c07ebb2013-08-01 13:22:33 -0700270 /* Get GUEST k1 and save it in VCPU */
David Daneyea69f282013-08-01 13:22:35 -0700271 PTR_LI t1, ~0x2ff
David Daney2c07ebb2013-08-01 13:22:33 -0700272 mfc0 t0, CP0_EBASE
273 and t0, t0, t1
274 LONG_L t0, 0x3000(t0)
275 LONG_S t0, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800276
David Daney2c07ebb2013-08-01 13:22:33 -0700277 /* Now that context has been saved, we can use other registers */
Sanjay Lalb680f702012-11-21 18:34:01 -0800278
David Daney2c07ebb2013-08-01 13:22:33 -0700279 /* Restore vcpu */
280 mfc0 a1, CP0_DDATA_LO
281 move s1, a1
Sanjay Lalb680f702012-11-21 18:34:01 -0800282
David Daney2c07ebb2013-08-01 13:22:33 -0700283 /* Restore run (vcpu->run) */
284 LONG_L a0, VCPU_RUN(a1)
285 /* Save pointer to run in s0, will be saved by the compiler */
286 move s0, a0
287
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700288 /*
289 * Save Host level EPC, BadVaddr and Cause to VCPU, useful to
290 * process the exception
291 */
David Daney2c07ebb2013-08-01 13:22:33 -0700292 mfc0 k0,CP0_EPC
293 LONG_S k0, VCPU_PC(k1)
294
295 mfc0 k0, CP0_BADVADDR
296 LONG_S k0, VCPU_HOST_CP0_BADVADDR(k1)
297
298 mfc0 k0, CP0_CAUSE
299 LONG_S k0, VCPU_HOST_CP0_CAUSE(k1)
300
301 mfc0 k0, CP0_ENTRYHI
302 LONG_S k0, VCPU_HOST_ENTRYHI(k1)
303
304 /* Now restore the host state just enough to run the handlers */
305
James Hogancaa1faa2015-12-16 23:49:26 +0000306 /* Switch EBASE to the one used by Linux */
David Daney2c07ebb2013-08-01 13:22:33 -0700307 /* load up the host EBASE */
308 mfc0 v0, CP0_STATUS
309
310 .set at
311 or k0, v0, ST0_BEV
312 .set noat
313
314 mtc0 k0, CP0_STATUS
315 ehb
316
317 LONG_L k0, VCPU_HOST_EBASE(k1)
318 mtc0 k0,CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800319
James Hogan98e91b82014-11-18 14:09:12 +0000320 /*
321 * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
322 * trigger FPE for pending exceptions.
323 */
324 .set at
325 and v1, v0, ST0_CU1
326 beqz v1, 1f
327 nop
328 .set push
329 SET_HARDFLOAT
330 cfc1 t0, fcr31
331 sw t0, VCPU_FCR31(k1)
332 ctc1 zero,fcr31
333 .set pop
334 .set noat
3351:
336
James Hogan539cb89fb2015-03-05 11:43:36 +0000337#ifdef CONFIG_CPU_HAS_MSA
338 /*
339 * If MSA is enabled, save MSACSR and clear it so that later
340 * instructions don't trigger MSAFPE for pending exceptions.
341 */
342 mfc0 t0, CP0_CONFIG3
343 ext t0, t0, 28, 1 /* MIPS_CONF3_MSAP */
344 beqz t0, 1f
345 nop
346 mfc0 t0, CP0_CONFIG5
347 ext t0, t0, 27, 1 /* MIPS_CONF5_MSAEN */
348 beqz t0, 1f
349 nop
350 _cfcmsa t0, MSA_CSR
351 sw t0, VCPU_MSA_CSR(k1)
352 _ctcmsa MSA_CSR, zero
3531:
354#endif
355
David Daney2c07ebb2013-08-01 13:22:33 -0700356 /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
357 .set at
358 and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
359 or v0, v0, ST0_CU0
360 .set noat
361 mtc0 v0, CP0_STATUS
362 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800363
David Daney2c07ebb2013-08-01 13:22:33 -0700364 /* Load up host GP */
365 LONG_L gp, VCPU_HOST_GP(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800366
David Daney2c07ebb2013-08-01 13:22:33 -0700367 /* Need a stack before we can jump to "C" */
368 LONG_L sp, VCPU_HOST_STACK(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800369
David Daney2c07ebb2013-08-01 13:22:33 -0700370 /* Saved host state */
David Daneyea69f282013-08-01 13:22:35 -0700371 INT_ADDIU sp, sp, -PT_SIZE
Sanjay Lalb680f702012-11-21 18:34:01 -0800372
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700373 /*
374 * XXXKYMA do we need to load the host ASID, maybe not because the
David Daney2c07ebb2013-08-01 13:22:33 -0700375 * kernel entries are marked GLOBAL, need to verify
376 */
Sanjay Lalb680f702012-11-21 18:34:01 -0800377
David Daney2c07ebb2013-08-01 13:22:33 -0700378 /* Restore host DDATA_LO */
379 LONG_L k0, PT_HOST_USERLOCAL(sp)
380 mtc0 k0, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800381
David Daney2c07ebb2013-08-01 13:22:33 -0700382 /* Restore RDHWR access */
David Daneyea69f282013-08-01 13:22:35 -0700383 PTR_LI k0, 0x2000000F
David Daney2c07ebb2013-08-01 13:22:33 -0700384 mtc0 k0, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800385
David Daney2c07ebb2013-08-01 13:22:33 -0700386 /* Jump to handler */
Sanjay Lalb680f702012-11-21 18:34:01 -0800387FEXPORT(__kvm_mips_jump_to_handler)
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700388 /*
389 * XXXKYMA: not sure if this is safe, how large is the stack??
David Daney2c07ebb2013-08-01 13:22:33 -0700390 * Now jump to the kvm_mips_handle_exit() to see if we can deal
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700391 * with this in the kernel
392 */
David Daneyea69f282013-08-01 13:22:35 -0700393 PTR_LA t9, kvm_mips_handle_exit
David Daney2c07ebb2013-08-01 13:22:33 -0700394 jalr.hb t9
David Daneyea69f282013-08-01 13:22:35 -0700395 INT_ADDIU sp, sp, -CALLFRAME_SIZ /* BD Slot */
Sanjay Lalb680f702012-11-21 18:34:01 -0800396
David Daney2c07ebb2013-08-01 13:22:33 -0700397 /* Return from handler Make sure interrupts are disabled */
398 di
399 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800400
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700401 /*
402 * XXXKYMA: k0/k1 could have been blown away if we processed
David Daney2c07ebb2013-08-01 13:22:33 -0700403 * an exception while we were handling the exception from the
404 * guest, reload k1
405 */
Sanjay Lalb680f702012-11-21 18:34:01 -0800406
David Daney2c07ebb2013-08-01 13:22:33 -0700407 move k1, s1
David Daneyea69f282013-08-01 13:22:35 -0700408 INT_ADDIU k1, k1, VCPU_HOST_ARCH
David Daney2c07ebb2013-08-01 13:22:33 -0700409
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700410 /*
411 * Check return value, should tell us if we are returning to the
David Daney2c07ebb2013-08-01 13:22:33 -0700412 * host (handle I/O etc)or resuming the guest
413 */
414 andi t0, v0, RESUME_HOST
415 bnez t0, __kvm_mips_return_to_host
416 nop
Sanjay Lalb680f702012-11-21 18:34:01 -0800417
418__kvm_mips_return_to_guest:
David Daney2c07ebb2013-08-01 13:22:33 -0700419 /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
420 mtc0 s1, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800421
David Daney2c07ebb2013-08-01 13:22:33 -0700422 /* Load up the Guest EBASE to minimize the window where BEV is set */
423 LONG_L t0, VCPU_GUEST_EBASE(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800424
David Daney2c07ebb2013-08-01 13:22:33 -0700425 /* Switch EBASE back to the one used by KVM */
426 mfc0 v1, CP0_STATUS
427 .set at
428 or k0, v1, ST0_BEV
429 .set noat
430 mtc0 k0, CP0_STATUS
431 ehb
432 mtc0 t0, CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800433
David Daney2c07ebb2013-08-01 13:22:33 -0700434 /* Setup status register for running guest in UM */
435 .set at
436 or v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
James Hoganf7982172015-02-04 17:06:37 +0000437 and v1, v1, ~(ST0_CU0 | ST0_MX)
David Daney2c07ebb2013-08-01 13:22:33 -0700438 .set noat
439 mtc0 v1, CP0_STATUS
440 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800441
442 /* Set Guest EPC */
David Daney2c07ebb2013-08-01 13:22:33 -0700443 LONG_L t0, VCPU_PC(k1)
444 mtc0 t0, CP0_EPC
Sanjay Lalb680f702012-11-21 18:34:01 -0800445
David Daney2c07ebb2013-08-01 13:22:33 -0700446 /* Set the ASID for the Guest Kernel */
James Hogan002374f2015-11-11 14:21:18 +0000447 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 */
David Daneyea69f282013-08-01 13:22:35 -0700452 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
453 INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
Sanjay Lalb680f702012-11-21 18:34:01 -08004541:
David Daney2c07ebb2013-08-01 13:22:33 -0700455 /* t1: contains the base of the ASID array, need to get the cpu id */
456 LONG_L t2, TI_CPU($28) /* smp_processor_id */
David Daneyea69f282013-08-01 13:22:35 -0700457 INT_SLL t2, t2, 2 /* x4 */
458 REG_ADDU t3, t1, t2
David Daney2c07ebb2013-08-01 13:22:33 -0700459 LONG_L k0, (t3)
James Hogan9b5c3392016-05-06 14:36:19 +0100460 andi k0, k0, MIPS_ENTRYHI_ASID
James Hogancaa1faa2015-12-16 23:49:26 +0000461 mtc0 k0, CP0_ENTRYHI
David Daney2c07ebb2013-08-01 13:22:33 -0700462 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800463
David Daney2c07ebb2013-08-01 13:22:33 -0700464 /* Disable RDHWR access */
James Hogancaa1faa2015-12-16 23:49:26 +0000465 mtc0 zero, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800466
David Daney2c07ebb2013-08-01 13:22:33 -0700467 /* load the guest context from VCPU and return */
468 LONG_L $0, VCPU_R0(k1)
469 LONG_L $1, VCPU_R1(k1)
470 LONG_L $2, VCPU_R2(k1)
471 LONG_L $3, VCPU_R3(k1)
472 LONG_L $4, VCPU_R4(k1)
473 LONG_L $5, VCPU_R5(k1)
474 LONG_L $6, VCPU_R6(k1)
475 LONG_L $7, VCPU_R7(k1)
476 LONG_L $8, VCPU_R8(k1)
477 LONG_L $9, VCPU_R9(k1)
478 LONG_L $10, VCPU_R10(k1)
479 LONG_L $11, VCPU_R11(k1)
480 LONG_L $12, VCPU_R12(k1)
481 LONG_L $13, VCPU_R13(k1)
482 LONG_L $14, VCPU_R14(k1)
483 LONG_L $15, VCPU_R15(k1)
484 LONG_L $16, VCPU_R16(k1)
485 LONG_L $17, VCPU_R17(k1)
486 LONG_L $18, VCPU_R18(k1)
487 LONG_L $19, VCPU_R19(k1)
488 LONG_L $20, VCPU_R20(k1)
489 LONG_L $21, VCPU_R21(k1)
490 LONG_L $22, VCPU_R22(k1)
491 LONG_L $23, VCPU_R23(k1)
492 LONG_L $24, VCPU_R24(k1)
493 LONG_L $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800494
David Daney2c07ebb2013-08-01 13:22:33 -0700495 /* $/k1 loaded later */
496 LONG_L $28, VCPU_R28(k1)
497 LONG_L $29, VCPU_R29(k1)
498 LONG_L $30, VCPU_R30(k1)
499 LONG_L $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800500
501FEXPORT(__kvm_mips_skip_guest_restore)
David Daney2c07ebb2013-08-01 13:22:33 -0700502 LONG_L k0, VCPU_HI(k1)
503 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800504
David Daney2c07ebb2013-08-01 13:22:33 -0700505 LONG_L k0, VCPU_LO(k1)
506 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800507
David Daney2c07ebb2013-08-01 13:22:33 -0700508 LONG_L k0, VCPU_R26(k1)
509 LONG_L k1, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800510
David Daney2c07ebb2013-08-01 13:22:33 -0700511 eret
Sanjay Lalb680f702012-11-21 18:34:01 -0800512
513__kvm_mips_return_to_host:
David Daney2c07ebb2013-08-01 13:22:33 -0700514 /* EBASE is already pointing to Linux */
515 LONG_L k1, VCPU_HOST_STACK(k1)
David Daneyea69f282013-08-01 13:22:35 -0700516 INT_ADDIU k1,k1, -PT_SIZE
Sanjay Lalb680f702012-11-21 18:34:01 -0800517
David Daney2c07ebb2013-08-01 13:22:33 -0700518 /* Restore host DDATA_LO */
519 LONG_L k0, PT_HOST_USERLOCAL(k1)
520 mtc0 k0, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800521
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700522 /*
523 * r2/v0 is the return code, shift it down by 2 (arithmetic)
524 * to recover the err code
525 */
David Daneyea69f282013-08-01 13:22:35 -0700526 INT_SRA k0, v0, 2
David Daney2c07ebb2013-08-01 13:22:33 -0700527 move $2, k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800528
James Hogan1300fcd2016-05-06 14:36:21 +0100529 /* Load context saved on the host stack */
David Daney2c07ebb2013-08-01 13:22:33 -0700530 LONG_L $16, PT_R16(k1)
531 LONG_L $17, PT_R17(k1)
532 LONG_L $18, PT_R18(k1)
533 LONG_L $19, PT_R19(k1)
534 LONG_L $20, PT_R20(k1)
535 LONG_L $21, PT_R21(k1)
536 LONG_L $22, PT_R22(k1)
537 LONG_L $23, PT_R23(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800538
David Daney2c07ebb2013-08-01 13:22:33 -0700539 LONG_L $28, PT_R28(k1)
540 LONG_L $29, PT_R29(k1)
541 LONG_L $30, PT_R30(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800542
David Daney2c07ebb2013-08-01 13:22:33 -0700543 LONG_L k0, PT_HI(k1)
544 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800545
David Daney2c07ebb2013-08-01 13:22:33 -0700546 LONG_L k0, PT_LO(k1)
547 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800548
David Daney2c07ebb2013-08-01 13:22:33 -0700549 /* Restore RDHWR access */
David Daneyea69f282013-08-01 13:22:35 -0700550 PTR_LI k0, 0x2000000F
James Hogancaa1faa2015-12-16 23:49:26 +0000551 mtc0 k0, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800552
David Daney2c07ebb2013-08-01 13:22:33 -0700553 /* Restore RA, which is the address we will return to */
James Hogancaa1faa2015-12-16 23:49:26 +0000554 LONG_L ra, PT_R31(k1)
555 j ra
David Daney2c07ebb2013-08-01 13:22:33 -0700556 nop
Sanjay Lalb680f702012-11-21 18:34:01 -0800557
Sanjay Lalb680f702012-11-21 18:34:01 -0800558VECTOR_END(MIPSX(GuestExceptionEnd))
559.end MIPSX(GuestException)
560
561MIPSX(exceptions):
562 ####
563 ##### The exception handlers.
564 #####
565 .word _C_LABEL(MIPSX(GuestException)) # 0
566 .word _C_LABEL(MIPSX(GuestException)) # 1
567 .word _C_LABEL(MIPSX(GuestException)) # 2
568 .word _C_LABEL(MIPSX(GuestException)) # 3
569 .word _C_LABEL(MIPSX(GuestException)) # 4
570 .word _C_LABEL(MIPSX(GuestException)) # 5
571 .word _C_LABEL(MIPSX(GuestException)) # 6
572 .word _C_LABEL(MIPSX(GuestException)) # 7
573 .word _C_LABEL(MIPSX(GuestException)) # 8
574 .word _C_LABEL(MIPSX(GuestException)) # 9
575 .word _C_LABEL(MIPSX(GuestException)) # 10
576 .word _C_LABEL(MIPSX(GuestException)) # 11
577 .word _C_LABEL(MIPSX(GuestException)) # 12
578 .word _C_LABEL(MIPSX(GuestException)) # 13
579 .word _C_LABEL(MIPSX(GuestException)) # 14
580 .word _C_LABEL(MIPSX(GuestException)) # 15
581 .word _C_LABEL(MIPSX(GuestException)) # 16
582 .word _C_LABEL(MIPSX(GuestException)) # 17
583 .word _C_LABEL(MIPSX(GuestException)) # 18
584 .word _C_LABEL(MIPSX(GuestException)) # 19
585 .word _C_LABEL(MIPSX(GuestException)) # 20
586 .word _C_LABEL(MIPSX(GuestException)) # 21
587 .word _C_LABEL(MIPSX(GuestException)) # 22
588 .word _C_LABEL(MIPSX(GuestException)) # 23
589 .word _C_LABEL(MIPSX(GuestException)) # 24
590 .word _C_LABEL(MIPSX(GuestException)) # 25
591 .word _C_LABEL(MIPSX(GuestException)) # 26
592 .word _C_LABEL(MIPSX(GuestException)) # 27
593 .word _C_LABEL(MIPSX(GuestException)) # 28
594 .word _C_LABEL(MIPSX(GuestException)) # 29
595 .word _C_LABEL(MIPSX(GuestException)) # 30
596 .word _C_LABEL(MIPSX(GuestException)) # 31