Index: /trunk/include/VBox/vmm/em.h
===================================================================
--- /trunk/include/VBox/vmm/em.h	(revision 65791)
+++ /trunk/include/VBox/vmm/em.h	(revision 65792)
@@ -200,4 +200,5 @@
 VMM_INT_DECL(int)               EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx, RTGCPHYS GCPhys);
 VMM_INT_DECL(int)               EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx);
+VMM_INT_DECL(int)               EMUnhaltAndWakeUp(PVM pVM, PVMCPU pVCpuDst);
 
 /** @name Assembly routines
Index: /trunk/include/VBox/vmm/vm.h
===================================================================
--- /trunk/include/VBox/vmm/vm.h	(revision 65791)
+++ /trunk/include/VBox/vmm/vm.h	(revision 65792)
@@ -410,5 +410,5 @@
 /** PDM critical section unlocking is pending, process promptly upon return to R3. */
 #define VMCPU_FF_PDM_CRITSECT               RT_BIT_32(5)
-/** This action forces the VCPU out of the halted state. */
+/** This action forces the VCPU out of the halted state, see EMUnhaltAndWakeUp. */
 #define VMCPU_FF_UNHALT                     RT_BIT_32(6)
 /** Pending IEM action (bit number). */
Index: /trunk/src/VBox/VMM/VMMAll/EMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 65791)
+++ /trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 65792)
@@ -259,4 +259,50 @@
         return !!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_UPDATE_APIC | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC));
     return false;
+}
+
+
+/**
+ * Unhalts and wakes up the given CPU.
+ *
+ * This is an API for assisting the KVM hypercall API in implementing KICK_CPU.
+ * It sets VMCPU_FF_UNHALT for @a pVCpuDst and makes sure it is woken up.   If
+ * the CPU isn't currently in a halt, the next HLT instruction it executes will
+ * be affected.
+ *
+ * @returns GVMMR0SchedWakeUpEx result or VINF_SUCCESS depending on context.
+ * @param   pVM             The cross context VM structure.
+ * @param   pVCpuDst        The cross context virtual CPU structure of the
+ *                          CPU to unhalt and wake up.  This is usually not the
+ *                          same as the caller.
+ * @thread  EMT
+ */
+VMM_INT_DECL(int) EMUnhaltAndWakeUp(PVM pVM, PVMCPU pVCpuDst)
+{
+    /*
+     * Flag the current(/next) HLT to unhalt immediately.
+     */
+    VMCPU_FF_SET(pVCpuDst, VMCPU_FF_UNHALT);
+
+    /*
+     * Wake up the EMT (technically should be abstracted by VMM/VMEmt, but
+     * just do it here for now).
+     */
+#ifdef IN_RING0
+    /* We might be here with preemption disabled or enabled (i.e. depending on
+       thread-context hooks being used), so don't try obtaining the GVMMR0 used
+       lock here. See @bugref{7270#c148}. */
+    int rc = GVMMR0SchedWakeUpEx(pVM, pVCpuDst->idCpu, false /* fTakeUsedLock */);
+    AssertRC(rc);
+
+#elif defined(IN_RING3)
+    int rc = SUPR3CallVMMR0(pVM->pVMR0, pVCpuDst->idCpu, VMMR0_DO_GVMM_SCHED_WAKE_UP, NULL /* pvArg */);
+    AssertRC(rc);
+
+#else
+    /* Nothing to do for raw-mode, shouldn't really be used by raw-mode guests anyway. */
+    Assert(pVM->cCpus == 1); NOREF(pVM);
+    int rc = VINF_SUCCESS;
+#endif
+    return rc;
 }
 
Index: /trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp	(revision 65791)
+++ /trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp	(revision 65792)
@@ -103,19 +103,6 @@
             if (uHyperArg1 < pVM->cCpus)
             {
-                PVMCPU pVCpuTarget = &pVM->aCpus[uHyperArg1];   /** ASSUMES pVCpu index == ApicId of the VCPU. */
-                VMCPU_FF_SET(pVCpuTarget, VMCPU_FF_UNHALT);
-#ifdef IN_RING0
-                /*
-                 * We might be here with preemption disabled or enabled (i.e. depending on thread-context hooks
-                 * being used), so don't try obtaining the GVMMR0 used lock here. See @bugref{7270#c148}.
-                 */
-                GVMMR0SchedWakeUpEx(pVM, pVCpuTarget->idCpu, false /* fTakeUsedLock */);
-#elif defined(IN_RING3)
-                int rc2 = SUPR3CallVMMR0(pVM->pVMR0, pVCpuTarget->idCpu, VMMR0_DO_GVMM_SCHED_WAKE_UP, NULL /* pvArg */);
-                AssertRC(rc2);
-#elif defined(IN_RC)
-                /* Nothing to do for raw-mode, shouldn't really be used by raw-mode guests anyway. */
-                Assert(pVM->cCpus == 1);
-#endif
+                PVMCPU pVCpuDst = &pVM->aCpus[uHyperArg1];   /* ASSUMES pVCpu index == ApicId of the VCPU. */
+                EMUnhaltAndWakeUp(pVM, pVCpuDst);
                 uHyperRet = KVM_HYPERCALL_RET_SUCCESS;
             }
