KVM/MIPS32: Entry point for trampolining to the guest and trap handlers.
- __kvm_mips_vcpu_run: main entry point to enter guest, we save kernel context, load up guest context from and ERET to guest context. - mips32_exception: L1 exception handler(s), save k0/k1 and jump to main handlers. - mips32_GuestException: Generic exception handlers for exceptions/interrupts while in guest context. Save guest context, restore some kernel context and jump to main 'C' handler: kvm_mips_handle_exit() Signed-off-by: Sanjay Lal <sanjayl@kymasys.com> Cc: kvm@vger.kernel.org Cc: linux-mips@linux-mips.org Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
		
							parent
							
								
									740765ce45
								
							
						
					
					
						commit
						b680f70fc1
					
				
							
								
								
									
										650
									
								
								arch/mips/kvm/kvm_locore.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										650
									
								
								arch/mips/kvm/kvm_locore.S
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,650 @@ | ||||
| /* | ||||
| * This file is subject to the terms and conditions of the GNU General Public | ||||
| * License.  See the file "COPYING" in the main directory of this archive | ||||
| * for more details. | ||||
| * | ||||
| * Main entry point for the guest, exception handling. | ||||
| * | ||||
| * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved. | ||||
| * Authors: Sanjay Lal <sanjayl@kymasys.com>
 | ||||
| */ | ||||
| 
 | ||||
| #include <asm/asm.h> | ||||
| #include <asm/asmmacro.h> | ||||
| #include <asm/regdef.h> | ||||
| #include <asm/mipsregs.h> | ||||
| #include <asm/stackframe.h> | ||||
| #include <asm/asm-offsets.h> | ||||
| 
 | ||||
| 
 | ||||
| #define _C_LABEL(x)     x | ||||
| #define MIPSX(name)     mips32_ ## name | ||||
| #define CALLFRAME_SIZ   32 | ||||
| 
 | ||||
| /* | ||||
|  * VECTOR | ||||
|  *  exception vector entrypoint | ||||
|  */ | ||||
| #define VECTOR(x, regmask)      \ | ||||
|     .ent    _C_LABEL(x),0;      \
 | ||||
|     EXPORT(x);
 | ||||
| 
 | ||||
| #define VECTOR_END(x)      \ | ||||
|     EXPORT(x);
 | ||||
| 
 | ||||
| /* Overload, Danger Will Robinson!! */ | ||||
| #define PT_HOST_ASID        PT_BVADDR | ||||
| #define PT_HOST_USERLOCAL   PT_EPC | ||||
| 
 | ||||
| #define CP0_DDATA_LO        $28,3 | ||||
| #define CP0_EBASE           $15,1 | ||||
| 
 | ||||
| #define CP0_INTCTL          $12,1 | ||||
| #define CP0_SRSCTL          $12,2 | ||||
| #define CP0_SRSMAP          $12,3 | ||||
| #define CP0_HWRENA          $7,0 | ||||
| 
 | ||||
| /* Resume Flags */ | ||||
| #define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */ | ||||
| 
 | ||||
| #define RESUME_GUEST            0 | ||||
| #define RESUME_HOST             RESUME_FLAG_HOST | ||||
| 
 | ||||
| /* | ||||
|  * __kvm_mips_vcpu_run: entry point to the guest | ||||
|  * a0: run | ||||
|  * a1: vcpu | ||||
|  */ | ||||
| 
 | ||||
| FEXPORT(__kvm_mips_vcpu_run) | ||||
|     .set    push
 | ||||
|     .set    noreorder
 | ||||
|     .set    noat
 | ||||
| 
 | ||||
|     /* k0/k1 not being used in host kernel context */ | ||||
| 	addiu  		k1,sp, -PT_SIZE | ||||
|     LONG_S	    $0, PT_R0(k1) | ||||
|     LONG_S     	$1, PT_R1(k1) | ||||
|     LONG_S     	$2, PT_R2(k1) | ||||
|     LONG_S     	$3, PT_R3(k1) | ||||
| 
 | ||||
|     LONG_S     	$4, PT_R4(k1) | ||||
|     LONG_S     	$5, PT_R5(k1) | ||||
|     LONG_S     	$6, PT_R6(k1) | ||||
|     LONG_S     	$7, PT_R7(k1) | ||||
| 
 | ||||
|     LONG_S     	$8,  PT_R8(k1) | ||||
|     LONG_S     	$9,  PT_R9(k1) | ||||
|     LONG_S     	$10, PT_R10(k1) | ||||
|     LONG_S     	$11, PT_R11(k1) | ||||
|     LONG_S     	$12, PT_R12(k1) | ||||
|     LONG_S     	$13, PT_R13(k1) | ||||
|     LONG_S     	$14, PT_R14(k1) | ||||
|     LONG_S     	$15, PT_R15(k1) | ||||
|     LONG_S     	$16, PT_R16(k1) | ||||
|     LONG_S     	$17, PT_R17(k1) | ||||
| 
 | ||||
|     LONG_S     	$18, PT_R18(k1) | ||||
|     LONG_S     	$19, PT_R19(k1) | ||||
|     LONG_S     	$20, PT_R20(k1) | ||||
|     LONG_S     	$21, PT_R21(k1) | ||||
|     LONG_S     	$22, PT_R22(k1) | ||||
|     LONG_S     	$23, PT_R23(k1) | ||||
|     LONG_S     	$24, PT_R24(k1) | ||||
|     LONG_S     	$25, PT_R25(k1) | ||||
| 
 | ||||
| 	/* XXXKYMA k0/k1 not saved, not being used if we got here through an ioctl() */ | ||||
| 
 | ||||
|     LONG_S     	$28, PT_R28(k1) | ||||
|     LONG_S     	$29, PT_R29(k1) | ||||
|     LONG_S     	$30, PT_R30(k1) | ||||
|     LONG_S     	$31, PT_R31(k1) | ||||
| 
 | ||||
|     /* Save hi/lo */ | ||||
| 	mflo		v0 | ||||
| 	LONG_S		v0, PT_LO(k1) | ||||
| 	mfhi   		v1 | ||||
| 	LONG_S		v1, PT_HI(k1) | ||||
| 
 | ||||
| 	/* Save host status */ | ||||
| 	mfc0		v0, CP0_STATUS | ||||
| 	LONG_S		v0, PT_STATUS(k1) | ||||
| 
 | ||||
| 	/* Save host ASID, shove it into the BVADDR location */ | ||||
| 	mfc0 		v1,CP0_ENTRYHI | ||||
| 	andi		v1, 0xff | ||||
| 	LONG_S		v1, PT_HOST_ASID(k1) | ||||
| 
 | ||||
|     /* Save DDATA_LO, will be used to store pointer to vcpu */ | ||||
|     mfc0        v1, CP0_DDATA_LO | ||||
|     LONG_S      v1, PT_HOST_USERLOCAL(k1) | ||||
| 
 | ||||
|     /* DDATA_LO has pointer to vcpu */ | ||||
|     mtc0        a1,CP0_DDATA_LO | ||||
| 
 | ||||
|     /* Offset into vcpu->arch */ | ||||
| 	addiu		k1, a1, VCPU_HOST_ARCH | ||||
| 
 | ||||
|     /* Save the host stack to VCPU, used for exception processing when we exit from the Guest */ | ||||
|     LONG_S      sp, VCPU_HOST_STACK(k1) | ||||
| 
 | ||||
|     /* Save the kernel gp as well */ | ||||
|     LONG_S      gp, VCPU_HOST_GP(k1) | ||||
| 
 | ||||
| 	/* Setup status register for running the guest in UM, interrupts are disabled */ | ||||
| 	li			k0,(ST0_EXL | KSU_USER| ST0_BEV) | ||||
| 	mtc0		k0,CP0_STATUS | ||||
|     ehb | ||||
| 
 | ||||
|     /* load up the new EBASE */ | ||||
|     LONG_L      k0, VCPU_GUEST_EBASE(k1) | ||||
|     mtc0        k0,CP0_EBASE | ||||
| 
 | ||||
|     /* Now that the new EBASE has been loaded, unset BEV, set interrupt mask as it was | ||||
|      * but make sure that timer interrupts are enabled | ||||
|      */ | ||||
|     li          k0,(ST0_EXL | KSU_USER | ST0_IE) | ||||
|     andi        v0, v0, ST0_IM | ||||
|     or          k0, k0, v0 | ||||
|     mtc0        k0,CP0_STATUS | ||||
|     ehb | ||||
| 
 | ||||
| 
 | ||||
| 	/* Set Guest EPC */ | ||||
| 	LONG_L		t0, VCPU_PC(k1) | ||||
| 	mtc0		t0, CP0_EPC | ||||
| 
 | ||||
| FEXPORT(__kvm_mips_load_asid) | ||||
|     /* Set the ASID for the Guest Kernel */ | ||||
|     sll         t0, t0, 1                       /* with kseg0 @ 0x40000000, kernel */
 | ||||
|                                                 /* addresses shift to 0x80000000 */ | ||||
|     bltz        t0, 1f                          /* If kernel */ | ||||
| 	addiu       t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */ | ||||
|     addiu       t1, k1, VCPU_GUEST_USER_ASID    /* else user */ | ||||
| 1: | ||||
|     /* t1: contains the base of the ASID array, need to get the cpu id  */ | ||||
|     LONG_L      t2, TI_CPU($28)             /* smp_processor_id */ | ||||
|     sll         t2, t2, 2                   /* x4 */ | ||||
|     addu        t3, t1, t2 | ||||
|     LONG_L      k0, (t3) | ||||
|     andi        k0, k0, 0xff | ||||
| 	mtc0		k0,CP0_ENTRYHI | ||||
|     ehb | ||||
| 
 | ||||
|     /* Disable RDHWR access */ | ||||
|     mtc0    zero,  CP0_HWRENA | ||||
| 
 | ||||
|     /* Now load up the Guest Context from VCPU */ | ||||
|     LONG_L     	$1, VCPU_R1(k1) | ||||
|     LONG_L     	$2, VCPU_R2(k1) | ||||
|     LONG_L     	$3, VCPU_R3(k1) | ||||
| 
 | ||||
|     LONG_L     	$4, VCPU_R4(k1) | ||||
|     LONG_L     	$5, VCPU_R5(k1) | ||||
|     LONG_L     	$6, VCPU_R6(k1) | ||||
|     LONG_L     	$7, VCPU_R7(k1) | ||||
| 
 | ||||
|     LONG_L     	$8,  VCPU_R8(k1) | ||||
|     LONG_L     	$9,  VCPU_R9(k1) | ||||
|     LONG_L     	$10, VCPU_R10(k1) | ||||
|     LONG_L     	$11, VCPU_R11(k1) | ||||
|     LONG_L     	$12, VCPU_R12(k1) | ||||
|     LONG_L     	$13, VCPU_R13(k1) | ||||
|     LONG_L     	$14, VCPU_R14(k1) | ||||
|     LONG_L     	$15, VCPU_R15(k1) | ||||
|     LONG_L     	$16, VCPU_R16(k1) | ||||
|     LONG_L     	$17, VCPU_R17(k1) | ||||
|     LONG_L     	$18, VCPU_R18(k1) | ||||
|     LONG_L     	$19, VCPU_R19(k1) | ||||
|     LONG_L     	$20, VCPU_R20(k1) | ||||
|     LONG_L     	$21, VCPU_R21(k1) | ||||
|     LONG_L     	$22, VCPU_R22(k1) | ||||
|     LONG_L     	$23, VCPU_R23(k1) | ||||
|     LONG_L     	$24, VCPU_R24(k1) | ||||
|     LONG_L     	$25, VCPU_R25(k1) | ||||
| 
 | ||||
|     /* k0/k1 loaded up later */ | ||||
| 
 | ||||
|     LONG_L     	$28, VCPU_R28(k1) | ||||
|     LONG_L     	$29, VCPU_R29(k1) | ||||
|     LONG_L     	$30, VCPU_R30(k1) | ||||
|     LONG_L     	$31, VCPU_R31(k1) | ||||
| 
 | ||||
|     /* Restore hi/lo */ | ||||
| 	LONG_L		k0, VCPU_LO(k1) | ||||
| 	mtlo		k0 | ||||
| 
 | ||||
| 	LONG_L		k0, VCPU_HI(k1) | ||||
| 	mthi   		k0 | ||||
| 
 | ||||
| FEXPORT(__kvm_mips_load_k0k1) | ||||
| 	/* Restore the guest's k0/k1 registers */ | ||||
|     LONG_L     	k0, VCPU_R26(k1) | ||||
|     LONG_L     	k1, VCPU_R27(k1) | ||||
| 
 | ||||
|     /* Jump to guest */ | ||||
| 	eret | ||||
| 	.set	pop
 | ||||
| 
 | ||||
| VECTOR(MIPSX(exception), unknown) | ||||
| /* | ||||
|  * Find out what mode we came from and jump to the proper handler. | ||||
|  */ | ||||
|     .set    push
 | ||||
| 	.set	noat
 | ||||
|     .set    noreorder
 | ||||
|     mtc0    k0, CP0_ERROREPC    #01: Save guest k0 | ||||
|     ehb                         #02: | ||||
| 
 | ||||
|     mfc0    k0, CP0_EBASE       #02: Get EBASE | ||||
|     srl     k0, k0, 10          #03: Get rid of CPUNum | ||||
|     sll     k0, k0, 10          #04 | ||||
|     LONG_S  k1, 0x3000(k0)      #05: Save k1 @ offset 0x3000
 | ||||
|     addiu   k0, k0, 0x2000      #06: Exception handler is installed @ offset 0x2000
 | ||||
| 	j	k0				        #07: jump to the function | ||||
| 	nop				        	#08: branch delay slot | ||||
| 	.set	push
 | ||||
| VECTOR_END(MIPSX(exceptionEnd)) | ||||
| .end MIPSX(exception) | ||||
| 
 | ||||
| /* | ||||
|  * Generic Guest exception handler. We end up here when the guest | ||||
|  * does something that causes a trap to kernel mode. | ||||
|  * | ||||
|  */ | ||||
| NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra) | ||||
|     .set    push
 | ||||
|     .set    noat
 | ||||
|     .set    noreorder
 | ||||
| 
 | ||||
|     /* Get the VCPU pointer from DDTATA_LO */ | ||||
|     mfc0        k1, CP0_DDATA_LO | ||||
| 	addiu		k1, k1, VCPU_HOST_ARCH | ||||
| 
 | ||||
|     /* Start saving Guest context to VCPU */ | ||||
|     LONG_S  $0, VCPU_R0(k1) | ||||
|     LONG_S  $1, VCPU_R1(k1) | ||||
|     LONG_S  $2, VCPU_R2(k1) | ||||
|     LONG_S  $3, VCPU_R3(k1) | ||||
|     LONG_S  $4, VCPU_R4(k1) | ||||
|     LONG_S  $5, VCPU_R5(k1) | ||||
|     LONG_S  $6, VCPU_R6(k1) | ||||
|     LONG_S  $7, VCPU_R7(k1) | ||||
|     LONG_S  $8, VCPU_R8(k1) | ||||
|     LONG_S  $9, VCPU_R9(k1) | ||||
|     LONG_S  $10, VCPU_R10(k1) | ||||
|     LONG_S  $11, VCPU_R11(k1) | ||||
|     LONG_S  $12, VCPU_R12(k1) | ||||
|     LONG_S  $13, VCPU_R13(k1) | ||||
|     LONG_S  $14, VCPU_R14(k1) | ||||
|     LONG_S  $15, VCPU_R15(k1) | ||||
|     LONG_S  $16, VCPU_R16(k1) | ||||
|     LONG_S  $17,VCPU_R17(k1) | ||||
|     LONG_S  $18, VCPU_R18(k1) | ||||
|     LONG_S  $19, VCPU_R19(k1) | ||||
|     LONG_S  $20, VCPU_R20(k1) | ||||
|     LONG_S  $21, VCPU_R21(k1) | ||||
|     LONG_S  $22, VCPU_R22(k1) | ||||
|     LONG_S  $23, VCPU_R23(k1) | ||||
|     LONG_S  $24, VCPU_R24(k1) | ||||
|     LONG_S  $25, VCPU_R25(k1) | ||||
| 
 | ||||
|     /* Guest k0/k1 saved later */ | ||||
| 
 | ||||
|     LONG_S  $28, VCPU_R28(k1) | ||||
|     LONG_S  $29, VCPU_R29(k1) | ||||
|     LONG_S  $30, VCPU_R30(k1) | ||||
|     LONG_S  $31, VCPU_R31(k1) | ||||
| 
 | ||||
|     /* We need to save hi/lo and restore them on | ||||
|      * the way out | ||||
|      */ | ||||
|     mfhi    t0 | ||||
|     LONG_S  t0, VCPU_HI(k1) | ||||
| 
 | ||||
|     mflo    t0 | ||||
|     LONG_S  t0, VCPU_LO(k1) | ||||
| 
 | ||||
|     /* Finally save guest k0/k1 to VCPU */ | ||||
|     mfc0    t0, CP0_ERROREPC | ||||
|     LONG_S  t0, VCPU_R26(k1) | ||||
| 
 | ||||
|     /* Get GUEST k1 and save it in VCPU */ | ||||
|     la      t1, ~0x2ff | ||||
|     mfc0    t0, CP0_EBASE | ||||
|     and     t0, t0, t1 | ||||
|     LONG_L  t0, 0x3000(t0) | ||||
|     LONG_S  t0, VCPU_R27(k1) | ||||
| 
 | ||||
|     /* Now that context has been saved, we can use other registers */ | ||||
| 
 | ||||
|     /* Restore vcpu */ | ||||
|     mfc0        a1, CP0_DDATA_LO | ||||
|     move        s1, a1 | ||||
| 
 | ||||
|    /* Restore run (vcpu->run) */ | ||||
|     LONG_L      a0, VCPU_RUN(a1) | ||||
|     /* Save pointer to run in s0, will be saved by the compiler */ | ||||
|     move        s0, a0 | ||||
| 
 | ||||
| 
 | ||||
|     /* Save Host level EPC, BadVaddr and Cause to VCPU, useful to process the exception */ | ||||
|     mfc0    k0,CP0_EPC | ||||
|     LONG_S  k0, VCPU_PC(k1) | ||||
| 
 | ||||
|     mfc0    k0, CP0_BADVADDR | ||||
|     LONG_S  k0, VCPU_HOST_CP0_BADVADDR(k1) | ||||
| 
 | ||||
|     mfc0    k0, CP0_CAUSE | ||||
|     LONG_S  k0, VCPU_HOST_CP0_CAUSE(k1) | ||||
| 
 | ||||
|     mfc0    k0, CP0_ENTRYHI | ||||
|     LONG_S  k0, VCPU_HOST_ENTRYHI(k1) | ||||
| 
 | ||||
|     /* Now restore the host state just enough to run the handlers */ | ||||
| 
 | ||||
|     /* Swtich EBASE to the one used by Linux */ | ||||
|     /* load up the host EBASE */ | ||||
|     mfc0        v0, CP0_STATUS | ||||
| 
 | ||||
|     .set at
 | ||||
| 	or          k0, v0, ST0_BEV | ||||
|     .set noat
 | ||||
| 
 | ||||
|     mtc0        k0, CP0_STATUS | ||||
|     ehb | ||||
| 
 | ||||
|     LONG_L      k0, VCPU_HOST_EBASE(k1) | ||||
|     mtc0        k0,CP0_EBASE | ||||
| 
 | ||||
| 
 | ||||
|     /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */ | ||||
|     .set at
 | ||||
| 	and         v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE) | ||||
|     or          v0, v0, ST0_CU0 | ||||
|     .set noat
 | ||||
|     mtc0        v0, CP0_STATUS | ||||
|     ehb | ||||
| 
 | ||||
|     /* Load up host GP */ | ||||
|     LONG_L  gp, VCPU_HOST_GP(k1) | ||||
| 
 | ||||
|     /* Need a stack before we can jump to "C" */ | ||||
|     LONG_L  sp, VCPU_HOST_STACK(k1) | ||||
| 
 | ||||
|     /* Saved host state */ | ||||
|     addiu   sp,sp, -PT_SIZE | ||||
| 
 | ||||
|     /* XXXKYMA do we need to load the host ASID, maybe not because the | ||||
|      * kernel entries are marked GLOBAL, need to verify | ||||
|      */ | ||||
| 
 | ||||
|     /* Restore host DDATA_LO */ | ||||
|     LONG_L      k0, PT_HOST_USERLOCAL(sp) | ||||
|     mtc0        k0, CP0_DDATA_LO | ||||
| 
 | ||||
|     /* Restore RDHWR access */ | ||||
|     la      k0, 0x2000000F | ||||
|     mtc0    k0,  CP0_HWRENA | ||||
| 
 | ||||
|     /* Jump to handler */ | ||||
| FEXPORT(__kvm_mips_jump_to_handler) | ||||
|     /* XXXKYMA: not sure if this is safe, how large is the stack?? */ | ||||
|     /* Now jump to the kvm_mips_handle_exit() to see if we can deal with this in the kernel */ | ||||
|     la          t9,kvm_mips_handle_exit | ||||
|     jalr.hb     t9 | ||||
|     addiu       sp,sp, -CALLFRAME_SIZ           /* BD Slot */ | ||||
| 
 | ||||
|     /* Return from handler Make sure interrupts are disabled */ | ||||
|     di | ||||
|     ehb | ||||
| 
 | ||||
|     /* XXXKYMA: k0/k1 could have been blown away if we processed an exception | ||||
|      * while we were handling the exception from the guest, reload k1 | ||||
|      */ | ||||
|     move        k1, s1 | ||||
| 	addiu		k1, k1, VCPU_HOST_ARCH | ||||
| 
 | ||||
|     /* Check return value, should tell us if we are returning to the host (handle I/O etc) | ||||
|      * or resuming the guest | ||||
|      */ | ||||
|     andi        t0, v0, RESUME_HOST | ||||
|     bnez        t0, __kvm_mips_return_to_host | ||||
|     nop | ||||
| 
 | ||||
| __kvm_mips_return_to_guest: | ||||
|     /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */ | ||||
|     mtc0        s1, CP0_DDATA_LO | ||||
| 
 | ||||
|     /* Load up the Guest EBASE to minimize the window where BEV is set */ | ||||
|     LONG_L      t0, VCPU_GUEST_EBASE(k1) | ||||
| 
 | ||||
|     /* Switch EBASE back to the one used by KVM */ | ||||
|     mfc0        v1, CP0_STATUS | ||||
|     .set at
 | ||||
| 	or          k0, v1, ST0_BEV | ||||
|     .set noat
 | ||||
|     mtc0        k0, CP0_STATUS | ||||
|     ehb | ||||
|     mtc0        t0,CP0_EBASE | ||||
| 
 | ||||
|     /* Setup status register for running guest in UM */ | ||||
|     .set at
 | ||||
|     or     v1, v1, (ST0_EXL | KSU_USER | ST0_IE) | ||||
|     and     v1, v1, ~ST0_CU0 | ||||
|     .set noat
 | ||||
|     mtc0    v1, CP0_STATUS | ||||
|     ehb | ||||
| 
 | ||||
| 
 | ||||
| 	/* Set Guest EPC */ | ||||
| 	LONG_L		t0, VCPU_PC(k1) | ||||
| 	mtc0		t0, CP0_EPC | ||||
| 
 | ||||
|     /* Set the ASID for the Guest Kernel */ | ||||
|     sll         t0, t0, 1                       /* with kseg0 @ 0x40000000, kernel */
 | ||||
|                                                 /* addresses shift to 0x80000000 */ | ||||
|     bltz        t0, 1f                          /* If kernel */ | ||||
| 	addiu       t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */ | ||||
|     addiu       t1, k1, VCPU_GUEST_USER_ASID    /* else user */ | ||||
| 1: | ||||
|     /* t1: contains the base of the ASID array, need to get the cpu id  */ | ||||
|     LONG_L      t2, TI_CPU($28)             /* smp_processor_id */ | ||||
|     sll         t2, t2, 2                   /* x4 */ | ||||
|     addu        t3, t1, t2 | ||||
|     LONG_L      k0, (t3) | ||||
|     andi        k0, k0, 0xff | ||||
| 	mtc0		k0,CP0_ENTRYHI | ||||
|     ehb | ||||
| 
 | ||||
|     /* Disable RDHWR access */ | ||||
|     mtc0    zero,  CP0_HWRENA | ||||
| 
 | ||||
|     /* load the guest context from VCPU and return */ | ||||
|     LONG_L  $0, VCPU_R0(k1) | ||||
|     LONG_L  $1, VCPU_R1(k1) | ||||
|     LONG_L  $2, VCPU_R2(k1) | ||||
|     LONG_L  $3, VCPU_R3(k1) | ||||
|     LONG_L  $4, VCPU_R4(k1) | ||||
|     LONG_L  $5, VCPU_R5(k1) | ||||
|     LONG_L  $6, VCPU_R6(k1) | ||||
|     LONG_L  $7, VCPU_R7(k1) | ||||
|     LONG_L  $8, VCPU_R8(k1) | ||||
|     LONG_L  $9, VCPU_R9(k1) | ||||
|     LONG_L  $10, VCPU_R10(k1) | ||||
|     LONG_L  $11, VCPU_R11(k1) | ||||
|     LONG_L  $12, VCPU_R12(k1) | ||||
|     LONG_L  $13, VCPU_R13(k1) | ||||
|     LONG_L  $14, VCPU_R14(k1) | ||||
|     LONG_L  $15, VCPU_R15(k1) | ||||
|     LONG_L  $16, VCPU_R16(k1) | ||||
|     LONG_L  $17, VCPU_R17(k1) | ||||
|     LONG_L  $18, VCPU_R18(k1) | ||||
|     LONG_L  $19, VCPU_R19(k1) | ||||
|     LONG_L  $20, VCPU_R20(k1) | ||||
|     LONG_L  $21, VCPU_R21(k1) | ||||
|     LONG_L  $22, VCPU_R22(k1) | ||||
|     LONG_L  $23, VCPU_R23(k1) | ||||
|     LONG_L  $24, VCPU_R24(k1) | ||||
|     LONG_L  $25, VCPU_R25(k1) | ||||
| 
 | ||||
|     /* $/k1 loaded later */ | ||||
|     LONG_L  $28, VCPU_R28(k1) | ||||
|     LONG_L  $29, VCPU_R29(k1) | ||||
|     LONG_L  $30, VCPU_R30(k1) | ||||
|     LONG_L  $31, VCPU_R31(k1) | ||||
| 
 | ||||
| FEXPORT(__kvm_mips_skip_guest_restore) | ||||
|     LONG_L  k0, VCPU_HI(k1) | ||||
|     mthi    k0 | ||||
| 
 | ||||
|     LONG_L  k0, VCPU_LO(k1) | ||||
|     mtlo    k0 | ||||
| 
 | ||||
|     LONG_L  k0, VCPU_R26(k1) | ||||
|     LONG_L  k1, VCPU_R27(k1) | ||||
| 
 | ||||
|     eret | ||||
| 
 | ||||
| __kvm_mips_return_to_host: | ||||
|     /* EBASE is already pointing to Linux */ | ||||
|     LONG_L  k1, VCPU_HOST_STACK(k1) | ||||
| 	addiu  	k1,k1, -PT_SIZE | ||||
| 
 | ||||
|     /* Restore host DDATA_LO */ | ||||
|     LONG_L      k0, PT_HOST_USERLOCAL(k1) | ||||
|     mtc0        k0, CP0_DDATA_LO | ||||
| 
 | ||||
|     /* Restore host ASID */ | ||||
|     LONG_L      k0, PT_HOST_ASID(sp) | ||||
|     andi        k0, 0xff | ||||
|     mtc0        k0,CP0_ENTRYHI | ||||
|     ehb | ||||
| 
 | ||||
|     /* Load context saved on the host stack */ | ||||
|     LONG_L  $0, PT_R0(k1) | ||||
|     LONG_L  $1, PT_R1(k1) | ||||
| 
 | ||||
|     /* r2/v0 is the return code, shift it down by 2 (arithmetic) to recover the err code  */ | ||||
|     sra     k0, v0, 2 | ||||
|     move    $2, k0 | ||||
| 
 | ||||
|     LONG_L  $3, PT_R3(k1) | ||||
|     LONG_L  $4, PT_R4(k1) | ||||
|     LONG_L  $5, PT_R5(k1) | ||||
|     LONG_L  $6, PT_R6(k1) | ||||
|     LONG_L  $7, PT_R7(k1) | ||||
|     LONG_L  $8, PT_R8(k1) | ||||
|     LONG_L  $9, PT_R9(k1) | ||||
|     LONG_L  $10, PT_R10(k1) | ||||
|     LONG_L  $11, PT_R11(k1) | ||||
|     LONG_L  $12, PT_R12(k1) | ||||
|     LONG_L  $13, PT_R13(k1) | ||||
|     LONG_L  $14, PT_R14(k1) | ||||
|     LONG_L  $15, PT_R15(k1) | ||||
|     LONG_L  $16, PT_R16(k1) | ||||
|     LONG_L  $17, PT_R17(k1) | ||||
|     LONG_L  $18, PT_R18(k1) | ||||
|     LONG_L  $19, PT_R19(k1) | ||||
|     LONG_L  $20, PT_R20(k1) | ||||
|     LONG_L  $21, PT_R21(k1) | ||||
|     LONG_L  $22, PT_R22(k1) | ||||
|     LONG_L  $23, PT_R23(k1) | ||||
|     LONG_L  $24, PT_R24(k1) | ||||
|     LONG_L  $25, PT_R25(k1) | ||||
| 
 | ||||
|     /* Host k0/k1 were not saved */ | ||||
| 
 | ||||
|     LONG_L  $28, PT_R28(k1) | ||||
|     LONG_L  $29, PT_R29(k1) | ||||
|     LONG_L  $30, PT_R30(k1) | ||||
| 
 | ||||
|     LONG_L  k0, PT_HI(k1) | ||||
|     mthi    k0 | ||||
| 
 | ||||
|     LONG_L  k0, PT_LO(k1) | ||||
|     mtlo    k0 | ||||
| 
 | ||||
|     /* Restore RDHWR access */ | ||||
|     la      k0, 0x2000000F | ||||
|     mtc0    k0,  CP0_HWRENA | ||||
| 
 | ||||
| 
 | ||||
|     /* Restore RA, which is the address we will return to */ | ||||
|     LONG_L  ra, PT_R31(k1) | ||||
|     j       ra | ||||
|     nop | ||||
| 
 | ||||
|     .set    pop
 | ||||
| VECTOR_END(MIPSX(GuestExceptionEnd)) | ||||
| .end MIPSX(GuestException) | ||||
| 
 | ||||
| MIPSX(exceptions): | ||||
| 	#### | ||||
| 	##### The exception handlers. | ||||
| 	##### | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  0 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  1 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  2 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  3 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  4 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  5 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  6 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  7 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  8 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	#  9 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 10 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 11 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 12 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 13 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 14 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 15 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 16 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 17 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 18 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 19 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 20 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 21 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 22 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 23 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 24 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 25 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 26 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 27 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 28 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 29 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 30 | ||||
| 	.word _C_LABEL(MIPSX(GuestException))	# 31 | ||||
| 
 | ||||
| 
 | ||||
| /* This routine makes changes to the instruction stream effective to the hardware. | ||||
|  * It should be called after the instruction stream is written. | ||||
|  * On return, the new instructions are effective. | ||||
|  * Inputs: | ||||
|  * a0 = Start address of new instruction stream | ||||
|  * a1 = Size, in bytes, of new instruction stream | ||||
|  */ | ||||
| 
 | ||||
| #define HW_SYNCI_Step       $1 | ||||
| LEAF(MIPSX(SyncICache)) | ||||
|     .set    push
 | ||||
| 	.set	mips32r2
 | ||||
|     beq     a1, zero, 20f | ||||
|     nop | ||||
|     addu    a1, a0, a1 | ||||
|     rdhwr   v0, HW_SYNCI_Step | ||||
|     beq     v0, zero, 20f | ||||
|     nop | ||||
| 
 | ||||
| 10: | ||||
|     synci   0(a0) | ||||
|     addu    a0, a0, v0 | ||||
|     sltu    v1, a0, a1 | ||||
|     bne     v1, zero, 10b | ||||
|     nop | ||||
|     sync | ||||
| 20: | ||||
|     jr.hb   ra | ||||
|     nop | ||||
|     .set pop
 | ||||
| END(MIPSX(SyncICache)) | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user