forked from mirrors/linux
		
	KVM: PPC: Book3S PR: Add emulation for tabort. in privileged state
Currently privileged-state guest will be run with TM disabled. Although the privileged-state guest cannot initiate a new transaction, it can use tabort to terminate its problem state's transaction. So it is still necessary to emulate tabort. for privileged-state guest. Tested with: https://github.com/justdoitqd/publicFiles/blob/master/test_tabort.c Signed-off-by: Simon Guo <wei.guo.simon@gmail.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
		
							parent
							
								
									e32c53d1cf
								
							
						
					
					
						commit
						26798f88d5
					
				
					 1 changed files with 68 additions and 0 deletions
				
			
		|  | @ -50,6 +50,7 @@ | |||
| #define OP_31_XOP_SLBMFEE	915 | ||||
| 
 | ||||
| #define OP_31_XOP_TBEGIN	654 | ||||
| #define OP_31_XOP_TABORT	910 | ||||
| 
 | ||||
| #define OP_31_XOP_TRECLAIM	942 | ||||
| #define OP_31_XOP_TRCHKPT	1006 | ||||
|  | @ -196,6 +197,47 @@ static void kvmppc_emulate_trchkpt(struct kvm_vcpu *vcpu) | |||
| 	kvmppc_restore_tm_pr(vcpu); | ||||
| 	preempt_enable(); | ||||
| } | ||||
| 
 | ||||
| /* emulate tabort. at guest privilege state */ | ||||
| static void kvmppc_emulate_tabort(struct kvm_vcpu *vcpu, int ra_val) | ||||
| { | ||||
| 	/* currently we only emulate tabort. but no emulation of other
 | ||||
| 	 * tabort variants since there is no kernel usage of them at | ||||
| 	 * present. | ||||
| 	 */ | ||||
| 	unsigned long guest_msr = kvmppc_get_msr(vcpu); | ||||
| 
 | ||||
| 	preempt_disable(); | ||||
| 	tm_enable(); | ||||
| 	tm_abort(ra_val); | ||||
| 
 | ||||
| 	/* CR0 = 0 | MSR[TS] | 0 */ | ||||
| 	vcpu->arch.cr = (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)) | | ||||
| 		(((guest_msr & MSR_TS_MASK) >> (MSR_TS_S_LG - 1)) | ||||
| 		 << CR0_SHIFT); | ||||
| 
 | ||||
| 	vcpu->arch.texasr = mfspr(SPRN_TEXASR); | ||||
| 	/* failure recording depends on Failure Summary bit,
 | ||||
| 	 * and tabort will be treated as nops in non-transactional | ||||
| 	 * state. | ||||
| 	 */ | ||||
| 	if (!(vcpu->arch.texasr & TEXASR_FS) && | ||||
| 			MSR_TM_ACTIVE(guest_msr)) { | ||||
| 		vcpu->arch.texasr &= ~(TEXASR_PR | TEXASR_HV); | ||||
| 		if (guest_msr & MSR_PR) | ||||
| 			vcpu->arch.texasr |= TEXASR_PR; | ||||
| 
 | ||||
| 		if (guest_msr & MSR_HV) | ||||
| 			vcpu->arch.texasr |= TEXASR_HV; | ||||
| 
 | ||||
| 		vcpu->arch.tfiar = kvmppc_get_pc(vcpu); | ||||
| 		mtspr(SPRN_TEXASR, vcpu->arch.texasr); | ||||
| 		mtspr(SPRN_TFIAR, vcpu->arch.tfiar); | ||||
| 	} | ||||
| 	tm_disable(); | ||||
| 	preempt_enable(); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||||
|  | @ -468,6 +510,32 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
| 				emulated = EMULATE_FAIL; | ||||
| 			break; | ||||
| 		} | ||||
| 		case OP_31_XOP_TABORT: | ||||
| 		{ | ||||
| 			ulong guest_msr = kvmppc_get_msr(vcpu); | ||||
| 			unsigned long ra_val = 0; | ||||
| 
 | ||||
| 			if (!cpu_has_feature(CPU_FTR_TM)) | ||||
| 				break; | ||||
| 
 | ||||
| 			if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { | ||||
| 				kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); | ||||
| 				emulated = EMULATE_AGAIN; | ||||
| 				break; | ||||
| 			} | ||||
| 
 | ||||
| 			/* only emulate for privilege guest, since problem state
 | ||||
| 			 * guest can run with TM enabled and we don't expect to | ||||
| 			 * trap at here for that case. | ||||
| 			 */ | ||||
| 			WARN_ON(guest_msr & MSR_PR); | ||||
| 
 | ||||
| 			if (ra) | ||||
| 				ra_val = kvmppc_get_gpr(vcpu, ra); | ||||
| 
 | ||||
| 			kvmppc_emulate_tabort(vcpu, ra_val); | ||||
| 			break; | ||||
| 		} | ||||
| 		case OP_31_XOP_TRECLAIM: | ||||
| 		{ | ||||
| 			ulong guest_msr = kvmppc_get_msr(vcpu); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Simon Guo
						Simon Guo