blob: 308706493fd5f0950df9b11d5a62c6610a0809d1 [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 $0, PT_R0(k1)
57 LONG_S $1, PT_R1(k1)
58 LONG_S $2, PT_R2(k1)
59 LONG_S $3, PT_R3(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080060
David Daney2c07ebb2013-08-01 13:22:33 -070061 LONG_S $4, PT_R4(k1)
62 LONG_S $5, PT_R5(k1)
63 LONG_S $6, PT_R6(k1)
64 LONG_S $7, PT_R7(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080065
David Daney2c07ebb2013-08-01 13:22:33 -070066 LONG_S $8, PT_R8(k1)
67 LONG_S $9, PT_R9(k1)
68 LONG_S $10, PT_R10(k1)
69 LONG_S $11, PT_R11(k1)
70 LONG_S $12, PT_R12(k1)
71 LONG_S $13, PT_R13(k1)
72 LONG_S $14, PT_R14(k1)
73 LONG_S $15, PT_R15(k1)
74 LONG_S $16, PT_R16(k1)
75 LONG_S $17, PT_R17(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080076
David Daney2c07ebb2013-08-01 13:22:33 -070077 LONG_S $18, PT_R18(k1)
78 LONG_S $19, PT_R19(k1)
79 LONG_S $20, PT_R20(k1)
80 LONG_S $21, PT_R21(k1)
81 LONG_S $22, PT_R22(k1)
82 LONG_S $23, PT_R23(k1)
83 LONG_S $24, PT_R24(k1)
84 LONG_S $25, PT_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080085
Deng-Cheng Zhud116e812014-06-26 12:11:34 -070086 /*
87 * XXXKYMA k0/k1 not saved, not being used if we got here through
88 * an ioctl()
89 */
Sanjay Lalb680f702012-11-21 18:34:01 -080090
David Daney2c07ebb2013-08-01 13:22:33 -070091 LONG_S $28, PT_R28(k1)
92 LONG_S $29, PT_R29(k1)
93 LONG_S $30, PT_R30(k1)
94 LONG_S $31, PT_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -080095
David Daney2c07ebb2013-08-01 13:22:33 -070096 /* Save hi/lo */
97 mflo v0
98 LONG_S v0, PT_LO(k1)
99 mfhi v1
100 LONG_S v1, PT_HI(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800101
102 /* Save host status */
David Daney2c07ebb2013-08-01 13:22:33 -0700103 mfc0 v0, CP0_STATUS
104 LONG_S v0, PT_STATUS(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800105
David Daney2c07ebb2013-08-01 13:22:33 -0700106 /* Save DDATA_LO, will be used to store pointer to vcpu */
107 mfc0 v1, CP0_DDATA_LO
108 LONG_S v1, PT_HOST_USERLOCAL(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800109
David Daney2c07ebb2013-08-01 13:22:33 -0700110 /* DDATA_LO has pointer to vcpu */
111 mtc0 a1, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800112
David Daney2c07ebb2013-08-01 13:22:33 -0700113 /* Offset into vcpu->arch */
David Daneyea69f282013-08-01 13:22:35 -0700114 INT_ADDIU k1, a1, VCPU_HOST_ARCH
Sanjay Lalb680f702012-11-21 18:34:01 -0800115
David Daney2c07ebb2013-08-01 13:22:33 -0700116 /*
117 * Save the host stack to VCPU, used for exception processing
118 * when we exit from the Guest
119 */
120 LONG_S sp, VCPU_HOST_STACK(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800121
David Daney2c07ebb2013-08-01 13:22:33 -0700122 /* Save the kernel gp as well */
123 LONG_S gp, VCPU_HOST_GP(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800124
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700125 /*
126 * Setup status register for running the guest in UM, interrupts
127 * are disabled
128 */
David Daney2c07ebb2013-08-01 13:22:33 -0700129 li k0, (ST0_EXL | KSU_USER | ST0_BEV)
130 mtc0 k0, CP0_STATUS
131 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800132
David Daney2c07ebb2013-08-01 13:22:33 -0700133 /* load up the new EBASE */
134 LONG_L k0, VCPU_GUEST_EBASE(k1)
135 mtc0 k0, CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800136
David Daney2c07ebb2013-08-01 13:22:33 -0700137 /*
138 * Now that the new EBASE has been loaded, unset BEV, set
139 * interrupt mask as it was but make sure that timer interrupts
140 * are enabled
141 */
142 li k0, (ST0_EXL | KSU_USER | ST0_IE)
143 andi v0, v0, ST0_IM
144 or k0, k0, v0
145 mtc0 k0, CP0_STATUS
146 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800147
Sanjay Lalb680f702012-11-21 18:34:01 -0800148 /* Set Guest EPC */
David Daney2c07ebb2013-08-01 13:22:33 -0700149 LONG_L t0, VCPU_PC(k1)
150 mtc0 t0, CP0_EPC
Sanjay Lalb680f702012-11-21 18:34:01 -0800151
152FEXPORT(__kvm_mips_load_asid)
David Daney2c07ebb2013-08-01 13:22:33 -0700153 /* Set the ASID for the Guest Kernel */
James Hogan002374f2015-11-11 14:21:18 +0000154 PTR_L t0, VCPU_COP0(k1)
155 LONG_L t0, COP0_STATUS(t0)
156 andi t0, KSU_USER | ST0_ERL | ST0_EXL
157 xori t0, KSU_USER
158 bnez t0, 1f /* If kernel */
David Daneyea69f282013-08-01 13:22:35 -0700159 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
160 INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
Sanjay Lalb680f702012-11-21 18:34:01 -08001611:
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700162 /* t1: contains the base of the ASID array, need to get the cpu id */
David Daney2c07ebb2013-08-01 13:22:33 -0700163 LONG_L t2, TI_CPU($28) /* smp_processor_id */
David Daneyea69f282013-08-01 13:22:35 -0700164 INT_SLL t2, t2, 2 /* x4 */
165 REG_ADDU t3, t1, t2
David Daney2c07ebb2013-08-01 13:22:33 -0700166 LONG_L k0, (t3)
James Hogan9b5c3392016-05-06 14:36:19 +0100167 andi k0, k0, MIPS_ENTRYHI_ASID
David Daney2c07ebb2013-08-01 13:22:33 -0700168 mtc0 k0, CP0_ENTRYHI
169 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800170
David Daney2c07ebb2013-08-01 13:22:33 -0700171 /* Disable RDHWR access */
172 mtc0 zero, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800173
David Daney2c07ebb2013-08-01 13:22:33 -0700174 /* Now load up the Guest Context from VCPU */
175 LONG_L $1, VCPU_R1(k1)
176 LONG_L $2, VCPU_R2(k1)
177 LONG_L $3, VCPU_R3(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800178
David Daney2c07ebb2013-08-01 13:22:33 -0700179 LONG_L $4, VCPU_R4(k1)
180 LONG_L $5, VCPU_R5(k1)
181 LONG_L $6, VCPU_R6(k1)
182 LONG_L $7, VCPU_R7(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800183
David Daney2c07ebb2013-08-01 13:22:33 -0700184 LONG_L $8, VCPU_R8(k1)
185 LONG_L $9, VCPU_R9(k1)
186 LONG_L $10, VCPU_R10(k1)
187 LONG_L $11, VCPU_R11(k1)
188 LONG_L $12, VCPU_R12(k1)
189 LONG_L $13, VCPU_R13(k1)
190 LONG_L $14, VCPU_R14(k1)
191 LONG_L $15, VCPU_R15(k1)
192 LONG_L $16, VCPU_R16(k1)
193 LONG_L $17, VCPU_R17(k1)
194 LONG_L $18, VCPU_R18(k1)
195 LONG_L $19, VCPU_R19(k1)
196 LONG_L $20, VCPU_R20(k1)
197 LONG_L $21, VCPU_R21(k1)
198 LONG_L $22, VCPU_R22(k1)
199 LONG_L $23, VCPU_R23(k1)
200 LONG_L $24, VCPU_R24(k1)
201 LONG_L $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800202
David Daney2c07ebb2013-08-01 13:22:33 -0700203 /* k0/k1 loaded up later */
Sanjay Lalb680f702012-11-21 18:34:01 -0800204
David Daney2c07ebb2013-08-01 13:22:33 -0700205 LONG_L $28, VCPU_R28(k1)
206 LONG_L $29, VCPU_R29(k1)
207 LONG_L $30, VCPU_R30(k1)
208 LONG_L $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800209
David Daney2c07ebb2013-08-01 13:22:33 -0700210 /* Restore hi/lo */
211 LONG_L k0, VCPU_LO(k1)
212 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800213
David Daney2c07ebb2013-08-01 13:22:33 -0700214 LONG_L k0, VCPU_HI(k1)
215 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800216
217FEXPORT(__kvm_mips_load_k0k1)
218 /* Restore the guest's k0/k1 registers */
David Daney2c07ebb2013-08-01 13:22:33 -0700219 LONG_L k0, VCPU_R26(k1)
220 LONG_L k1, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800221
David Daney2c07ebb2013-08-01 13:22:33 -0700222 /* Jump to guest */
Sanjay Lalb680f702012-11-21 18:34:01 -0800223 eret
Sanjay Lalb680f702012-11-21 18:34:01 -0800224
225VECTOR(MIPSX(exception), unknown)
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700226/* Find out what mode we came from and jump to the proper handler. */
David Daney2c07ebb2013-08-01 13:22:33 -0700227 mtc0 k0, CP0_ERROREPC #01: Save guest k0
228 ehb #02:
Sanjay Lalb680f702012-11-21 18:34:01 -0800229
David Daney2c07ebb2013-08-01 13:22:33 -0700230 mfc0 k0, CP0_EBASE #02: Get EBASE
David Daneyea69f282013-08-01 13:22:35 -0700231 INT_SRL k0, k0, 10 #03: Get rid of CPUNum
232 INT_SLL k0, k0, 10 #04
David Daney2c07ebb2013-08-01 13:22:33 -0700233 LONG_S k1, 0x3000(k0) #05: Save k1 @ offset 0x3000
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700234 INT_ADDIU k0, k0, 0x2000 #06: Exception handler is
235 # installed @ offset 0x2000
David Daney2c07ebb2013-08-01 13:22:33 -0700236 j k0 #07: jump to the function
237 nop #08: branch delay slot
Sanjay Lalb680f702012-11-21 18:34:01 -0800238VECTOR_END(MIPSX(exceptionEnd))
239.end MIPSX(exception)
240
241/*
242 * Generic Guest exception handler. We end up here when the guest
243 * does something that causes a trap to kernel mode.
Sanjay Lalb680f702012-11-21 18:34:01 -0800244 */
245NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
David Daney2c07ebb2013-08-01 13:22:33 -0700246 /* Get the VCPU pointer from DDTATA_LO */
247 mfc0 k1, CP0_DDATA_LO
David Daneyea69f282013-08-01 13:22:35 -0700248 INT_ADDIU k1, k1, VCPU_HOST_ARCH
Sanjay Lalb680f702012-11-21 18:34:01 -0800249
David Daney2c07ebb2013-08-01 13:22:33 -0700250 /* Start saving Guest context to VCPU */
251 LONG_S $0, VCPU_R0(k1)
252 LONG_S $1, VCPU_R1(k1)
253 LONG_S $2, VCPU_R2(k1)
254 LONG_S $3, VCPU_R3(k1)
255 LONG_S $4, VCPU_R4(k1)
256 LONG_S $5, VCPU_R5(k1)
257 LONG_S $6, VCPU_R6(k1)
258 LONG_S $7, VCPU_R7(k1)
259 LONG_S $8, VCPU_R8(k1)
260 LONG_S $9, VCPU_R9(k1)
261 LONG_S $10, VCPU_R10(k1)
262 LONG_S $11, VCPU_R11(k1)
263 LONG_S $12, VCPU_R12(k1)
264 LONG_S $13, VCPU_R13(k1)
265 LONG_S $14, VCPU_R14(k1)
266 LONG_S $15, VCPU_R15(k1)
267 LONG_S $16, VCPU_R16(k1)
268 LONG_S $17, VCPU_R17(k1)
269 LONG_S $18, VCPU_R18(k1)
270 LONG_S $19, VCPU_R19(k1)
271 LONG_S $20, VCPU_R20(k1)
272 LONG_S $21, VCPU_R21(k1)
273 LONG_S $22, VCPU_R22(k1)
274 LONG_S $23, VCPU_R23(k1)
275 LONG_S $24, VCPU_R24(k1)
276 LONG_S $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800277
David Daney2c07ebb2013-08-01 13:22:33 -0700278 /* Guest k0/k1 saved later */
Sanjay Lalb680f702012-11-21 18:34:01 -0800279
David Daney2c07ebb2013-08-01 13:22:33 -0700280 LONG_S $28, VCPU_R28(k1)
281 LONG_S $29, VCPU_R29(k1)
282 LONG_S $30, VCPU_R30(k1)
283 LONG_S $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800284
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700285 /* We need to save hi/lo and restore them on the way out */
David Daney2c07ebb2013-08-01 13:22:33 -0700286 mfhi t0
287 LONG_S t0, VCPU_HI(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800288
David Daney2c07ebb2013-08-01 13:22:33 -0700289 mflo t0
290 LONG_S t0, VCPU_LO(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800291
David Daney2c07ebb2013-08-01 13:22:33 -0700292 /* Finally save guest k0/k1 to VCPU */
293 mfc0 t0, CP0_ERROREPC
294 LONG_S t0, VCPU_R26(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800295
David Daney2c07ebb2013-08-01 13:22:33 -0700296 /* Get GUEST k1 and save it in VCPU */
David Daneyea69f282013-08-01 13:22:35 -0700297 PTR_LI t1, ~0x2ff
David Daney2c07ebb2013-08-01 13:22:33 -0700298 mfc0 t0, CP0_EBASE
299 and t0, t0, t1
300 LONG_L t0, 0x3000(t0)
301 LONG_S t0, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800302
David Daney2c07ebb2013-08-01 13:22:33 -0700303 /* Now that context has been saved, we can use other registers */
Sanjay Lalb680f702012-11-21 18:34:01 -0800304
David Daney2c07ebb2013-08-01 13:22:33 -0700305 /* Restore vcpu */
306 mfc0 a1, CP0_DDATA_LO
307 move s1, a1
Sanjay Lalb680f702012-11-21 18:34:01 -0800308
David Daney2c07ebb2013-08-01 13:22:33 -0700309 /* Restore run (vcpu->run) */
310 LONG_L a0, VCPU_RUN(a1)
311 /* Save pointer to run in s0, will be saved by the compiler */
312 move s0, a0
313
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700314 /*
315 * Save Host level EPC, BadVaddr and Cause to VCPU, useful to
316 * process the exception
317 */
David Daney2c07ebb2013-08-01 13:22:33 -0700318 mfc0 k0,CP0_EPC
319 LONG_S k0, VCPU_PC(k1)
320
321 mfc0 k0, CP0_BADVADDR
322 LONG_S k0, VCPU_HOST_CP0_BADVADDR(k1)
323
324 mfc0 k0, CP0_CAUSE
325 LONG_S k0, VCPU_HOST_CP0_CAUSE(k1)
326
327 mfc0 k0, CP0_ENTRYHI
328 LONG_S k0, VCPU_HOST_ENTRYHI(k1)
329
330 /* Now restore the host state just enough to run the handlers */
331
James Hogancaa1faa2015-12-16 23:49:26 +0000332 /* Switch EBASE to the one used by Linux */
David Daney2c07ebb2013-08-01 13:22:33 -0700333 /* load up the host EBASE */
334 mfc0 v0, CP0_STATUS
335
336 .set at
337 or k0, v0, ST0_BEV
338 .set noat
339
340 mtc0 k0, CP0_STATUS
341 ehb
342
343 LONG_L k0, VCPU_HOST_EBASE(k1)
344 mtc0 k0,CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800345
James Hogan98e91b82014-11-18 14:09:12 +0000346 /*
347 * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
348 * trigger FPE for pending exceptions.
349 */
350 .set at
351 and v1, v0, ST0_CU1
352 beqz v1, 1f
353 nop
354 .set push
355 SET_HARDFLOAT
356 cfc1 t0, fcr31
357 sw t0, VCPU_FCR31(k1)
358 ctc1 zero,fcr31
359 .set pop
360 .set noat
3611:
362
James Hogan539cb89fb2015-03-05 11:43:36 +0000363#ifdef CONFIG_CPU_HAS_MSA
364 /*
365 * If MSA is enabled, save MSACSR and clear it so that later
366 * instructions don't trigger MSAFPE for pending exceptions.
367 */
368 mfc0 t0, CP0_CONFIG3
369 ext t0, t0, 28, 1 /* MIPS_CONF3_MSAP */
370 beqz t0, 1f
371 nop
372 mfc0 t0, CP0_CONFIG5
373 ext t0, t0, 27, 1 /* MIPS_CONF5_MSAEN */
374 beqz t0, 1f
375 nop
376 _cfcmsa t0, MSA_CSR
377 sw t0, VCPU_MSA_CSR(k1)
378 _ctcmsa MSA_CSR, zero
3791:
380#endif
381
David Daney2c07ebb2013-08-01 13:22:33 -0700382 /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
383 .set at
384 and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
385 or v0, v0, ST0_CU0
386 .set noat
387 mtc0 v0, CP0_STATUS
388 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800389
David Daney2c07ebb2013-08-01 13:22:33 -0700390 /* Load up host GP */
391 LONG_L gp, VCPU_HOST_GP(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800392
David Daney2c07ebb2013-08-01 13:22:33 -0700393 /* Need a stack before we can jump to "C" */
394 LONG_L sp, VCPU_HOST_STACK(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800395
David Daney2c07ebb2013-08-01 13:22:33 -0700396 /* Saved host state */
David Daneyea69f282013-08-01 13:22:35 -0700397 INT_ADDIU sp, sp, -PT_SIZE
Sanjay Lalb680f702012-11-21 18:34:01 -0800398
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700399 /*
400 * XXXKYMA do we need to load the host ASID, maybe not because the
David Daney2c07ebb2013-08-01 13:22:33 -0700401 * kernel entries are marked GLOBAL, need to verify
402 */
Sanjay Lalb680f702012-11-21 18:34:01 -0800403
David Daney2c07ebb2013-08-01 13:22:33 -0700404 /* Restore host DDATA_LO */
405 LONG_L k0, PT_HOST_USERLOCAL(sp)
406 mtc0 k0, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800407
David Daney2c07ebb2013-08-01 13:22:33 -0700408 /* Restore RDHWR access */
David Daneyea69f282013-08-01 13:22:35 -0700409 PTR_LI k0, 0x2000000F
David Daney2c07ebb2013-08-01 13:22:33 -0700410 mtc0 k0, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800411
David Daney2c07ebb2013-08-01 13:22:33 -0700412 /* Jump to handler */
Sanjay Lalb680f702012-11-21 18:34:01 -0800413FEXPORT(__kvm_mips_jump_to_handler)
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700414 /*
415 * XXXKYMA: not sure if this is safe, how large is the stack??
David Daney2c07ebb2013-08-01 13:22:33 -0700416 * Now jump to the kvm_mips_handle_exit() to see if we can deal
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700417 * with this in the kernel
418 */
David Daneyea69f282013-08-01 13:22:35 -0700419 PTR_LA t9, kvm_mips_handle_exit
David Daney2c07ebb2013-08-01 13:22:33 -0700420 jalr.hb t9
David Daneyea69f282013-08-01 13:22:35 -0700421 INT_ADDIU sp, sp, -CALLFRAME_SIZ /* BD Slot */
Sanjay Lalb680f702012-11-21 18:34:01 -0800422
David Daney2c07ebb2013-08-01 13:22:33 -0700423 /* Return from handler Make sure interrupts are disabled */
424 di
425 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800426
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700427 /*
428 * XXXKYMA: k0/k1 could have been blown away if we processed
David Daney2c07ebb2013-08-01 13:22:33 -0700429 * an exception while we were handling the exception from the
430 * guest, reload k1
431 */
Sanjay Lalb680f702012-11-21 18:34:01 -0800432
David Daney2c07ebb2013-08-01 13:22:33 -0700433 move k1, s1
David Daneyea69f282013-08-01 13:22:35 -0700434 INT_ADDIU k1, k1, VCPU_HOST_ARCH
David Daney2c07ebb2013-08-01 13:22:33 -0700435
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700436 /*
437 * Check return value, should tell us if we are returning to the
David Daney2c07ebb2013-08-01 13:22:33 -0700438 * host (handle I/O etc)or resuming the guest
439 */
440 andi t0, v0, RESUME_HOST
441 bnez t0, __kvm_mips_return_to_host
442 nop
Sanjay Lalb680f702012-11-21 18:34:01 -0800443
444__kvm_mips_return_to_guest:
David Daney2c07ebb2013-08-01 13:22:33 -0700445 /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
446 mtc0 s1, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800447
David Daney2c07ebb2013-08-01 13:22:33 -0700448 /* Load up the Guest EBASE to minimize the window where BEV is set */
449 LONG_L t0, VCPU_GUEST_EBASE(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800450
David Daney2c07ebb2013-08-01 13:22:33 -0700451 /* Switch EBASE back to the one used by KVM */
452 mfc0 v1, CP0_STATUS
453 .set at
454 or k0, v1, ST0_BEV
455 .set noat
456 mtc0 k0, CP0_STATUS
457 ehb
458 mtc0 t0, CP0_EBASE
Sanjay Lalb680f702012-11-21 18:34:01 -0800459
David Daney2c07ebb2013-08-01 13:22:33 -0700460 /* Setup status register for running guest in UM */
461 .set at
462 or v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
James Hoganf7982172015-02-04 17:06:37 +0000463 and v1, v1, ~(ST0_CU0 | ST0_MX)
David Daney2c07ebb2013-08-01 13:22:33 -0700464 .set noat
465 mtc0 v1, CP0_STATUS
466 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800467
468 /* Set Guest EPC */
David Daney2c07ebb2013-08-01 13:22:33 -0700469 LONG_L t0, VCPU_PC(k1)
470 mtc0 t0, CP0_EPC
Sanjay Lalb680f702012-11-21 18:34:01 -0800471
David Daney2c07ebb2013-08-01 13:22:33 -0700472 /* Set the ASID for the Guest Kernel */
James Hogan002374f2015-11-11 14:21:18 +0000473 PTR_L t0, VCPU_COP0(k1)
474 LONG_L t0, COP0_STATUS(t0)
475 andi t0, KSU_USER | ST0_ERL | ST0_EXL
476 xori t0, KSU_USER
477 bnez t0, 1f /* If kernel */
David Daneyea69f282013-08-01 13:22:35 -0700478 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
479 INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
Sanjay Lalb680f702012-11-21 18:34:01 -08004801:
David Daney2c07ebb2013-08-01 13:22:33 -0700481 /* t1: contains the base of the ASID array, need to get the cpu id */
482 LONG_L t2, TI_CPU($28) /* smp_processor_id */
David Daneyea69f282013-08-01 13:22:35 -0700483 INT_SLL t2, t2, 2 /* x4 */
484 REG_ADDU t3, t1, t2
David Daney2c07ebb2013-08-01 13:22:33 -0700485 LONG_L k0, (t3)
James Hogan9b5c3392016-05-06 14:36:19 +0100486 andi k0, k0, MIPS_ENTRYHI_ASID
James Hogancaa1faa2015-12-16 23:49:26 +0000487 mtc0 k0, CP0_ENTRYHI
David Daney2c07ebb2013-08-01 13:22:33 -0700488 ehb
Sanjay Lalb680f702012-11-21 18:34:01 -0800489
David Daney2c07ebb2013-08-01 13:22:33 -0700490 /* Disable RDHWR access */
James Hogancaa1faa2015-12-16 23:49:26 +0000491 mtc0 zero, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800492
David Daney2c07ebb2013-08-01 13:22:33 -0700493 /* load the guest context from VCPU and return */
494 LONG_L $0, VCPU_R0(k1)
495 LONG_L $1, VCPU_R1(k1)
496 LONG_L $2, VCPU_R2(k1)
497 LONG_L $3, VCPU_R3(k1)
498 LONG_L $4, VCPU_R4(k1)
499 LONG_L $5, VCPU_R5(k1)
500 LONG_L $6, VCPU_R6(k1)
501 LONG_L $7, VCPU_R7(k1)
502 LONG_L $8, VCPU_R8(k1)
503 LONG_L $9, VCPU_R9(k1)
504 LONG_L $10, VCPU_R10(k1)
505 LONG_L $11, VCPU_R11(k1)
506 LONG_L $12, VCPU_R12(k1)
507 LONG_L $13, VCPU_R13(k1)
508 LONG_L $14, VCPU_R14(k1)
509 LONG_L $15, VCPU_R15(k1)
510 LONG_L $16, VCPU_R16(k1)
511 LONG_L $17, VCPU_R17(k1)
512 LONG_L $18, VCPU_R18(k1)
513 LONG_L $19, VCPU_R19(k1)
514 LONG_L $20, VCPU_R20(k1)
515 LONG_L $21, VCPU_R21(k1)
516 LONG_L $22, VCPU_R22(k1)
517 LONG_L $23, VCPU_R23(k1)
518 LONG_L $24, VCPU_R24(k1)
519 LONG_L $25, VCPU_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800520
David Daney2c07ebb2013-08-01 13:22:33 -0700521 /* $/k1 loaded later */
522 LONG_L $28, VCPU_R28(k1)
523 LONG_L $29, VCPU_R29(k1)
524 LONG_L $30, VCPU_R30(k1)
525 LONG_L $31, VCPU_R31(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800526
527FEXPORT(__kvm_mips_skip_guest_restore)
David Daney2c07ebb2013-08-01 13:22:33 -0700528 LONG_L k0, VCPU_HI(k1)
529 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800530
David Daney2c07ebb2013-08-01 13:22:33 -0700531 LONG_L k0, VCPU_LO(k1)
532 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800533
David Daney2c07ebb2013-08-01 13:22:33 -0700534 LONG_L k0, VCPU_R26(k1)
535 LONG_L k1, VCPU_R27(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800536
David Daney2c07ebb2013-08-01 13:22:33 -0700537 eret
Sanjay Lalb680f702012-11-21 18:34:01 -0800538
539__kvm_mips_return_to_host:
David Daney2c07ebb2013-08-01 13:22:33 -0700540 /* EBASE is already pointing to Linux */
541 LONG_L k1, VCPU_HOST_STACK(k1)
David Daneyea69f282013-08-01 13:22:35 -0700542 INT_ADDIU k1,k1, -PT_SIZE
Sanjay Lalb680f702012-11-21 18:34:01 -0800543
David Daney2c07ebb2013-08-01 13:22:33 -0700544 /* Restore host DDATA_LO */
545 LONG_L k0, PT_HOST_USERLOCAL(k1)
546 mtc0 k0, CP0_DDATA_LO
Sanjay Lalb680f702012-11-21 18:34:01 -0800547
David Daney2c07ebb2013-08-01 13:22:33 -0700548 /* Load context saved on the host stack */
549 LONG_L $0, PT_R0(k1)
550 LONG_L $1, PT_R1(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800551
Deng-Cheng Zhud116e812014-06-26 12:11:34 -0700552 /*
553 * r2/v0 is the return code, shift it down by 2 (arithmetic)
554 * to recover the err code
555 */
David Daneyea69f282013-08-01 13:22:35 -0700556 INT_SRA k0, v0, 2
David Daney2c07ebb2013-08-01 13:22:33 -0700557 move $2, k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800558
David Daney2c07ebb2013-08-01 13:22:33 -0700559 LONG_L $3, PT_R3(k1)
560 LONG_L $4, PT_R4(k1)
561 LONG_L $5, PT_R5(k1)
562 LONG_L $6, PT_R6(k1)
563 LONG_L $7, PT_R7(k1)
564 LONG_L $8, PT_R8(k1)
565 LONG_L $9, PT_R9(k1)
566 LONG_L $10, PT_R10(k1)
567 LONG_L $11, PT_R11(k1)
568 LONG_L $12, PT_R12(k1)
569 LONG_L $13, PT_R13(k1)
570 LONG_L $14, PT_R14(k1)
571 LONG_L $15, PT_R15(k1)
572 LONG_L $16, PT_R16(k1)
573 LONG_L $17, PT_R17(k1)
574 LONG_L $18, PT_R18(k1)
575 LONG_L $19, PT_R19(k1)
576 LONG_L $20, PT_R20(k1)
577 LONG_L $21, PT_R21(k1)
578 LONG_L $22, PT_R22(k1)
579 LONG_L $23, PT_R23(k1)
580 LONG_L $24, PT_R24(k1)
581 LONG_L $25, PT_R25(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800582
David Daney2c07ebb2013-08-01 13:22:33 -0700583 /* Host k0/k1 were not saved */
Sanjay Lalb680f702012-11-21 18:34:01 -0800584
David Daney2c07ebb2013-08-01 13:22:33 -0700585 LONG_L $28, PT_R28(k1)
586 LONG_L $29, PT_R29(k1)
587 LONG_L $30, PT_R30(k1)
Sanjay Lalb680f702012-11-21 18:34:01 -0800588
David Daney2c07ebb2013-08-01 13:22:33 -0700589 LONG_L k0, PT_HI(k1)
590 mthi k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800591
David Daney2c07ebb2013-08-01 13:22:33 -0700592 LONG_L k0, PT_LO(k1)
593 mtlo k0
Sanjay Lalb680f702012-11-21 18:34:01 -0800594
David Daney2c07ebb2013-08-01 13:22:33 -0700595 /* Restore RDHWR access */
David Daneyea69f282013-08-01 13:22:35 -0700596 PTR_LI k0, 0x2000000F
James Hogancaa1faa2015-12-16 23:49:26 +0000597 mtc0 k0, CP0_HWRENA
Sanjay Lalb680f702012-11-21 18:34:01 -0800598
David Daney2c07ebb2013-08-01 13:22:33 -0700599 /* Restore RA, which is the address we will return to */
James Hogancaa1faa2015-12-16 23:49:26 +0000600 LONG_L ra, PT_R31(k1)
601 j ra
David Daney2c07ebb2013-08-01 13:22:33 -0700602 nop
Sanjay Lalb680f702012-11-21 18:34:01 -0800603
Sanjay Lalb680f702012-11-21 18:34:01 -0800604VECTOR_END(MIPSX(GuestExceptionEnd))
605.end MIPSX(GuestException)
606
607MIPSX(exceptions):
608 ####
609 ##### The exception handlers.
610 #####
611 .word _C_LABEL(MIPSX(GuestException)) # 0
612 .word _C_LABEL(MIPSX(GuestException)) # 1
613 .word _C_LABEL(MIPSX(GuestException)) # 2
614 .word _C_LABEL(MIPSX(GuestException)) # 3
615 .word _C_LABEL(MIPSX(GuestException)) # 4
616 .word _C_LABEL(MIPSX(GuestException)) # 5
617 .word _C_LABEL(MIPSX(GuestException)) # 6
618 .word _C_LABEL(MIPSX(GuestException)) # 7
619 .word _C_LABEL(MIPSX(GuestException)) # 8
620 .word _C_LABEL(MIPSX(GuestException)) # 9
621 .word _C_LABEL(MIPSX(GuestException)) # 10
622 .word _C_LABEL(MIPSX(GuestException)) # 11
623 .word _C_LABEL(MIPSX(GuestException)) # 12
624 .word _C_LABEL(MIPSX(GuestException)) # 13
625 .word _C_LABEL(MIPSX(GuestException)) # 14
626 .word _C_LABEL(MIPSX(GuestException)) # 15
627 .word _C_LABEL(MIPSX(GuestException)) # 16
628 .word _C_LABEL(MIPSX(GuestException)) # 17
629 .word _C_LABEL(MIPSX(GuestException)) # 18
630 .word _C_LABEL(MIPSX(GuestException)) # 19
631 .word _C_LABEL(MIPSX(GuestException)) # 20
632 .word _C_LABEL(MIPSX(GuestException)) # 21
633 .word _C_LABEL(MIPSX(GuestException)) # 22
634 .word _C_LABEL(MIPSX(GuestException)) # 23
635 .word _C_LABEL(MIPSX(GuestException)) # 24
636 .word _C_LABEL(MIPSX(GuestException)) # 25
637 .word _C_LABEL(MIPSX(GuestException)) # 26
638 .word _C_LABEL(MIPSX(GuestException)) # 27
639 .word _C_LABEL(MIPSX(GuestException)) # 28
640 .word _C_LABEL(MIPSX(GuestException)) # 29
641 .word _C_LABEL(MIPSX(GuestException)) # 30
642 .word _C_LABEL(MIPSX(GuestException)) # 31