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: Simon Guo <wei.guo.simon@gmail.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
03c81682a9
commit
e32c53d1cf
3 changed files with 64 additions and 1 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -299,7 +299,7 @@ out:
|
|||
}
|
||||
|
||||
#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);
|
||||
|
|
Loading…
Reference in a new issue