summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@ozlabs.org>2018-06-07 11:06:21 +0300
committerPaul Mackerras <paulus@ozlabs.org>2018-06-13 02:45:28 +0300
commita50623fb57002207b9b2636e1d3bd5cf17a3e74f (patch)
treeb1b4b959bc8f66300d0636ba0ff6f753e6a1f7d4 /arch
parent916ccadccdcd8a0b7184dce37066a9fb2f9b4195 (diff)
downloadlinux-a50623fb57002207b9b2636e1d3bd5cf17a3e74f.tar.xz
KVM: PPC: Book3S PR: Fix failure status setting in treclaim. emulation
The treclaim. emulation needs to record failure status in the TEXASR register if the transaction had not previously failed. However, the current code first does kvmppc_save_tm_pr() (which does a treclaim. itself) and then checks the failure summary bit in TEXASR after that. Since treclaim. itself causes transaction failure, the FS bit is always set, so we were never updating TEXASR with the failure cause supplied by the guest as the RA parameter to the treclaim. instruction. This caused the tm-unavailable test in tools/testing/selftests/powerpc/tm to fail. To fix this, we need to read TEXASR before calling kvmppc_save_tm_pr(), and base the final value of TEXASR on that value. Fixes: 03c81682a90b ("KVM: PPC: Book3S PR: Add emulation for treclaim.") Reviewed-by: Simon Guo <wei.guo.simon@gmail.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kvm/book3s_emulate.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index fdbc695038dc..05cac5ea79c5 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -138,6 +138,7 @@ static void kvmppc_emulate_treclaim(struct kvm_vcpu *vcpu, int ra_val)
{
unsigned long guest_msr = kvmppc_get_msr(vcpu);
int fc_val = ra_val ? ra_val : 1;
+ uint64_t texasr;
/* CR0 = 0 | MSR[TS] | 0 */
vcpu->arch.cr = (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)) |
@@ -145,25 +146,26 @@ static void kvmppc_emulate_treclaim(struct kvm_vcpu *vcpu, int ra_val)
<< CR0_SHIFT);
preempt_disable();
+ tm_enable();
+ texasr = mfspr(SPRN_TEXASR);
kvmppc_save_tm_pr(vcpu);
kvmppc_copyfrom_vcpu_tm(vcpu);
- tm_enable();
- vcpu->arch.texasr = mfspr(SPRN_TEXASR);
/* failure recording depends on Failure Summary bit */
- if (!(vcpu->arch.texasr & TEXASR_FS)) {
- vcpu->arch.texasr &= ~TEXASR_FC;
- vcpu->arch.texasr |= ((u64)fc_val << TEXASR_FC_LG);
+ if (!(texasr & TEXASR_FS)) {
+ texasr &= ~TEXASR_FC;
+ texasr |= ((u64)fc_val << TEXASR_FC_LG) | TEXASR_FS;
- vcpu->arch.texasr &= ~(TEXASR_PR | TEXASR_HV);
+ texasr &= ~(TEXASR_PR | TEXASR_HV);
if (kvmppc_get_msr(vcpu) & MSR_PR)
- vcpu->arch.texasr |= TEXASR_PR;
+ texasr |= TEXASR_PR;
if (kvmppc_get_msr(vcpu) & MSR_HV)
- vcpu->arch.texasr |= TEXASR_HV;
+ texasr |= TEXASR_HV;
+ vcpu->arch.texasr = texasr;
vcpu->arch.tfiar = kvmppc_get_pc(vcpu);
- mtspr(SPRN_TEXASR, vcpu->arch.texasr);
+ mtspr(SPRN_TEXASR, texasr);
mtspr(SPRN_TFIAR, vcpu->arch.tfiar);
}
tm_disable();