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

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
...@@ -262,10 +262,12 @@ extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu); ...@@ -262,10 +262,12 @@ extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu);
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu); void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu);
void kvmppc_restore_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); void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu);
#else #else
static inline void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu) {} 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_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) {} static inline void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu) {}
#endif #endif
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#define OP_31_XOP_TBEGIN 654 #define OP_31_XOP_TBEGIN 654
#define OP_31_XOP_TRECLAIM 942 #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 */ /* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */
#define OP_31_XOP_DCBZ 1010 #define OP_31_XOP_DCBZ 1010
...@@ -172,6 +173,29 @@ static void kvmppc_emulate_treclaim(struct kvm_vcpu *vcpu, int ra_val) ...@@ -172,6 +173,29 @@ static void kvmppc_emulate_treclaim(struct kvm_vcpu *vcpu, int ra_val)
kvmppc_set_msr(vcpu, guest_msr); kvmppc_set_msr(vcpu, guest_msr);
preempt_enable(); 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 #endif
int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, 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, ...@@ -478,6 +502,43 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_emulate_treclaim(vcpu, ra_val); kvmppc_emulate_treclaim(vcpu, ra_val);
break; 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 #endif
default: default:
emulated = EMULATE_FAIL; emulated = EMULATE_FAIL;
......
...@@ -299,7 +299,7 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu) ...@@ -299,7 +299,7 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu)
} }
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM #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(); tm_enable();
vcpu->arch.tfhar = mfspr(SPRN_TFHAR); vcpu->arch.tfhar = mfspr(SPRN_TFHAR);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment