Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26798f88 authored by Simon Guo's avatar Simon Guo Committed by Paul Mackerras
Browse files

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: default avatarSimon Guo <wei.guo.simon@gmail.com>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parent e32c53d1
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -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);