Merge tag 'regmap-v3.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[linux-2.6.git] / arch / mips / kvm / kvm_locore.S
blobdca2aa66599371f376845e8ab598c752ac7b08a6
1 /*
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.
6 * Main entry point for the guest, exception handling.
8 * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
9 * Authors: Sanjay Lal <sanjayl@kymasys.com>
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>
20 #define _C_LABEL(x)     x
21 #define MIPSX(name)     mips32_ ## name
22 #define CALLFRAME_SIZ   32
25  * VECTOR
26  *  exception vector entrypoint
27  */
28 #define VECTOR(x, regmask)      \
29     .ent    _C_LABEL(x),0;      \
30     EXPORT(x);
32 #define VECTOR_END(x)      \
33     EXPORT(x);
35 /* Overload, Danger Will Robinson!! */
36 #define PT_HOST_ASID        PT_BVADDR
37 #define PT_HOST_USERLOCAL   PT_EPC
39 #define CP0_DDATA_LO        $28,3
40 #define CP0_EBASE           $15,1
42 #define CP0_INTCTL          $12,1
43 #define CP0_SRSCTL          $12,2
44 #define CP0_SRSMAP          $12,3
45 #define CP0_HWRENA          $7,0
47 /* Resume Flags */
48 #define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
50 #define RESUME_GUEST            0
51 #define RESUME_HOST             RESUME_FLAG_HOST
54  * __kvm_mips_vcpu_run: entry point to the guest
55  * a0: run
56  * a1: vcpu
57  */
59 FEXPORT(__kvm_mips_vcpu_run)
60     .set    push
61     .set    noreorder
62     .set    noat
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)
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)
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)
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)
96         /* XXXKYMA k0/k1 not saved, not being used if we got here through an ioctl() */
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)
103     /* Save hi/lo */
104         mflo            v0
105         LONG_S          v0, PT_LO(k1)
106         mfhi            v1
107         LONG_S          v1, PT_HI(k1)
109         /* Save host status */
110         mfc0            v0, CP0_STATUS
111         LONG_S          v0, PT_STATUS(k1)
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)
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)
122     /* DDATA_LO has pointer to vcpu */
123     mtc0        a1,CP0_DDATA_LO
125     /* Offset into vcpu->arch */
126         addiu           k1, a1, VCPU_HOST_ARCH
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)
131     /* Save the kernel gp as well */
132     LONG_S      gp, VCPU_HOST_GP(k1)
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
139     /* load up the new EBASE */
140     LONG_L      k0, VCPU_GUEST_EBASE(k1)
141     mtc0        k0,CP0_EBASE
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
153         /* Set Guest EPC */
154         LONG_L          t0, VCPU_PC(k1)
155         mtc0            t0, CP0_EPC
157 FEXPORT(__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 */
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
174     /* Disable RDHWR access */
175     mtc0    zero,  CP0_HWRENA
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)
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)
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)
206     /* k0/k1 loaded up later */
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)
213     /* Restore hi/lo */
214         LONG_L          k0, VCPU_LO(k1)
215         mtlo            k0
217         LONG_L          k0, VCPU_HI(k1)
218         mthi            k0
220 FEXPORT(__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)
225     /* Jump to guest */
226         eret
227         .set    pop
229 VECTOR(MIPSX(exception), unknown)
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:
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
247 VECTOR_END(MIPSX(exceptionEnd))
248 .end MIPSX(exception)
251  * Generic Guest exception handler. We end up here when the guest
252  * does something that causes a trap to kernel mode.
254  */
255 NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
256     .set    push
257     .set    noat
258     .set    noreorder
260     /* Get the VCPU pointer from DDTATA_LO */
261     mfc0        k1, CP0_DDATA_LO
262         addiu           k1, k1, VCPU_HOST_ARCH
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)
292     /* Guest k0/k1 saved later */
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)
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)
305     mflo    t0
306     LONG_S  t0, VCPU_LO(k1)
308     /* Finally save guest k0/k1 to VCPU */
309     mfc0    t0, CP0_ERROREPC
310     LONG_S  t0, VCPU_R26(k1)
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)
319     /* Now that context has been saved, we can use other registers */
321     /* Restore vcpu */
322     mfc0        a1, CP0_DDATA_LO
323     move        s1, a1
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
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)
335     mfc0    k0, CP0_BADVADDR
336     LONG_S  k0, VCPU_HOST_CP0_BADVADDR(k1)
338     mfc0    k0, CP0_CAUSE
339     LONG_S  k0, VCPU_HOST_CP0_CAUSE(k1)
341     mfc0    k0, CP0_ENTRYHI
342     LONG_S  k0, VCPU_HOST_ENTRYHI(k1)
344     /* Now restore the host state just enough to run the handlers */
346     /* Swtich EBASE to the one used by Linux */
347     /* load up the host EBASE */
348     mfc0        v0, CP0_STATUS
350     .set at
351         or          k0, v0, ST0_BEV
352     .set noat
354     mtc0        k0, CP0_STATUS
355     ehb
357     LONG_L      k0, VCPU_HOST_EBASE(k1)
358     mtc0        k0,CP0_EBASE
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
369     /* Load up host GP */
370     LONG_L  gp, VCPU_HOST_GP(k1)
372     /* Need a stack before we can jump to "C" */
373     LONG_L  sp, VCPU_HOST_STACK(k1)
375     /* Saved host state */
376     addiu   sp,sp, -PT_SIZE
378     /* XXXKYMA do we need to load the host ASID, maybe not because the
379      * kernel entries are marked GLOBAL, need to verify
380      */
382     /* Restore host DDATA_LO */
383     LONG_L      k0, PT_HOST_USERLOCAL(sp)
384     mtc0        k0, CP0_DDATA_LO
386     /* Restore RDHWR access */
387     la      k0, 0x2000000F
388     mtc0    k0,  CP0_HWRENA
390     /* Jump to handler */
391 FEXPORT(__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 */
398     /* Return from handler Make sure interrupts are disabled */
399     di
400     ehb
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
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
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
419     /* Load up the Guest EBASE to minimize the window where BEV is set */
420     LONG_L      t0, VCPU_GUEST_EBASE(k1)
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
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
440         /* Set Guest EPC */
441         LONG_L          t0, VCPU_PC(k1)
442         mtc0            t0, CP0_EPC
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 */
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
460     /* Disable RDHWR access */
461     mtc0    zero,  CP0_HWRENA
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)
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)
497 FEXPORT(__kvm_mips_skip_guest_restore)
498     LONG_L  k0, VCPU_HI(k1)
499     mthi    k0
501     LONG_L  k0, VCPU_LO(k1)
502     mtlo    k0
504     LONG_L  k0, VCPU_R26(k1)
505     LONG_L  k1, VCPU_R27(k1)
507     eret
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
514     /* Restore host DDATA_LO */
515     LONG_L      k0, PT_HOST_USERLOCAL(k1)
516     mtc0        k0, CP0_DDATA_LO
518     /* Restore host ASID */
519     LONG_L      k0, PT_HOST_ASID(sp)
520     andi        k0, 0xff
521     mtc0        k0,CP0_ENTRYHI
522     ehb
524     /* Load context saved on the host stack */
525     LONG_L  $0, PT_R0(k1)
526     LONG_L  $1, PT_R1(k1)
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
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)
556     /* Host k0/k1 were not saved */
558     LONG_L  $28, PT_R28(k1)
559     LONG_L  $29, PT_R29(k1)
560     LONG_L  $30, PT_R30(k1)
562     LONG_L  k0, PT_HI(k1)
563     mthi    k0
565     LONG_L  k0, PT_LO(k1)
566     mtlo    k0
568     /* Restore RDHWR access */
569     la      k0, 0x2000000F
570     mtc0    k0,  CP0_HWRENA
573     /* Restore RA, which is the address we will return to */
574     LONG_L  ra, PT_R31(k1)
575     j       ra
576     nop
578     .set    pop
579 VECTOR_END(MIPSX(GuestExceptionEnd))
580 .end MIPSX(GuestException)
582 MIPSX(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
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  */
628 #define HW_SYNCI_Step       $1
629 LEAF(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
640     synci   0(a0)
641     addu    a0, a0, v0
642     sltu    v1, a0, a1
643     bne     v1, zero, 10b
644     nop
645     sync
647     jr.hb   ra
648     nop
649     .set pop
650 END(MIPSX(SyncICache))