KVM: PPC: Book3S HV: Don't push XIVE context when not using XIVE device
authorPaul Mackerras <paulus@ozlabs.org>
Tue, 13 Aug 2019 10:01:00 +0000 (20:01 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 16 Aug 2019 04:16:08 +0000 (14:16 +1000)
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
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_xive.c
arch/powerpc/kvm/book3s_xive_native.c

index 2e7e788eb0cfc557b35d505e3ea896654008c669..07181d0dfcb79a0b582d1e8b3af2569955969d0f 100644 (file)
@@ -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? */
index 09f838aa31385174f1cdffe1bae5f233a4f4aeec..586867e46e51d1db41560144000441e9ee20496a 100644 (file)
@@ -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];
index 368427fcad205bf7870b3f55c623392c2bf9d8c9..11b91b46fc394efd3b23199a9aab2057111dc41f 100644 (file)
@@ -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);