]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - arch/powerpc/kvm/book3s_xive.c
KVM: PPC: Book3S HV: Don't push XIVE context when not using XIVE device
[linux.git] / arch / powerpc / kvm / book3s_xive.c
index 6ca0d7376a9f8ec1e2aa72aa8f2744e61c9732cb..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);
@@ -1134,20 +1140,25 @@ void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu)
        /* Mask the VP IPI */
        xive_vm_esb_load(&xc->vp_ipi_data, XIVE_ESB_SET_PQ_01);
 
-       /* Disable the VP */
-       xive_native_disable_vp(xc->vp_id);
-
-       /* Free the queues & associated interrupts */
+       /* Free escalations */
        for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
-               struct xive_q *q = &xc->queues[i];
-
-               /* Free the escalation irq */
                if (xc->esc_virq[i]) {
                        free_irq(xc->esc_virq[i], vcpu);
                        irq_dispose_mapping(xc->esc_virq[i]);
                        kfree(xc->esc_virq_names[i]);
                }
-               /* Free the queue */
+       }
+
+       /* 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];
+
                xive_native_disable_queue(xc->vp_id, q, i);
                if (q->qpage) {
                        free_pages((unsigned long)q->qpage,
@@ -1986,10 +1997,8 @@ static int kvmppc_xive_create(struct kvm_device *dev, u32 type)
 
        xive->single_escalation = xive_native_has_single_escalation();
 
-       if (ret) {
-               kfree(xive);
+       if (ret)
                return ret;
-       }
 
        return 0;
 }