path: root/arch
diff options
authorPaul Mackerras <paulus@ozlabs.org>2017-07-31 10:43:37 +1000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-08-06 19:19:39 -0700
commit17d381054b1d6f4adc3db623b2066fff41b4dc1a (patch)
tree3e4af9183e251f55a8bcabcc31286b2bcb18fe41 /arch
parentf5b29db247d4b16a165903a1b29a0a5dbc9aa41c (diff)
KVM: PPC: Book3S HV: Reload HTM registers explicitly
Commit 46a704f8409f ("KVM: PPC: Book3S HV: Preserve userspace HTM state properly", 2017-06-15) added code which assumes that the kernel is able to handle a TM (transactional memory) unavailable interrupt from userspace by reloading the TM-related registers and enabling TM for the process. That ability was added in the 4.9 kernel; earlier kernel versions simply panic on getting the TM unavailable interrupt. Since commit 46a704f8409f has been backported to the 4.4 stable tree as commit 824b9506e4f2, 4.4.75 and subsequent versions are vulnerable to a userspace-triggerable panic. This patch fixes the problem by explicitly reloading the TM-related registers before returning to userspace, rather than disabling TM for the process. Commit 46a704f8409f also failed to enable TM for the kernel, leading to a TM unavailable interrupt in the kernel, causing an oops. This fixes that problem too, by enabling TM before accessing the TM registers. That problem is fixed upstream by the patch "KVM: PPC: Book3S HV: Enable TM before accessing TM registers". Fixes: 824b9506e4f2 ("KVM: PPC: Book3S HV: Preserve userspace HTM state properly") Signed-off-by: Paul Mackerras <paulus@ozlabs.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch')
1 files changed, 15 insertions, 1 deletions
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index b5eeaa1824df..428563b195c3 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -2711,10 +2711,11 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
run->fail_entry.hardware_entry_failure_reason = 0;
return -EINVAL;
+ /* Enable TM so we can read the TM SPRs */
+ mtmsr(mfmsr() | MSR_TM);
current->thread.tm_tfhar = mfspr(SPRN_TFHAR);
current->thread.tm_tfiar = mfspr(SPRN_TFIAR);
current->thread.tm_texasr = mfspr(SPRN_TEXASR);
- current->thread.regs->msr &= ~MSR_TM;
@@ -2782,6 +2783,19 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
mtspr(SPRN_VRSAVE, user_vrsave);
+ /*
+ * Since we don't do lazy TM reload, we need to reload
+ * the TM registers here.
+ */
+ if (cpu_has_feature(CPU_FTR_TM) && current->thread.regs &&
+ (current->thread.regs->msr & MSR_TM)) {
+ mtspr(SPRN_TFHAR, current->thread.tm_tfhar);
+ mtspr(SPRN_TFIAR, current->thread.tm_tfiar);
+ mtspr(SPRN_TEXASR, current->thread.tm_texasr);
+ }
vcpu->arch.state = KVMPPC_VCPU_NOTREADY;