Commit 1c3ab876 authored by Paul Mackerras's avatar Paul Mackerras Committed by Greg Kroah-Hartman

KVM: PPC: Book3S HV: Reload HTM registers explicitly

Commit 46a704f8 ("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 46a704f8 has been backported to the 3.18 stable tree
as commit 0b423dab, 3.18.59 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 46a704f8 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: 0b423dab ("KVM: PPC: Book3S HV: Preserve userspace HTM state properly")
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 901aae4f
...@@ -1974,10 +1974,11 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) ...@@ -1974,10 +1974,11 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
run->fail_entry.hardware_entry_failure_reason = 0; run->fail_entry.hardware_entry_failure_reason = 0;
return -EINVAL; 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_tfhar = mfspr(SPRN_TFHAR);
current->thread.tm_tfiar = mfspr(SPRN_TFIAR); current->thread.tm_tfiar = mfspr(SPRN_TFIAR);
current->thread.tm_texasr = mfspr(SPRN_TEXASR); current->thread.tm_texasr = mfspr(SPRN_TEXASR);
current->thread.regs->msr &= ~MSR_TM;
} }
#endif #endif
...@@ -2043,6 +2044,19 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) ...@@ -2043,6 +2044,19 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
} }
mtspr(SPRN_VRSAVE, user_vrsave); mtspr(SPRN_VRSAVE, user_vrsave);
/*
* Since we don't do lazy TM reload, we need to reload
* the TM registers here.
*/
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
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);
}
#endif
out: out:
vcpu->arch.state = KVMPPC_VCPU_NOTREADY; vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
atomic_dec(&vcpu->kvm->arch.vcpus_running); atomic_dec(&vcpu->kvm->arch.vcpus_running);
......
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