{
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
-       local_paca->kvm_hstate.kvm_vcpu = vcpu;
-       local_paca->kvm_hstate.kvm_vcore = vc;
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
                vc->stolen_tb += mftb() - vc->preempt_tb;
 }
 
        /* Ensure the thread won't go into the kernel if it wakes */
        tpaca->kvm_hstate.hwthread_req = 1;
+       tpaca->kvm_hstate.kvm_vcpu = NULL;
 
        /*
         * If the thread is already executing in the kernel (e.g. handling
        smp_wmb();
 #if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
        if (vcpu->arch.ptid) {
-               kvmppc_grab_hwthread(cpu);
                xics_wake_cpu(cpu);
                ++vc->n_woken;
        }
 
 /*
  * Check that we are on thread 0 and that any other threads in
- * this core are off-line.
+ * this core are off-line.  Then grab the threads so they can't
+ * enter the kernel.
  */
 static int on_primary_thread(void)
 {
        while (++thr < threads_per_core)
                if (cpu_online(cpu + thr))
                        return 0;
+
+       /* Grab all hw threads so they can't go into the kernel */
+       for (thr = 1; thr < threads_per_core; ++thr) {
+               if (kvmppc_grab_hwthread(cpu + thr)) {
+                       /* Couldn't grab one; let the others go */
+                       do {
+                               kvmppc_release_hwthread(cpu + thr);
+                       } while (--thr > 0);
+                       return 0;
+               }
+       }
        return 1;
 }
 
                spin_lock(&vc->lock);
        }
 
-       /*
-        * Make sure we are running on thread 0, and that
-        * secondary threads are offline.
-        */
-       if (threads_per_core > 1 && !on_primary_thread()) {
-               list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
-                       vcpu->arch.ret = -EBUSY;
-               goto out;
-       }
-
        /*
         * Assign physical thread IDs, first to non-ceded vcpus
         * and then to ceded ones.
                if (vcpu->arch.ceded)
                        vcpu->arch.ptid = ptid++;
 
+       /*
+        * Make sure we are running on thread 0, and that
+        * secondary threads are offline.
+        */
+       if (threads_per_core > 1 && !on_primary_thread()) {
+               list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+                       vcpu->arch.ret = -EBUSY;
+               goto out;
+       }
+
        vc->stolen_tb += mftb() - vc->preempt_tb;
        vc->pcpu = smp_processor_id();
        list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
                kvmppc_start_thread(vcpu);
                kvmppc_create_dtl_entry(vcpu, vc);
        }
-       /* Grab any remaining hw threads so they can't go into the kernel */
-       for (i = ptid; i < threads_per_core; ++i)
-               kvmppc_grab_hwthread(vc->pcpu + i);
 
        preempt_disable();
        spin_unlock(&vc->lock);
 
 
 27:    /* XXX should handle hypervisor maintenance interrupts etc. here */
 
+       /* reload vcpu pointer after clearing the IPI */
+       ld      r4,HSTATE_KVM_VCPU(r13)
+       cmpdi   r4,0
        /* if we have no vcpu to run, go back to sleep */
-       beq     cr1,kvm_no_guest
+       beq     kvm_no_guest
 
        /* were we napping due to cede? */
        lbz     r0,HSTATE_NAPPING(r13)
        .endr
 
 secondary_nap:
+       /* Clear our vcpu pointer so we don't come back in early */
+       li      r0, 0
+       std     r0, HSTATE_KVM_VCPU(r13)
+       lwsync
        /* Clear any pending IPI - assume we're a secondary thread */
        ld      r5, HSTATE_XICS_PHYS(r13)
        li      r7, XICS_XIRR
 kvm_no_guest:
        li      r0, KVM_HWTHREAD_IN_NAP
        stb     r0, HSTATE_HWTHREAD_STATE(r13)
-       li      r0, 0
-       std     r0, HSTATE_KVM_VCPU(r13)
 
        li      r3, LPCR_PECE0
        mfspr   r4, SPRN_LPCR