--- /dev/null
+From 4c3bb4ccd074e1a0552078c0bf94c662367a1658 Mon Sep 17 00:00:00 2001
+From: Paul Mackerras <paulus@ozlabs.org>
+Date: Thu, 15 Jun 2017 15:43:17 +1000
+Subject: KVM: PPC: Book3S HV: Restore critical SPRs to host values on guest exit
+
+From: Paul Mackerras <paulus@ozlabs.org>
+
+commit 4c3bb4ccd074e1a0552078c0bf94c662367a1658 upstream.
+
+This restores several special-purpose registers (SPRs) to sane values
+on guest exit that were missed before.
+
+TAR and VRSAVE are readable and writable by userspace, and we need to
+save and restore them to prevent the guest from potentially affecting
+userspace execution (not that TAR or VRSAVE are used by any known
+program that run uses the KVM_RUN ioctl). We save/restore these
+in kvmppc_vcpu_run_hv() rather than on every guest entry/exit.
+
+FSCR affects userspace execution in that it can prohibit access to
+certain facilities by userspace. We restore it to the normal value
+for the task on exit from the KVM_RUN ioctl.
+
+IAMR is normally 0, and is restored to 0 on guest exit. However,
+with a radix host on POWER9, it is set to a value that prevents the
+kernel from executing user-accessible memory. On POWER9, we save
+IAMR on guest entry and restore it on guest exit to the saved value
+rather than 0. On POWER8 we continue to set it to 0 on guest exit.
+
+PSPB is normally 0. We restore it to 0 on guest exit to prevent
+userspace taking advantage of the guest having set it non-zero
+(which would allow userspace to set its SMT priority to high).
+
+UAMOR is normally 0. We restore it to 0 on guest exit to prevent
+the AMR from being used as a covert channel between userspace
+processes, since the AMR is not context-switched at present.
+
+[paulus@ozlabs.org - removed IAMR bits that are only needed on POWER9]
+
+Fixes: b005255e12a3 ("KVM: PPC: Book3S HV: Context-switch new POWER8 SPRs", 2014-01-08)
+Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kvm/book3s_hv.c | 11 +++++++++--
+ arch/powerpc/kvm/book3s_hv_rmhandlers.S | 2 ++
+ 2 files changed, 11 insertions(+), 2 deletions(-)
+
+--- a/arch/powerpc/kvm/book3s_hv.c
++++ b/arch/powerpc/kvm/book3s_hv.c
+@@ -2808,6 +2808,8 @@ static int kvmppc_vcpu_run_hv(struct kvm
+ int r;
+ int srcu_idx;
+ unsigned long ebb_regs[3] = {}; /* shut up GCC */
++ unsigned long user_tar = 0;
++ unsigned int user_vrsave;
+
+ if (!vcpu->arch.sane) {
+ run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+@@ -2858,12 +2860,14 @@ static int kvmppc_vcpu_run_hv(struct kvm
+
+ flush_all_to_thread(current);
+
+- /* Save userspace EBB register values */
++ /* Save userspace EBB and other register values */
+ if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
+ ebb_regs[0] = mfspr(SPRN_EBBHR);
+ ebb_regs[1] = mfspr(SPRN_EBBRR);
+ ebb_regs[2] = mfspr(SPRN_BESCR);
++ user_tar = mfspr(SPRN_TAR);
+ }
++ user_vrsave = mfspr(SPRN_VRSAVE);
+
+ vcpu->arch.wqp = &vcpu->arch.vcore->wq;
+ vcpu->arch.pgdir = current->mm->pgd;
+@@ -2887,12 +2891,15 @@ static int kvmppc_vcpu_run_hv(struct kvm
+ r = kvmppc_xics_rm_complete(vcpu, 0);
+ } while (is_kvmppc_resume_guest(r));
+
+- /* Restore userspace EBB register values */
++ /* Restore userspace EBB and other register values */
+ if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
+ mtspr(SPRN_EBBHR, ebb_regs[0]);
+ mtspr(SPRN_EBBRR, ebb_regs[1]);
+ mtspr(SPRN_BESCR, ebb_regs[2]);
++ mtspr(SPRN_TAR, user_tar);
++ mtspr(SPRN_FSCR, current->thread.fscr);
+ }
++ mtspr(SPRN_VRSAVE, user_vrsave);
+
+ out:
+ vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
+--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
++++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+@@ -1363,6 +1363,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
+ mtspr SPRN_IAMR, r0
+ mtspr SPRN_CIABR, r0
+ mtspr SPRN_DAWRX, r0
++ mtspr SPRN_PSPB, r0
+ mtspr SPRN_TCSCR, r0
+ mtspr SPRN_WORT, r0
+ /* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */
+@@ -1378,6 +1379,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
+ std r6,VCPU_UAMOR(r9)
+ li r6,0
+ mtspr SPRN_AMR,r6
++ mtspr SPRN_UAMOR, r6
+
+ /* Switch DSCR back to host value */
+ mfspr r8, SPRN_DSCR