diff options
author | Simon Guo <wei.guo.simon@gmail.com> | 2018-05-23 09:02:04 +0200 |
---|---|---|
committer | Paul Mackerras <paulus@ozlabs.org> | 2018-06-01 02:30:23 +0200 |
commit | e32c53d1cf0022af180548474f4c29c189d37d93 (patch) | |
tree | 63d9d8940dbb32f5ae175d3f96e091c45e6ab600 /arch/powerpc/kvm | |
parent | KVM: PPC: Book3S PR: Add emulation for treclaim. (diff) | |
download | linux-e32c53d1cf0022af180548474f4c29c189d37d93.tar.xz linux-e32c53d1cf0022af180548474f4c29c189d37d93.zip |
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>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r-- | arch/powerpc/kvm/book3s_emulate.c | 61 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 2 |
2 files changed, 62 insertions, 1 deletions
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c index 04c29e01b391..b7530cf58834 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c @@ -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; diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index bb9209947db9..a275f8b3a4a0 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -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); |