blob: dca2aa66599371f376845e8ab598c752ac7b08a6 [file] [log] [blame]
Sanjay Lalb680f702012-11-21 18:34:01 -08001/*
2* This file is subject to the terms and conditions of the GNU General Public
3* License. See the file "COPYING" in the main directory of this archive
4* for more details.
5*
6* Main entry point for the guest, exception handling.
7*
8* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
9* Authors: Sanjay Lal <sanjayl@kymasys.com>
10*/
11
12#include <asm/asm.h>
13#include <asm/asmmacro.h>
14#include <asm/regdef.h>
15#include <asm/mipsregs.h>
16#include <asm/stackframe.h>
17#include <asm/asm-offsets.h>
18
19
20#define _C_LABEL(x) x
21#define MIPSX(name) mips32_ ## name
22#define CALLFRAME_SIZ 32
23
24/*
25 * VECTOR
26 * exception vector entrypoint
27 */
28#define VECTOR(x, regmask) \
29 .ent _C_LABEL(x),0; \
30 EXPORT(x);
31
32#define VECTOR_END(x) \
33 EXPORT(x);
34
35/* Overload, Danger Will Robinson!! */
36#define PT_HOST_ASID PT_BVADDR
37#define PT_HOST_USERLOCAL PT_EPC
38
39#define CP0_DDATA_LO $28,3
40#define CP0_EBASE $15,1
41
42#define CP0_INTCTL $12,1
43#define CP0_SRSCTL $12,2
44#define CP0_SRSMAP $12,3
45#define CP0_HWRENA $7,0
46
47/* Resume Flags */
48#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
49
50#define RESUME_GUEST 0
51#define RESUME_HOST RESUME_FLAG_HOST
52
53/*
54 * __kvm_mips_vcpu_run: entry point to the guest
55 * a0: run
56 * a1: vcpu
57 */
58
59FEXPORT(__kvm_mips_vcpu_run)
60 .set push
61 .set noreorder
62 .set noat
63
64 /* k0/k1 not being used in host kernel context */
65 addiu k1,sp, -PT_SIZE
66 LONG_S $0, PT_R0(k1)
67 LONG_S $1, PT_R1(k1)
68 LONG_S $2, PT_R2(k1)
69 LONG_S $3, PT_R3(k1)
70
71 LONG_S $4, PT_R4(k1)
72 LONG_S $5, PT_R5(k1)
73 LONG_S $6, PT_R6(k1)
74 LONG_S $7, PT_R7(k1)
75
76 LONG_S $8, PT_R8(k1)
77 LONG_S $9, PT_R9(k1)
78 LONG_S $10, PT_R10(k1)
79 LONG_S $11, PT_R11(k1)
80 LONG_S $12, PT_R12(k1)
81 LONG_S $13, PT_R13(k1)
82 LONG_S $14, PT_R14(k1)
83 LONG_S $15, PT_R15(k1)
84 LONG_S $16, PT_R16(k1)
85 LONG_S $17, PT_R17(k1)
86
87 LONG_S $18, PT_R18(k1)
88 LONG_S $19, PT_R19(k1)
89 LONG_S $20, PT_R20(k1)
90 LONG_S $21, PT_R21(k1)
91 LONG_S $22, PT_R22(k1)
92 LONG_S $23, PT_R23(k1)
93 LONG_S $24, PT_R24(k1)
94 LONG_S $25, PT_R25(k1)
95
96 /* XXXKYMA k0/k1 not saved, not being used if we got here through an ioctl() */
97
98 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)
102
103 /* Save hi/lo */
104 mflo v0
105 LONG_S v0, PT_LO(k1)
106 mfhi v1
107 LONG_S v1, PT_HI(k1)
108
109 /* Save host status */
110 mfc0 v0, CP0_STATUS
111 LONG_S v0, PT_STATUS(k1)
112
113 /* Save host ASID, shove it into the BVADDR location */
114 mfc0 v1,CP0_ENTRYHI
115 andi v1, 0xff
116 LONG_S v1, PT_HOST_ASID(k1)
117
118 /* 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)
121
122 /* DDATA_LO has pointer to vcpu */
123 mtc0 a1,CP0_DDATA_LO
124
125 /* Offset into vcpu->arch */
126 addiu k1, a1, VCPU_HOST_ARCH
127
128 /* Save the host stack to VCPU, used for exception processing when we exit from the Guest */
129 LONG_S sp, VCPU_HOST_STACK(k1)
130
131 /* Save the kernel gp as well */
132 LONG_S gp, VCPU_HOST_GP(k1)
133
134 /* Setup status register for running the guest in UM, interrupts are disabled */
135 li k0,(ST0_EXL | KSU_USER| ST0_BEV)
136 mtc0 k0,CP0_STATUS
137 ehb
138
139 /* load up the new EBASE */
140 LONG_L k0, VCPU_GUEST_EBASE(k1)
141 mtc0 k0,CP0_EBASE
142
143 /* Now that the new EBASE has been loaded, unset BEV, set interrupt mask as it was
144 * but make sure that timer interrupts are enabled
145 */
146 li k0,(ST0_EXL | KSU_USER | ST0_IE)
147 andi v0, v0, ST0_IM
148 or k0, k0, v0
149 mtc0 k0,CP0_STATUS
150 ehb
151
152
153 /* Set Guest EPC */
154 LONG_L t0, VCPU_PC(k1)
155 mtc0 t0, CP0_EPC
156
157FEXPORT(__kvm_mips_load_asid)
158 /* Set the ASID for the Guest Kernel */
159 sll t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
160 /* addresses shift to 0x80000000 */
161 bltz t0, 1f /* If kernel */
162 addiu t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
163 addiu t1, k1, VCPU_GUEST_USER_ASID /* else user */
1641:
165 /* t1: contains the base of the ASID array, need to get the cpu id */
166 LONG_L t2, TI_CPU($28) /* smp_processor_id */
167 sll t2, t2, 2 /* x4 */
168 addu t3, t1, t2
169 LONG_L k0, (t3)
170 andi k0, k0, 0xff
171 mtc0 k0,CP0_ENTRYHI
172 ehb
173
174 /* Disable RDHWR access */
175 mtc0 zero, CP0_HWRENA
176
177 /* Now load up the Guest Context from VCPU */
178 LONG_L $1, VCPU_R1(k1)
179 LONG_L $2, VCPU_R2(k1)
180 LONG_L $3, VCPU_R3(k1)
181
182 LONG_L $4, VCPU_R4(k1)
183 LONG_L $5, VCPU_R5(k1)
184 LONG_L $6, VCPU_R6(k1)
185 LONG_L $7, VCPU_R7(k1)
186
187 LONG_L $8, VCPU_R8(k1)
188 LONG_L $9, VCPU_R9(k1)
189 LONG_L $10, VCPU_R10(k1)
190 LONG_L $11, VCPU_R11(k1)
191 LONG_L $12, VCPU_R12(k1)
192 LONG_L $13, VCPU_R13(k1)
193 LONG_L $14, VCPU_R14(k1)
194 LONG_L $15, VCPU_R15(k1)
195 LONG_L $16, VCPU_R16(k1)
196 LONG_L $17, VCPU_R17(k1)
197 LONG_L $18, VCPU_R18(k1)
198 LONG_L $19, VCPU_R19(k1)
199 LONG_L $20, VCPU_R20(k1)
200 LONG_L $21, VCPU_R21(k1)
201 LONG_L $22, VCPU_R22(k1)
202 LONG_L $23, VCPU_R23(k1)
203 LONG_L $24, VCPU_R24(k1)
204 LONG_L $25, VCPU_R25(k1)
205
206 /* k0/k1 loaded up later */
207
208 LONG_L $28, VCPU_R28(k1)
209 LONG_L $29, VCPU_R29(k1)
210 LONG_L $30, VCPU_R30(k1)
211 LONG_L $31, VCPU_R31(k1)
212
213 /* Restore hi/lo */
214 LONG_L k0, VCPU_LO(k1)
215 mtlo k0
216
217 LONG_L k0, VCPU_HI(k1)
218 mthi k0
219
220FEXPORT(__kvm_mips_load_k0k1)
221 /* Restore the guest's k0/k1 registers */
222 LONG_L k0, VCPU_R26(k1)
223 LONG_L k1, VCPU_R27(k1)
224
225 /* Jump to guest */
226 eret
227 .set pop
228
229VECTOR(MIPSX(exception), unknown)
230/*
231 * Find out what mode we came from and jump to the proper handler.
232 */
233 .set push
234 .set noat
235 .set noreorder
236 mtc0 k0, CP0_ERROREPC #01: Save guest k0
237 ehb #02:
238
239 mfc0 k0, CP0_EBASE #02: Get EBASE
240 srl k0, k0, 10 #03: Get rid of CPUNum
241 sll k0, k0, 10 #04
242 LONG_S k1, 0x3000(k0) #05: Save k1 @ offset 0x3000
243 addiu k0, k0, 0x2000 #06: Exception handler is installed @ offset 0x2000
244 j k0 #07: jump to the function
245 nop #08: branch delay slot
246 .set push
247VECTOR_END(MIPSX(exceptionEnd))
248.end MIPSX(exception)
249
250/*
251 * Generic Guest exception handler. We end up here when the guest
252 * does something that causes a trap to kernel mode.
253 *
254 */
255NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
256 .set push
257 .set noat
258 .set noreorder
259
260 /* Get the VCPU pointer from DDTATA_LO */
261 mfc0 k1, CP0_DDATA_LO
262 addiu k1, k1, VCPU_HOST_ARCH
263
264 /* Start saving Guest context to VCPU */
265 LONG_S $0, VCPU_R0(k1)
266 LONG_S $1, VCPU_R1(k1)
267 LONG_S $2, VCPU_R2(k1)
268 LONG_S $3, VCPU_R3(k1)
269 LONG_S $4, VCPU_R4(k1)
270 LONG_S $5, VCPU_R5(k1)
271 LONG_S $6, VCPU_R6(k1)
272 LONG_S $7, VCPU_R7(k1)
273 LONG_S $8, VCPU_R8(k1)
274 LONG_S $9, VCPU_R9(k1)
275 LONG_S $10, VCPU_R10(k1)
276 LONG_S $11, VCPU_R11(k1)
277 LONG_S $12, VCPU_R12(k1)
278 LONG_S $13, VCPU_R13(k1)
279 LONG_S $14, VCPU_R14(k1)
280 LONG_S $15, VCPU_R15(k1)
281 LONG_S $16, VCPU_R16(k1)
282 LONG_S $17,VCPU_R17(k1)
283 LONG_S $18, VCPU_R18(k1)
284 LONG_S $19, VCPU_R19(k1)
285 LONG_S $20, VCPU_R20(k1)
286 LONG_S $21, VCPU_R21(k1)
287 LONG_S $22, VCPU_R22(k1)
288 LONG_S $23, VCPU_R23(k1)
289 LONG_S $24, VCPU_R24(k1)
290 LONG_S $25, VCPU_R25(k1)
291
292 /* Guest k0/k1 saved later */
293
294 LONG_S $28, VCPU_R28(k1)
295 LONG_S $29, VCPU_R29(k1)
296 LONG_S $30, VCPU_R30(k1)
297 LONG_S $31, VCPU_R31(k1)
298
299 /* We need to save hi/lo and restore them on
300 * the way out
301 */
302 mfhi t0
303 LONG_S t0, VCPU_HI(k1)
304
305 mflo t0
306 LONG_S t0, VCPU_LO(k1)
307
308 /* Finally save guest k0/k1 to VCPU */
309 mfc0 t0, CP0_ERROREPC
310 LONG_S t0, VCPU_R26(k1)
311
312 /* Get GUEST k1 and save it in VCPU */
313 la t1, ~0x2ff
314 mfc0 t0, CP0_EBASE
315 and t0, t0, t1
316 LONG_L t0, 0x3000(t0)
317 LONG_S t0, VCPU_R27(k1)
318
319 /* Now that context has been saved, we can use other registers */
320
321 /* Restore vcpu */
322 mfc0 a1, CP0_DDATA_LO
323 move s1, a1
324
325 /* Restore run (vcpu->run) */
326 LONG_L a0, VCPU_RUN(a1)
327 /* Save pointer to run in s0, will be saved by the compiler */
328 move s0, a0
329
330
331 /* Save Host level EPC, BadVaddr and Cause to VCPU, useful to process the exception */
332 mfc0 k0,CP0_EPC
333 LONG_S k0, VCPU_PC(k1)
334
335 mfc0 k0, CP0_BADVADDR
336 LONG_S k0, VCPU_HOST_CP0_BADVADDR(k1)
337
338 mfc0 k0, CP0_CAUSE
339 LONG_S k0, VCPU_HOST_CP0_CAUSE(k1)
340
341 mfc0 k0, CP0_ENTRYHI
342 LONG_S k0, VCPU_HOST_ENTRYHI(k1)
343
344 /* Now restore the host state just enough to run the handlers */
345
346 /* Swtich EBASE to the one used by Linux */
347 /* load up the host EBASE */
348 mfc0 v0, CP0_STATUS
349
350 .set at
351 or k0, v0, ST0_BEV
352 .set noat
353
354 mtc0 k0, CP0_STATUS
355 ehb
356
357 LONG_L k0, VCPU_HOST_EBASE(k1)
358 mtc0 k0,CP0_EBASE
359
360
361 /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
362 .set at
363 and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
364 or v0, v0, ST0_CU0
365 .set noat
366 mtc0 v0, CP0_STATUS
367 ehb
368
369 /* Load up host GP */
370 LONG_L gp, VCPU_HOST_GP(k1)
371
372 /* Need a stack before we can jump to "C" */
373 LONG_L sp, VCPU_HOST_STACK(k1)
374
375 /* Saved host state */
376 addiu sp,sp, -PT_SIZE
377
378 /* XXXKYMA do we need to load the host ASID, maybe not because the
379 * kernel entries are marked GLOBAL, need to verify
380 */
381
382 /* Restore host DDATA_LO */
383 LONG_L k0, PT_HOST_USERLOCAL(sp)
384 mtc0 k0, CP0_DDATA_LO
385
386 /* Restore RDHWR access */
387 la k0, 0x2000000F
388 mtc0 k0, CP0_HWRENA
389
390 /* Jump to handler */
391FEXPORT(__kvm_mips_jump_to_handler)
392 /* XXXKYMA: not sure if this is safe, how large is the stack?? */
393 /* Now jump to the kvm_mips_handle_exit() to see if we can deal with this in the kernel */
394 la t9,kvm_mips_handle_exit
395 jalr.hb t9
396 addiu sp,sp, -CALLFRAME_SIZ /* BD Slot */
397
398 /* Return from handler Make sure interrupts are disabled */
399 di
400 ehb
401
402 /* XXXKYMA: k0/k1 could have been blown away if we processed an exception
403 * while we were handling the exception from the guest, reload k1
404 */
405 move k1, s1
406 addiu k1, k1, VCPU_HOST_ARCH
407
408 /* Check return value, should tell us if we are returning to the host (handle I/O etc)
409 * or resuming the guest
410 */
411 andi t0, v0, RESUME_HOST
412 bnez t0, __kvm_mips_return_to_host
413 nop
414
415__kvm_mips_return_to_guest:
416 /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
417 mtc0 s1, CP0_DDATA_LO
418
419 /* Load up the Guest EBASE to minimize the window where BEV is set */
420 LONG_L t0, VCPU_GUEST_EBASE(k1)
421
422 /* Switch EBASE back to the one used by KVM */
423 mfc0 v1, CP0_STATUS
424 .set at
425 or k0, v1, ST0_BEV
426 .set noat
427 mtc0 k0, CP0_STATUS
428 ehb
429 mtc0 t0,CP0_EBASE
430
431 /* Setup status register for running guest in UM */
432 .set at
433 or v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
434 and v1, v1, ~ST0_CU0
435 .set noat
436 mtc0 v1, CP0_STATUS
437 ehb
438
439
440 /* Set Guest EPC */
441 LONG_L t0, VCPU_PC(k1)
442 mtc0 t0, CP0_EPC
443
444 /* Set the ASID for the Guest Kernel */
445 sll t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
446 /* addresses shift to 0x80000000 */
447 bltz t0, 1f /* If kernel */
448 addiu t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
449 addiu t1, k1, VCPU_GUEST_USER_ASID /* else user */
4501:
451 /* t1: contains the base of the ASID array, need to get the cpu id */
452 LONG_L t2, TI_CPU($28) /* smp_processor_id */
453 sll t2, t2, 2 /* x4 */
454 addu t3, t1, t2
455 LONG_L k0, (t3)
456 andi k0, k0, 0xff
457 mtc0 k0,CP0_ENTRYHI
458 ehb
459
460 /* Disable RDHWR access */
461 mtc0 zero, CP0_HWRENA
462
463 /* load the guest context from VCPU and return */
464 LONG_L $0, VCPU_R0(k1)
465 LONG_L $1, VCPU_R1(k1)
466 LONG_L $2, VCPU_R2(k1)
467 LONG_L $3, VCPU_R3(k1)
468 LONG_L $4, VCPU_R4(k1)
469 LONG_L $5, VCPU_R5(k1)
470 LONG_L $6, VCPU_R6(k1)
471 LONG_L $7, VCPU_R7(k1)
472 LONG_L $8, VCPU_R8(k1)
473 LONG_L $9, VCPU_R9(k1)
474 LONG_L $10, VCPU_R10(k1)
475 LONG_L $11, VCPU_R11(k1)
476 LONG_L $12, VCPU_R12(k1)
477 LONG_L $13, VCPU_R13(k1)
478 LONG_L $14, VCPU_R14(k1)
479 LONG_L $15, VCPU_R15(k1)
480 LONG_L $16, VCPU_R16(k1)
481 LONG_L $17, VCPU_R17(k1)
482 LONG_L $18, VCPU_R18(k1)
483 LONG_L $19, VCPU_R19(k1)
484 LONG_L $20, VCPU_R20(k1)
485 LONG_L $21, VCPU_R21(k1)
486 LONG_L $22, VCPU_R22(k1)
487 LONG_L $23, VCPU_R23(k1)
488 LONG_L $24, VCPU_R24(k1)
489 LONG_L $25, VCPU_R25(k1)
490
491 /* $/k1 loaded later */
492 LONG_L $28, VCPU_R28(k1)
493 LONG_L $29, VCPU_R29(k1)
494 LONG_L $30, VCPU_R30(k1)
495 LONG_L $31, VCPU_R31(k1)
496
497FEXPORT(__kvm_mips_skip_guest_restore)
498 LONG_L k0, VCPU_HI(k1)
499 mthi k0
500
501 LONG_L k0, VCPU_LO(k1)
502 mtlo k0
503
504 LONG_L k0, VCPU_R26(k1)
505 LONG_L k1, VCPU_R27(k1)
506
507 eret
508
509__kvm_mips_return_to_host:
510 /* EBASE is already pointing to Linux */
511 LONG_L k1, VCPU_HOST_STACK(k1)
512 addiu k1,k1, -PT_SIZE
513
514 /* Restore host DDATA_LO */
515 LONG_L k0, PT_HOST_USERLOCAL(k1)
516 mtc0 k0, CP0_DDATA_LO
517
518 /* Restore host ASID */
519 LONG_L k0, PT_HOST_ASID(sp)
520 andi k0, 0xff
521 mtc0 k0,CP0_ENTRYHI
522 ehb
523
524 /* Load context saved on the host stack */
525 LONG_L $0, PT_R0(k1)
526 LONG_L $1, PT_R1(k1)
527
528 /* r2/v0 is the return code, shift it down by 2 (arithmetic) to recover the err code */
529 sra k0, v0, 2
530 move $2, k0
531
532 LONG_L $3, PT_R3(k1)
533 LONG_L $4, PT_R4(k1)
534 LONG_L $5, PT_R5(k1)
535 LONG_L $6, PT_R6(k1)
536 LONG_L $7, PT_R7(k1)
537 LONG_L $8, PT_R8(k1)
538 LONG_L $9, PT_R9(k1)
539 LONG_L $10, PT_R10(k1)
540 LONG_L $11, PT_R11(k1)
541 LONG_L $12, PT_R12(k1)
542 LONG_L $13, PT_R13(k1)
543 LONG_L $14, PT_R14(k1)
544 LONG_L $15, PT_R15(k1)
545 LONG_L $16, PT_R16(k1)
546 LONG_L $17, PT_R17(k1)
547 LONG_L $18, PT_R18(k1)
548 LONG_L $19, PT_R19(k1)
549 LONG_L $20, PT_R20(k1)
550 LONG_L $21, PT_R21(k1)
551 LONG_L $22, PT_R22(k1)
552 LONG_L $23, PT_R23(k1)
553 LONG_L $24, PT_R24(k1)
554 LONG_L $25, PT_R25(k1)
555
556 /* Host k0/k1 were not saved */
557
558 LONG_L $28, PT_R28(k1)
559 LONG_L $29, PT_R29(k1)
560 LONG_L $30, PT_R30(k1)
561
562 LONG_L k0, PT_HI(k1)
563 mthi k0
564
565 LONG_L k0, PT_LO(k1)
566 mtlo k0
567
568 /* Restore RDHWR access */
569 la k0, 0x2000000F
570 mtc0 k0, CP0_HWRENA
571
572
573 /* Restore RA, which is the address we will return to */
574 LONG_L ra, PT_R31(k1)
575 j ra
576 nop
577
578 .set pop
579VECTOR_END(MIPSX(GuestExceptionEnd))
580.end MIPSX(GuestException)
581
582MIPSX(exceptions):
583 ####
584 ##### The exception handlers.
585 #####
586 .word _C_LABEL(MIPSX(GuestException)) # 0
587 .word _C_LABEL(MIPSX(GuestException)) # 1
588 .word _C_LABEL(MIPSX(GuestException)) # 2
589 .word _C_LABEL(MIPSX(GuestException)) # 3
590 .word _C_LABEL(MIPSX(GuestException)) # 4
591 .word _C_LABEL(MIPSX(GuestException)) # 5
592 .word _C_LABEL(MIPSX(GuestException)) # 6
593 .word _C_LABEL(MIPSX(GuestException)) # 7
594 .word _C_LABEL(MIPSX(GuestException)) # 8
595 .word _C_LABEL(MIPSX(GuestException)) # 9
596 .word _C_LABEL(MIPSX(GuestException)) # 10
597 .word _C_LABEL(MIPSX(GuestException)) # 11
598 .word _C_LABEL(MIPSX(GuestException)) # 12
599 .word _C_LABEL(MIPSX(GuestException)) # 13
600 .word _C_LABEL(MIPSX(GuestException)) # 14
601 .word _C_LABEL(MIPSX(GuestException)) # 15
602 .word _C_LABEL(MIPSX(GuestException)) # 16
603 .word _C_LABEL(MIPSX(GuestException)) # 17
604 .word _C_LABEL(MIPSX(GuestException)) # 18
605 .word _C_LABEL(MIPSX(GuestException)) # 19
606 .word _C_LABEL(MIPSX(GuestException)) # 20
607 .word _C_LABEL(MIPSX(GuestException)) # 21
608 .word _C_LABEL(MIPSX(GuestException)) # 22
609 .word _C_LABEL(MIPSX(GuestException)) # 23
610 .word _C_LABEL(MIPSX(GuestException)) # 24
611 .word _C_LABEL(MIPSX(GuestException)) # 25
612 .word _C_LABEL(MIPSX(GuestException)) # 26
613 .word _C_LABEL(MIPSX(GuestException)) # 27
614 .word _C_LABEL(MIPSX(GuestException)) # 28
615 .word _C_LABEL(MIPSX(GuestException)) # 29
616 .word _C_LABEL(MIPSX(GuestException)) # 30
617 .word _C_LABEL(MIPSX(GuestException)) # 31
618
619
620/* This routine makes changes to the instruction stream effective to the hardware.
621 * It should be called after the instruction stream is written.
622 * On return, the new instructions are effective.
623 * Inputs:
624 * a0 = Start address of new instruction stream
625 * a1 = Size, in bytes, of new instruction stream
626 */
627
628#define HW_SYNCI_Step $1
629LEAF(MIPSX(SyncICache))
630 .set push
631 .set mips32r2
632 beq a1, zero, 20f
633 nop
634 addu a1, a0, a1
635 rdhwr v0, HW_SYNCI_Step
636 beq v0, zero, 20f
637 nop
638
63910:
640 synci 0(a0)
641 addu a0, a0, v0
642 sltu v1, a0, a1
643 bne v1, zero, 10b
644 nop
645 sync
64620:
647 jr.hb ra
648 nop
649 .set pop
650END(MIPSX(SyncICache))