diff options
Diffstat (limited to 'arch/powerpc/kvm/book3s_interrupts.S')
| -rw-r--r-- | arch/powerpc/kvm/book3s_interrupts.S | 68 | 
1 files changed, 57 insertions, 11 deletions
diff --git a/arch/powerpc/kvm/book3s_interrupts.S b/arch/powerpc/kvm/book3s_interrupts.S index 17cfae5497a..d044b8b7c69 100644 --- a/arch/powerpc/kvm/book3s_interrupts.S +++ b/arch/powerpc/kvm/book3s_interrupts.S @@ -25,9 +25,17 @@  #include <asm/exception-64s.h>  #if defined(CONFIG_PPC_BOOK3S_64) +#if defined(_CALL_ELF) && _CALL_ELF == 2 +#define FUNC(name) 		name +#else  #define FUNC(name) 		GLUE(.,name) +#endif +#define GET_SHADOW_VCPU(reg)    addi	reg, r13, PACA_SVCPU +  #elif defined(CONFIG_PPC_BOOK3S_32)  #define FUNC(name)		name +#define GET_SHADOW_VCPU(reg)	lwz     reg, (THREAD + THREAD_KVM_SVCPU)(r2) +  #endif /* CONFIG_PPC_BOOK3S_XX */  #define VCPU_LOAD_NVGPRS(vcpu) \ @@ -87,15 +95,40 @@ kvm_start_entry:  	VCPU_LOAD_NVGPRS(r4)  kvm_start_lightweight: +	/* Copy registers into shadow vcpu so we can access them in real mode */ +	GET_SHADOW_VCPU(r3) +	bl	FUNC(kvmppc_copy_to_svcpu) +	nop +	REST_GPR(4, r1)  #ifdef CONFIG_PPC_BOOK3S_64 +	/* Get the dcbz32 flag */  	PPC_LL	r3, VCPU_HFLAGS(r4)  	rldicl	r3, r3, 0, 63		/* r3 &= 1 */  	stb	r3, HSTATE_RESTORE_HID5(r13)  	/* Load up guest SPRG3 value, since it's user readable */ -	ld	r3, VCPU_SHARED(r4) -	ld	r3, VCPU_SHARED_SPRG3(r3) +	lwz	r3, VCPU_SHAREDBE(r4) +	cmpwi	r3, 0 +	ld	r5, VCPU_SHARED(r4) +	beq	sprg3_little_endian +sprg3_big_endian: +#ifdef __BIG_ENDIAN__ +	ld	r3, VCPU_SHARED_SPRG3(r5) +#else +	addi	r5, r5, VCPU_SHARED_SPRG3 +	ldbrx	r3, 0, r5 +#endif +	b	after_sprg3_load +sprg3_little_endian: +#ifdef __LITTLE_ENDIAN__ +	ld	r3, VCPU_SHARED_SPRG3(r5) +#else +	addi	r5, r5, VCPU_SHARED_SPRG3 +	ldbrx	r3, 0, r5 +#endif + +after_sprg3_load:  	mtspr	SPRN_SPRG3, r3  #endif /* CONFIG_PPC_BOOK3S_64 */ @@ -111,9 +144,6 @@ kvm_start_lightweight:   *   */ -.global kvmppc_handler_highmem -kvmppc_handler_highmem: -  	/*  	 * Register usage at this point:  	 * @@ -122,21 +152,37 @@ kvmppc_handler_highmem:  	 * R12      = exit handler id  	 * R13      = PACA  	 * SVCPU.*  = guest * +	 * MSR.EE   = 1  	 *  	 */ -	/* R7 = vcpu */ -	PPC_LL	r7, GPR4(r1) +	PPC_LL	r3, GPR4(r1)		/* vcpu pointer */ + +	/* +	 * kvmppc_copy_from_svcpu can clobber volatile registers, save +	 * the exit handler id to the vcpu and restore it from there later. +	 */ +	stw	r12, VCPU_TRAP(r3) + +	/* Transfer reg values from shadow vcpu back to vcpu struct */ +	/* On 64-bit, interrupts are still off at this point */ + +	GET_SHADOW_VCPU(r4) +	bl	FUNC(kvmppc_copy_from_svcpu) +	nop  #ifdef CONFIG_PPC_BOOK3S_64  	/*  	 * Reload kernel SPRG3 value.  	 * No need to save guest value as usermode can't modify SPRG3.  	 */ -	ld	r3, PACA_SPRG3(r13) -	mtspr	SPRN_SPRG3, r3 +	ld	r3, PACA_SPRG_VDSO(r13) +	mtspr	SPRN_SPRG_VDSO_WRITE, r3  #endif /* CONFIG_PPC_BOOK3S_64 */ +	/* R7 = vcpu */ +	PPC_LL	r7, GPR4(r1) +  	PPC_STL	r14, VCPU_GPR(R14)(r7)  	PPC_STL	r15, VCPU_GPR(R15)(r7)  	PPC_STL	r16, VCPU_GPR(R16)(r7) @@ -157,11 +203,11 @@ kvmppc_handler_highmem:  	PPC_STL	r31, VCPU_GPR(R31)(r7)  	/* Pass the exit number as 3rd argument to kvmppc_handle_exit */ -	mr	r5, r12 +	lwz	r5, VCPU_TRAP(r7)  	/* Restore r3 (kvm_run) and r4 (vcpu) */  	REST_2GPRS(3, r1) -	bl	FUNC(kvmppc_handle_exit) +	bl	FUNC(kvmppc_handle_exit_pr)  	/* If RESUME_GUEST, get back in the loop */  	cmpwi	r3, RESUME_GUEST  | 
