blob: c567240386a0f10818b0e06433f4b33b1bf5e6dc [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
James Hogan539cb89fb2015-03-05 11:43:36 +000039#define CP0_CONFIG3 $16,3
40#define CP0_CONFIG5 $16,5
Sanjay Lalb680f702012-11-21 18:34:01 -080041#define CP0_EBASE $15,1
42
43#define CP0_INTCTL $12,1
44#define CP0_SRSCTL $12,2
45#define CP0_SRSMAP $12,3
46#define CP0_HWRENA $7,0
47
48/* Resume Flags */
49#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
50
51#define RESUME_GUEST 0
52#define RESUME_HOST RESUME_FLAG_HOST
53
54/*
55 * __kvm_mips_vcpu_run: entry point to the guest
56 * a0: run
57 * a1: vcpu
58 */
David Daney2c07ebb2013-08-01 13:22:33 -070059 .set noreorder
60 .set noat
Sanjay Lalb680f702012-11-21 18:34:01 -080061
David Daneybb48c2f2013-08-01 13:22:34 -070062FEXPORT(__kvm_mips_vcpu_run)
David Daney2c07ebb2013-08-01 13:22:33 -070063 /* k0/k1 not being used in host kernel context */
David Daneyea69f282013-08-01 13:22:35 -070064 INT_ADDIU k1, sp, -PT_SIZE
David Daney2c07ebb2013-08-01 13:22:33 -070065 LONG_S $0, PT_R0(k1)
66 LONG_S $1, PT_R1(k1)
67 LONG_S $2, PT_R2(k1)
68 LONG_S $3, PT_R3(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080069
David Daney2c07ebb2013-08-01 13:22:33 -070070 LONG_S $4, PT_R4(k1)
71 LONG_S $5, PT_R5(k1)
72 LONG_S $6, PT_R6(k1)
73 LONG_S $7, PT_R7(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080074
David Daney2c07ebb2013-08-01 13:22:33 -070075 LONG_S $8, PT_R8(k1)
76 LONG_S $9, PT_R9(k1)
77 LONG_S $10, PT_R10(k1)
78 LONG_S $11, PT_R11(k1)
79 LONG_S $12, PT_R12(k1)
80 LONG_S $13, PT_R13(k1)
81 LONG_S $14, PT_R14(k1)
82 LONG_S $15, PT_R15(k1)
83 LONG_S $16, PT_R16(k1)
84 LONG_S $17, PT_R17(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080085
David Daney2c07ebb2013-08-01 13:22:33 -070086 LONG_S $18, PT_R18(k1)
87 LONG_S $19, PT_R19(k1)
88 LONG_S $20, PT_R20(k1)
89 LONG_S $21, PT_R21(k1)
90 LONG_S $22, PT_R22(k1)
91 LONG_S $23, PT_R23(k1)
92 LONG_S $24, PT_R24(k1)
93 LONG_S $25, PT_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080094
Deng-Cheng Zhud116e812014-06-26 12:11:34 -070095 /*
96 * XXXKYMA k0/k1 not saved, not being used if we got here through
97 * an ioctl()
98 */
Sanjay Lalb680f702012-11-21 18:34:01 -080099
David Daney2c07ebb2013-08-01 13:22:33 -0700100 LONG_S $28, PT_R28(k1)
101 LONG_S $29, PT_R29(k1)
102 LONG_S $30, PT_R30(k1)
103 LONG_S $31, PT_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800104
David Daney2c07ebb2013-08-01 13:22:33 -0700105 /* Save hi/lo */
106 mflo v0
107 LONG_S v0, PT_LO(k1)
108 mfhi v1
109 LONG_S v1, PT_HI(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800110
111 /* Save host status */
David Daney2c07ebb2013-08-01 13:22:33 -0700112 mfc0 v0, CP0_STATUS
113 LONG_S v0, PT_STATUS(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800114
115 /* Save host ASID, shove it into the BVADDR location */
David Daney2c07ebb2013-08-01 13:22:33 -0700116 mfc0 v1, CP0_ENTRYHI
117 andi v1, 0xff
118 LONG_S v1, PT_HOST_ASID(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800119
David Daney2c07ebb2013-08-01 13:22:33 -0700120 /* Save DDATA_LO, will be used to store pointer to vcpu */
121 mfc0 v1, CP0_DDATA_LO
122 LONG_S v1, PT_HOST_USERLOCAL(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800123
David Daney2c07ebb2013-08-01 13:22:33 -0700124 /* DDATA_LO has pointer to vcpu */
125 mtc0 a1, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800126
David Daney2c07ebb2013-08-01 13:22:33 -0700127 /* Offset into vcpu->arch */
David Daneyea69f282013-08-01 13:22:35 -0700128 INT_ADDIU k1, a1, VCPU_HOST_ARCH
Sanjay Lalb680f702012-11-21 18:34:01 -0800129
David Daney2c07ebb2013-08-01 13:22:33 -0700130 /*
131 * Save the host stack to VCPU, used for exception processing
132 * when we exit from the Guest
133 */
134 LONG_S sp, VCPU_HOST_STACK(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800135
David Daney2c07ebb2013-08-01 13:22:33 -0700136 /* Save the kernel gp as well */
137 LONG_S gp, VCPU_HOST_GP(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800138
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700139 /*
140 * Setup status register for running the guest in UM, interrupts
141 * are disabled
142 */
David Daney2c07ebb2013-08-01 13:22:33 -0700143 li k0, (ST0_EXL | KSU_USER | ST0_BEV)
144 mtc0 k0, CP0_STATUS
145 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800146
David Daney2c07ebb2013-08-01 13:22:33 -0700147 /* load up the new EBASE */
148 LONG_L k0, VCPU_GUEST_EBASE(k1)
149 mtc0 k0, CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800150
David Daney2c07ebb2013-08-01 13:22:33 -0700151 /*
152 * Now that the new EBASE has been loaded, unset BEV, set
153 * interrupt mask as it was but make sure that timer interrupts
154 * are enabled
155 */
156 li k0, (ST0_EXL | KSU_USER | ST0_IE)
157 andi v0, v0, ST0_IM
158 or k0, k0, v0
159 mtc0 k0, CP0_STATUS
160 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800161
Sanjay Lalb680f702012-11-21 18:34:01 -0800162 /* Set Guest EPC */
David Daney2c07ebb2013-08-01 13:22:33 -0700163 LONG_L t0, VCPU_PC(k1)
164 mtc0 t0, CP0_EPC
Sanjay Lalb680f702012-11-21 18:34:01 -0800165
166FEXPORT(__kvm_mips_load_asid)
David Daney2c07ebb2013-08-01 13:22:33 -0700167 /* Set the ASID for the Guest Kernel */
David Daneyea69f282013-08-01 13:22:35 -0700168 INT_SLL t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
David Daney2c07ebb2013-08-01 13:22:33 -0700169 /* addresses shift to 0x80000000 */
170 bltz t0, 1f /* If kernel */
David Daneyea69f282013-08-01 13:22:35 -0700171 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
172 INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
Sanjay Lalb680f702012-11-21 18:34:01 -08001731:
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700174 /* t1: contains the base of the ASID array, need to get the cpu id */
David Daney2c07ebb2013-08-01 13:22:33 -0700175 LONG_L t2, TI_CPU($28) /* smp_processor_id */
David Daneyea69f282013-08-01 13:22:35 -0700176 INT_SLL t2, t2, 2 /* x4 */
177 REG_ADDU t3, t1, t2
David Daney2c07ebb2013-08-01 13:22:33 -0700178 LONG_L k0, (t3)
179 andi k0, k0, 0xff
180 mtc0 k0, CP0_ENTRYHI
181 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800182
David Daney2c07ebb2013-08-01 13:22:33 -0700183 /* Disable RDHWR access */
184 mtc0 zero, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800185
David Daney2c07ebb2013-08-01 13:22:33 -0700186 /* Now load up the Guest Context from VCPU */
187 LONG_L $1, VCPU_R1(k1)
188 LONG_L $2, VCPU_R2(k1)
189 LONG_L $3, VCPU_R3(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800190
David Daney2c07ebb2013-08-01 13:22:33 -0700191 LONG_L $4, VCPU_R4(k1)
192 LONG_L $5, VCPU_R5(k1)
193 LONG_L $6, VCPU_R6(k1)
194 LONG_L $7, VCPU_R7(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800195
David Daney2c07ebb2013-08-01 13:22:33 -0700196 LONG_L $8, VCPU_R8(k1)
197 LONG_L $9, VCPU_R9(k1)
198 LONG_L $10, VCPU_R10(k1)
199 LONG_L $11, VCPU_R11(k1)
200 LONG_L $12, VCPU_R12(k1)
201 LONG_L $13, VCPU_R13(k1)
202 LONG_L $14, VCPU_R14(k1)
203 LONG_L $15, VCPU_R15(k1)
204 LONG_L $16, VCPU_R16(k1)
205 LONG_L $17, VCPU_R17(k1)
206 LONG_L $18, VCPU_R18(k1)
207 LONG_L $19, VCPU_R19(k1)
208 LONG_L $20, VCPU_R20(k1)
209 LONG_L $21, VCPU_R21(k1)
210 LONG_L $22, VCPU_R22(k1)
211 LONG_L $23, VCPU_R23(k1)
212 LONG_L $24, VCPU_R24(k1)
213 LONG_L $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800214
David Daney2c07ebb2013-08-01 13:22:33 -0700215 /* k0/k1 loaded up later */
Sanjay Lalb680f702012-11-21 18:34:01 -0800216
David Daney2c07ebb2013-08-01 13:22:33 -0700217 LONG_L $28, VCPU_R28(k1)
218 LONG_L $29, VCPU_R29(k1)
219 LONG_L $30, VCPU_R30(k1)
220 LONG_L $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800221
David Daney2c07ebb2013-08-01 13:22:33 -0700222 /* Restore hi/lo */
223 LONG_L k0, VCPU_LO(k1)
224 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800225
David Daney2c07ebb2013-08-01 13:22:33 -0700226 LONG_L k0, VCPU_HI(k1)
227 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800228
229FEXPORT(__kvm_mips_load_k0k1)
230 /* Restore the guest's k0/k1 registers */
David Daney2c07ebb2013-08-01 13:22:33 -0700231 LONG_L k0, VCPU_R26(k1)
232 LONG_L k1, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800233
David Daney2c07ebb2013-08-01 13:22:33 -0700234 /* Jump to guest */
Sanjay Lalb680f702012-11-21 18:34:01 -0800235 eret
Sanjay Lalb680f702012-11-21 18:34:01 -0800236
237VECTOR(MIPSX(exception), unknown)
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700238/* Find out what mode we came from and jump to the proper handler. */
David Daney2c07ebb2013-08-01 13:22:33 -0700239 mtc0 k0, CP0_ERROREPC #01: Save guest k0
240 ehb #02:
Sanjay Lalb680f702012-11-21 18:34:01 -0800241
David Daney2c07ebb2013-08-01 13:22:33 -0700242 mfc0 k0, CP0_EBASE #02: Get EBASE
David Daneyea69f282013-08-01 13:22:35 -0700243 INT_SRL k0, k0, 10 #03: Get rid of CPUNum
244 INT_SLL k0, k0, 10 #04
David Daney2c07ebb2013-08-01 13:22:33 -0700245 LONG_S k1, 0x3000(k0) #05: Save k1 @ offset 0x3000
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700246 INT_ADDIU k0, k0, 0x2000 #06: Exception handler is
247 # installed @ offset 0x2000
David Daney2c07ebb2013-08-01 13:22:33 -0700248 j k0 #07: jump to the function
249 nop #08: branch delay slot
Sanjay Lalb680f702012-11-21 18:34:01 -0800250VECTOR_END(MIPSX(exceptionEnd))
251.end MIPSX(exception)
252
253/*
254 * Generic Guest exception handler. We end up here when the guest
255 * does something that causes a trap to kernel mode.
Sanjay Lalb680f702012-11-21 18:34:01 -0800256 */
257NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
David Daney2c07ebb2013-08-01 13:22:33 -0700258 /* Get the VCPU pointer from DDTATA_LO */
259 mfc0 k1, CP0_DDATA_LO
David Daneyea69f282013-08-01 13:22:35 -0700260 INT_ADDIU k1, k1, VCPU_HOST_ARCH
Sanjay Lalb680f702012-11-21 18:34:01 -0800261
David Daney2c07ebb2013-08-01 13:22:33 -0700262 /* Start saving Guest context to VCPU */
263 LONG_S $0, VCPU_R0(k1)
264 LONG_S $1, VCPU_R1(k1)
265 LONG_S $2, VCPU_R2(k1)
266 LONG_S $3, VCPU_R3(k1)
267 LONG_S $4, VCPU_R4(k1)
268 LONG_S $5, VCPU_R5(k1)
269 LONG_S $6, VCPU_R6(k1)
270 LONG_S $7, VCPU_R7(k1)
271 LONG_S $8, VCPU_R8(k1)
272 LONG_S $9, VCPU_R9(k1)
273 LONG_S $10, VCPU_R10(k1)
274 LONG_S $11, VCPU_R11(k1)
275 LONG_S $12, VCPU_R12(k1)
276 LONG_S $13, VCPU_R13(k1)
277 LONG_S $14, VCPU_R14(k1)
278 LONG_S $15, VCPU_R15(k1)
279 LONG_S $16, VCPU_R16(k1)
280 LONG_S $17, VCPU_R17(k1)
281 LONG_S $18, VCPU_R18(k1)
282 LONG_S $19, VCPU_R19(k1)
283 LONG_S $20, VCPU_R20(k1)
284 LONG_S $21, VCPU_R21(k1)
285 LONG_S $22, VCPU_R22(k1)
286 LONG_S $23, VCPU_R23(k1)
287 LONG_S $24, VCPU_R24(k1)
288 LONG_S $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800289
David Daney2c07ebb2013-08-01 13:22:33 -0700290 /* Guest k0/k1 saved later */
Sanjay Lalb680f702012-11-21 18:34:01 -0800291
David Daney2c07ebb2013-08-01 13:22:33 -0700292 LONG_S $28, VCPU_R28(k1)
293 LONG_S $29, VCPU_R29(k1)
294 LONG_S $30, VCPU_R30(k1)
295 LONG_S $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800296
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700297 /* We need to save hi/lo and restore them on the way out */
David Daney2c07ebb2013-08-01 13:22:33 -0700298 mfhi t0
299 LONG_S t0, VCPU_HI(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800300
David Daney2c07ebb2013-08-01 13:22:33 -0700301 mflo t0
302 LONG_S t0, VCPU_LO(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800303
David Daney2c07ebb2013-08-01 13:22:33 -0700304 /* Finally save guest k0/k1 to VCPU */
305 mfc0 t0, CP0_ERROREPC
306 LONG_S t0, VCPU_R26(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800307
David Daney2c07ebb2013-08-01 13:22:33 -0700308 /* Get GUEST k1 and save it in VCPU */
David Daneyea69f282013-08-01 13:22:35 -0700309 PTR_LI t1, ~0x2ff
David Daney2c07ebb2013-08-01 13:22:33 -0700310 mfc0 t0, CP0_EBASE
311 and t0, t0, t1
312 LONG_L t0, 0x3000(t0)
313 LONG_S t0, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800314
David Daney2c07ebb2013-08-01 13:22:33 -0700315 /* Now that context has been saved, we can use other registers */
Sanjay Lalb680f702012-11-21 18:34:01 -0800316
David Daney2c07ebb2013-08-01 13:22:33 -0700317 /* Restore vcpu */
318 mfc0 a1, CP0_DDATA_LO
319 move s1, a1
Sanjay Lalb680f702012-11-21 18:34:01 -0800320
David Daney2c07ebb2013-08-01 13:22:33 -0700321 /* Restore run (vcpu->run) */
322 LONG_L a0, VCPU_RUN(a1)
323 /* Save pointer to run in s0, will be saved by the compiler */
324 move s0, a0
325
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700326 /*
327 * Save Host level EPC, BadVaddr and Cause to VCPU, useful to
328 * process the exception
329 */
David Daney2c07ebb2013-08-01 13:22:33 -0700330 mfc0 k0,CP0_EPC
331 LONG_S k0, VCPU_PC(k1)
332
333 mfc0 k0, CP0_BADVADDR
334 LONG_S k0, VCPU_HOST_CP0_BADVADDR(k1)
335
336 mfc0 k0, CP0_CAUSE
337 LONG_S k0, VCPU_HOST_CP0_CAUSE(k1)
338
339 mfc0 k0, CP0_ENTRYHI
340 LONG_S k0, VCPU_HOST_ENTRYHI(k1)
341
342 /* Now restore the host state just enough to run the handlers */
343
344 /* Swtich EBASE to the one used by Linux */
345 /* load up the host EBASE */
346 mfc0 v0, CP0_STATUS
347
348 .set at
349 or k0, v0, ST0_BEV
350 .set noat
351
352 mtc0 k0, CP0_STATUS
353 ehb
354
355 LONG_L k0, VCPU_HOST_EBASE(k1)
356 mtc0 k0,CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800357
James Hogan98e91b82014-11-18 14:09:12 +0000358 /*
359 * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
360 * trigger FPE for pending exceptions.
361 */
362 .set at
363 and v1, v0, ST0_CU1
364 beqz v1, 1f
365 nop
366 .set push
367 SET_HARDFLOAT
368 cfc1 t0, fcr31
369 sw t0, VCPU_FCR31(k1)
370 ctc1 zero,fcr31
371 .set pop
372 .set noat
3731:
374
James Hogan539cb89fb2015-03-05 11:43:36 +0000375#ifdef CONFIG_CPU_HAS_MSA
376 /*
377 * If MSA is enabled, save MSACSR and clear it so that later
378 * instructions don't trigger MSAFPE for pending exceptions.
379 */
380 mfc0 t0, CP0_CONFIG3
381 ext t0, t0, 28, 1 /* MIPS_CONF3_MSAP */
382 beqz t0, 1f
383 nop
384 mfc0 t0, CP0_CONFIG5
385 ext t0, t0, 27, 1 /* MIPS_CONF5_MSAEN */
386 beqz t0, 1f
387 nop
388 _cfcmsa t0, MSA_CSR
389 sw t0, VCPU_MSA_CSR(k1)
390 _ctcmsa MSA_CSR, zero
3911:
392#endif
393
David Daney2c07ebb2013-08-01 13:22:33 -0700394 /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
395 .set at
396 and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
397 or v0, v0, ST0_CU0
398 .set noat
399 mtc0 v0, CP0_STATUS
400 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800401
David Daney2c07ebb2013-08-01 13:22:33 -0700402 /* Load up host GP */
403 LONG_L gp, VCPU_HOST_GP(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800404
David Daney2c07ebb2013-08-01 13:22:33 -0700405 /* Need a stack before we can jump to "C" */
406 LONG_L sp, VCPU_HOST_STACK(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800407
David Daney2c07ebb2013-08-01 13:22:33 -0700408 /* Saved host state */
David Daneyea69f282013-08-01 13:22:35 -0700409 INT_ADDIU sp, sp, -PT_SIZE
Sanjay Lalb680f702012-11-21 18:34:01 -0800410
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700411 /*
412 * XXXKYMA do we need to load the host ASID, maybe not because the
David Daney2c07ebb2013-08-01 13:22:33 -0700413 * kernel entries are marked GLOBAL, need to verify
414 */
Sanjay Lalb680f702012-11-21 18:34:01 -0800415
David Daney2c07ebb2013-08-01 13:22:33 -0700416 /* Restore host DDATA_LO */
417 LONG_L k0, PT_HOST_USERLOCAL(sp)
418 mtc0 k0, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800419
David Daney2c07ebb2013-08-01 13:22:33 -0700420 /* Restore RDHWR access */
David Daneyea69f282013-08-01 13:22:35 -0700421 PTR_LI k0, 0x2000000F
David Daney2c07ebb2013-08-01 13:22:33 -0700422 mtc0 k0, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800423
David Daney2c07ebb2013-08-01 13:22:33 -0700424 /* Jump to handler */
Sanjay Lalb680f702012-11-21 18:34:01 -0800425FEXPORT(__kvm_mips_jump_to_handler)
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700426 /*
427 * XXXKYMA: not sure if this is safe, how large is the stack??
David Daney2c07ebb2013-08-01 13:22:33 -0700428 * Now jump to the kvm_mips_handle_exit() to see if we can deal
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700429 * with this in the kernel
430 */
David Daneyea69f282013-08-01 13:22:35 -0700431 PTR_LA t9, kvm_mips_handle_exit
David Daney2c07ebb2013-08-01 13:22:33 -0700432 jalr.hb t9
David Daneyea69f282013-08-01 13:22:35 -0700433 INT_ADDIU sp, sp, -CALLFRAME_SIZ /* BD Slot */
Sanjay Lalb680f702012-11-21 18:34:01 -0800434
David Daney2c07ebb2013-08-01 13:22:33 -0700435 /* Return from handler Make sure interrupts are disabled */
436 di
437 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800438
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700439 /*
440 * XXXKYMA: k0/k1 could have been blown away if we processed
David Daney2c07ebb2013-08-01 13:22:33 -0700441 * an exception while we were handling the exception from the
442 * guest, reload k1
443 */
Sanjay Lalb680f702012-11-21 18:34:01 -0800444
David Daney2c07ebb2013-08-01 13:22:33 -0700445 move k1, s1
David Daneyea69f282013-08-01 13:22:35 -0700446 INT_ADDIU k1, k1, VCPU_HOST_ARCH
David Daney2c07ebb2013-08-01 13:22:33 -0700447
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700448 /*
449 * Check return value, should tell us if we are returning to the
David Daney2c07ebb2013-08-01 13:22:33 -0700450 * host (handle I/O etc)or resuming the guest
451 */
452 andi t0, v0, RESUME_HOST
453 bnez t0, __kvm_mips_return_to_host
454 nop
Sanjay Lalb680f702012-11-21 18:34:01 -0800455
456__kvm_mips_return_to_guest:
David Daney2c07ebb2013-08-01 13:22:33 -0700457 /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
458 mtc0 s1, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800459
David Daney2c07ebb2013-08-01 13:22:33 -0700460 /* Load up the Guest EBASE to minimize the window where BEV is set */
461 LONG_L t0, VCPU_GUEST_EBASE(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800462
David Daney2c07ebb2013-08-01 13:22:33 -0700463 /* Switch EBASE back to the one used by KVM */
464 mfc0 v1, CP0_STATUS
465 .set at
466 or k0, v1, ST0_BEV
467 .set noat
468 mtc0 k0, CP0_STATUS
469 ehb
470 mtc0 t0, CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800471
David Daney2c07ebb2013-08-01 13:22:33 -0700472 /* Setup status register for running guest in UM */
473 .set at
474 or v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
James Hoganf7982172015-02-04 17:06:37 +0000475 and v1, v1, ~(ST0_CU0 | ST0_MX)
David Daney2c07ebb2013-08-01 13:22:33 -0700476 .set noat
477 mtc0 v1, CP0_STATUS
478 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800479
480 /* Set Guest EPC */
David Daney2c07ebb2013-08-01 13:22:33 -0700481 LONG_L t0, VCPU_PC(k1)
482 mtc0 t0, CP0_EPC
Sanjay Lalb680f702012-11-21 18:34:01 -0800483
David Daney2c07ebb2013-08-01 13:22:33 -0700484 /* Set the ASID for the Guest Kernel */
David Daneyea69f282013-08-01 13:22:35 -0700485 INT_SLL t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
David Daney2c07ebb2013-08-01 13:22:33 -0700486 /* addresses shift to 0x80000000 */
487 bltz t0, 1f /* If kernel */
David Daneyea69f282013-08-01 13:22:35 -0700488 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
489 INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
Sanjay Lalb680f702012-11-21 18:34:01 -08004901:
David Daney2c07ebb2013-08-01 13:22:33 -0700491 /* t1: contains the base of the ASID array, need to get the cpu id */
492 LONG_L t2, TI_CPU($28) /* smp_processor_id */
David Daneyea69f282013-08-01 13:22:35 -0700493 INT_SLL t2, t2, 2 /* x4 */
494 REG_ADDU t3, t1, t2
David Daney2c07ebb2013-08-01 13:22:33 -0700495 LONG_L k0, (t3)
496 andi k0, k0, 0xff
497 mtc0 k0,CP0_ENTRYHI
498 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800499
David Daney2c07ebb2013-08-01 13:22:33 -0700500 /* Disable RDHWR access */
501 mtc0 zero, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800502
David Daney2c07ebb2013-08-01 13:22:33 -0700503 /* load the guest context from VCPU and return */
504 LONG_L $0, VCPU_R0(k1)
505 LONG_L $1, VCPU_R1(k1)
506 LONG_L $2, VCPU_R2(k1)
507 LONG_L $3, VCPU_R3(k1)
508 LONG_L $4, VCPU_R4(k1)
509 LONG_L $5, VCPU_R5(k1)
510 LONG_L $6, VCPU_R6(k1)
511 LONG_L $7, VCPU_R7(k1)
512 LONG_L $8, VCPU_R8(k1)
513 LONG_L $9, VCPU_R9(k1)
514 LONG_L $10, VCPU_R10(k1)
515 LONG_L $11, VCPU_R11(k1)
516 LONG_L $12, VCPU_R12(k1)
517 LONG_L $13, VCPU_R13(k1)
518 LONG_L $14, VCPU_R14(k1)
519 LONG_L $15, VCPU_R15(k1)
520 LONG_L $16, VCPU_R16(k1)
521 LONG_L $17, VCPU_R17(k1)
522 LONG_L $18, VCPU_R18(k1)
523 LONG_L $19, VCPU_R19(k1)
524 LONG_L $20, VCPU_R20(k1)
525 LONG_L $21, VCPU_R21(k1)
526 LONG_L $22, VCPU_R22(k1)
527 LONG_L $23, VCPU_R23(k1)
528 LONG_L $24, VCPU_R24(k1)
529 LONG_L $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800530
David Daney2c07ebb2013-08-01 13:22:33 -0700531 /* $/k1 loaded later */
532 LONG_L $28, VCPU_R28(k1)
533 LONG_L $29, VCPU_R29(k1)
534 LONG_L $30, VCPU_R30(k1)
535 LONG_L $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800536
537FEXPORT(__kvm_mips_skip_guest_restore)
David Daney2c07ebb2013-08-01 13:22:33 -0700538 LONG_L k0, VCPU_HI(k1)
539 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800540
David Daney2c07ebb2013-08-01 13:22:33 -0700541 LONG_L k0, VCPU_LO(k1)
542 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800543
David Daney2c07ebb2013-08-01 13:22:33 -0700544 LONG_L k0, VCPU_R26(k1)
545 LONG_L k1, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800546
David Daney2c07ebb2013-08-01 13:22:33 -0700547 eret
Sanjay Lalb680f702012-11-21 18:34:01 -0800548
549__kvm_mips_return_to_host:
David Daney2c07ebb2013-08-01 13:22:33 -0700550 /* EBASE is already pointing to Linux */
551 LONG_L k1, VCPU_HOST_STACK(k1)
David Daneyea69f282013-08-01 13:22:35 -0700552 INT_ADDIU k1,k1, -PT_SIZE
Sanjay Lalb680f702012-11-21 18:34:01 -0800553
David Daney2c07ebb2013-08-01 13:22:33 -0700554 /* Restore host DDATA_LO */
555 LONG_L k0, PT_HOST_USERLOCAL(k1)
556 mtc0 k0, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800557
David Daney2c07ebb2013-08-01 13:22:33 -0700558 /* Restore host ASID */
559 LONG_L k0, PT_HOST_ASID(sp)
560 andi k0, 0xff
561 mtc0 k0,CP0_ENTRYHI
562 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800563
David Daney2c07ebb2013-08-01 13:22:33 -0700564 /* Load context saved on the host stack */
565 LONG_L $0, PT_R0(k1)
566 LONG_L $1, PT_R1(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800567
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700568 /*
569 * r2/v0 is the return code, shift it down by 2 (arithmetic)
570 * to recover the err code
571 */
David Daneyea69f282013-08-01 13:22:35 -0700572 INT_SRA k0, v0, 2
David Daney2c07ebb2013-08-01 13:22:33 -0700573 move $2, k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800574
David Daney2c07ebb2013-08-01 13:22:33 -0700575 LONG_L $3, PT_R3(k1)
576 LONG_L $4, PT_R4(k1)
577 LONG_L $5, PT_R5(k1)
578 LONG_L $6, PT_R6(k1)
579 LONG_L $7, PT_R7(k1)
580 LONG_L $8, PT_R8(k1)
581 LONG_L $9, PT_R9(k1)
582 LONG_L $10, PT_R10(k1)
583 LONG_L $11, PT_R11(k1)
584 LONG_L $12, PT_R12(k1)
585 LONG_L $13, PT_R13(k1)
586 LONG_L $14, PT_R14(k1)
587 LONG_L $15, PT_R15(k1)
588 LONG_L $16, PT_R16(k1)
589 LONG_L $17, PT_R17(k1)
590 LONG_L $18, PT_R18(k1)
591 LONG_L $19, PT_R19(k1)
592 LONG_L $20, PT_R20(k1)
593 LONG_L $21, PT_R21(k1)
594 LONG_L $22, PT_R22(k1)
595 LONG_L $23, PT_R23(k1)
596 LONG_L $24, PT_R24(k1)
597 LONG_L $25, PT_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800598
David Daney2c07ebb2013-08-01 13:22:33 -0700599 /* Host k0/k1 were not saved */
Sanjay Lalb680f702012-11-21 18:34:01 -0800600
David Daney2c07ebb2013-08-01 13:22:33 -0700601 LONG_L $28, PT_R28(k1)
602 LONG_L $29, PT_R29(k1)
603 LONG_L $30, PT_R30(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800604
David Daney2c07ebb2013-08-01 13:22:33 -0700605 LONG_L k0, PT_HI(k1)
606 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800607
David Daney2c07ebb2013-08-01 13:22:33 -0700608 LONG_L k0, PT_LO(k1)
609 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800610
David Daney2c07ebb2013-08-01 13:22:33 -0700611 /* Restore RDHWR access */
David Daneyea69f282013-08-01 13:22:35 -0700612 PTR_LI k0, 0x2000000F
David Daney2c07ebb2013-08-01 13:22:33 -0700613 mtc0 k0, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800614
David Daney2c07ebb2013-08-01 13:22:33 -0700615 /* Restore RA, which is the address we will return to */
616 LONG_L ra, PT_R31(k1)
617 j ra
618 nop
Sanjay Lalb680f702012-11-21 18:34:01 -0800619
Sanjay Lalb680f702012-11-21 18:34:01 -0800620VECTOR_END(MIPSX(GuestExceptionEnd))
621.end MIPSX(GuestException)
622
623MIPSX(exceptions):
624 ####
625 ##### The exception handlers.
626 #####
627 .word _C_LABEL(MIPSX(GuestException)) # 0
628 .word _C_LABEL(MIPSX(GuestException)) # 1
629 .word _C_LABEL(MIPSX(GuestException)) # 2
630 .word _C_LABEL(MIPSX(GuestException)) # 3
631 .word _C_LABEL(MIPSX(GuestException)) # 4
632 .word _C_LABEL(MIPSX(GuestException)) # 5
633 .word _C_LABEL(MIPSX(GuestException)) # 6
634 .word _C_LABEL(MIPSX(GuestException)) # 7
635 .word _C_LABEL(MIPSX(GuestException)) # 8
636 .word _C_LABEL(MIPSX(GuestException)) # 9
637 .word _C_LABEL(MIPSX(GuestException)) # 10
638 .word _C_LABEL(MIPSX(GuestException)) # 11
639 .word _C_LABEL(MIPSX(GuestException)) # 12
640 .word _C_LABEL(MIPSX(GuestException)) # 13
641 .word _C_LABEL(MIPSX(GuestException)) # 14
642 .word _C_LABEL(MIPSX(GuestException)) # 15
643 .word _C_LABEL(MIPSX(GuestException)) # 16
644 .word _C_LABEL(MIPSX(GuestException)) # 17
645 .word _C_LABEL(MIPSX(GuestException)) # 18
646 .word _C_LABEL(MIPSX(GuestException)) # 19
647 .word _C_LABEL(MIPSX(GuestException)) # 20
648 .word _C_LABEL(MIPSX(GuestException)) # 21
649 .word _C_LABEL(MIPSX(GuestException)) # 22
650 .word _C_LABEL(MIPSX(GuestException)) # 23
651 .word _C_LABEL(MIPSX(GuestException)) # 24
652 .word _C_LABEL(MIPSX(GuestException)) # 25
653 .word _C_LABEL(MIPSX(GuestException)) # 26
654 .word _C_LABEL(MIPSX(GuestException)) # 27
655 .word _C_LABEL(MIPSX(GuestException)) # 28
656 .word _C_LABEL(MIPSX(GuestException)) # 29
657 .word _C_LABEL(MIPSX(GuestException)) # 30
658 .word _C_LABEL(MIPSX(GuestException)) # 31