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

KVM: PPC: Book3S PR: Add emulation for trechkpt.



This patch adds host emulation when guest PR KVM executes "trechkpt.",
which is a privileged instruction and will trap into host.

We firstly copy vcpu ongoing content into vcpu tm checkpoint
content, then perform kvmppc_restore_tm_pr() to do trechkpt.
with updated vcpu tm checkpoint values.

Signed-off-by: default avatarSimon Guo <wei.guo.simon@gmail.com>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parent 03c81682
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -262,10 +262,12 @@ extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu);
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu);
void kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu);
void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu);
void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu);
#else
static inline void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu) {}
static inline void kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu) {}
static inline void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu) {}
static inline void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu) {}
#endif

+61 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@
#define OP_31_XOP_TBEGIN	654

#define OP_31_XOP_TRECLAIM	942
#define OP_31_XOP_TRCHKPT	1006

/* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */
#define OP_31_XOP_DCBZ		1010
@@ -172,6 +173,29 @@ static void kvmppc_emulate_treclaim(struct kvm_vcpu *vcpu, int ra_val)
	kvmppc_set_msr(vcpu, guest_msr);
	preempt_enable();
}

static void kvmppc_emulate_trchkpt(struct kvm_vcpu *vcpu)
{
	unsigned long guest_msr = kvmppc_get_msr(vcpu);

	preempt_disable();
	/*
	 * need flush FP/VEC/VSX to vcpu save area before
	 * copy.
	 */
	kvmppc_giveup_ext(vcpu, MSR_VSX);
	kvmppc_copyto_vcpu_tm(vcpu);
	kvmppc_save_tm_sprs(vcpu);

	/*
	 * as a result of trecheckpoint. set TS to suspended.
	 */
	guest_msr &= ~(MSR_TS_MASK);
	guest_msr |= MSR_TS_S;
	kvmppc_set_msr(vcpu, guest_msr);
	kvmppc_restore_tm_pr(vcpu);
	preempt_enable();
}
#endif

int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
@@ -478,6 +502,43 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
			kvmppc_emulate_treclaim(vcpu, ra_val);
			break;
		}
		case OP_31_XOP_TRCHKPT:
		{
			ulong guest_msr = kvmppc_get_msr(vcpu);
			unsigned long texasr;

			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;
			}

			/* generate interrupt based on priorities */
			if (guest_msr & MSR_PR) {
				/* Privileged Instruction type Program Intr */
				kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV);
				emulated = EMULATE_AGAIN;
				break;
			}

			tm_enable();
			texasr = mfspr(SPRN_TEXASR);
			tm_disable();

			if (MSR_TM_ACTIVE(guest_msr) ||
				!(texasr & (TEXASR_FS))) {
				/* TM bad thing interrupt */
				kvmppc_core_queue_program(vcpu, SRR1_PROGTM);
				emulated = EMULATE_AGAIN;
				break;
			}

			kvmppc_emulate_trchkpt(vcpu);
			break;
		}
#endif
		default:
			emulated = EMULATE_FAIL;
+1 −1
Original line number Diff line number Diff line
@@ -299,7 +299,7 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu)
}

#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
static inline void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu)
void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu)
{
	tm_enable();
	vcpu->arch.tfhar = mfspr(SPRN_TFHAR);