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