| From f80ea4281342a64d36806360928d8f5e7d388d60 Mon Sep 17 00:00:00 2001 |
| From: Paul Mackerras <paulus@ozlabs.org> |
| Date: Tue, 13 Aug 2019 20:01:00 +1000 |
| Subject: [PATCH] KVM: PPC: Book3S HV: Don't push XIVE context when not using |
| XIVE device |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| commit 8d4ba9c931bc384bcc6889a43915aaaf19d3e499 upstream. |
| |
| At present, when running a guest on POWER9 using HV KVM but not using |
| an in-kernel interrupt controller (XICS or XIVE), for example if QEMU |
| is run with the kernel_irqchip=off option, the guest entry code goes |
| ahead and tries to load the guest context into the XIVE hardware, even |
| though no context has been set up. |
| |
| To fix this, we check that the "CAM word" is non-zero before pushing |
| it to the hardware. The CAM word is initialized to a non-zero value |
| in kvmppc_xive_connect_vcpu() and kvmppc_xive_native_connect_vcpu(), |
| and is now cleared in kvmppc_xive_{,native_}cleanup_vcpu. |
| |
| Fixes: 5af50993850a ("KVM: PPC: Book3S HV: Native usage of the XIVE interrupt controller") |
| Cc: stable@vger.kernel.org # v4.12+ |
| Reported-by: Cédric Le Goater <clg@kaod.org> |
| Signed-off-by: Paul Mackerras <paulus@ozlabs.org> |
| Reviewed-by: Cédric Le Goater <clg@kaod.org> |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Link: https://lore.kernel.org/r/20190813100100.GC9567@blackberry |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S |
| index 337e64468d78..44e226dcae89 100644 |
| --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S |
| +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S |
| @@ -942,6 +942,8 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300) |
| ld r11, VCPU_XIVE_SAVED_STATE(r4) |
| li r9, TM_QW1_OS |
| lwz r8, VCPU_XIVE_CAM_WORD(r4) |
| + cmpwi r8, 0 |
| + beq no_xive |
| li r7, TM_QW1_OS + TM_WORD2 |
| mfmsr r0 |
| andi. r0, r0, MSR_DR /* in real mode? */ |
| diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c |
| index 09f838aa3138..586867e46e51 100644 |
| --- a/arch/powerpc/kvm/book3s_xive.c |
| +++ b/arch/powerpc/kvm/book3s_xive.c |
| @@ -67,8 +67,14 @@ void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu) |
| void __iomem *tima = local_paca->kvm_hstate.xive_tima_virt; |
| u64 pq; |
| |
| - if (!tima) |
| + /* |
| + * Nothing to do if the platform doesn't have a XIVE |
| + * or this vCPU doesn't have its own XIVE context |
| + * (e.g. because it's not using an in-kernel interrupt controller). |
| + */ |
| + if (!tima || !vcpu->arch.xive_cam_word) |
| return; |
| + |
| eieio(); |
| __raw_writeq(vcpu->arch.xive_saved_state.w01, tima + TM_QW1_OS); |
| __raw_writel(vcpu->arch.xive_cam_word, tima + TM_QW1_OS + TM_WORD2); |
| @@ -1146,6 +1152,9 @@ void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu) |
| /* Disable the VP */ |
| xive_native_disable_vp(xc->vp_id); |
| |
| + /* Clear the cam word so guest entry won't try to push context */ |
| + vcpu->arch.xive_cam_word = 0; |
| + |
| /* Free the queues */ |
| for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { |
| struct xive_q *q = &xc->queues[i]; |
| diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c |
| index 1f34ec8f82d1..5d7523292ddd 100644 |
| --- a/arch/powerpc/kvm/book3s_xive_native.c |
| +++ b/arch/powerpc/kvm/book3s_xive_native.c |
| @@ -81,6 +81,9 @@ void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu) |
| /* Disable the VP */ |
| xive_native_disable_vp(xc->vp_id); |
| |
| + /* Clear the cam word so guest entry won't try to push context */ |
| + vcpu->arch.xive_cam_word = 0; |
| + |
| /* Free the queues */ |
| for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { |
| kvmppc_xive_native_cleanup_queue(vcpu, i); |
| -- |
| 2.7.4 |
| |