Index: /trunk/include/VBox/vmm/vmapi.h
===================================================================
--- /trunk/include/VBox/vmm/vmapi.h	(revision 61642)
+++ /trunk/include/VBox/vmm/vmapi.h	(revision 61643)
@@ -437,4 +437,5 @@
 VMMR3DECL(int)          VMR3AtStateRegister(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser);
 VMMR3DECL(int)          VMR3AtStateDeregister(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser);
+VMMR3_INT_DECL(bool)    VMR3SetGuruMeditation(PVM pVM);
 VMMR3_INT_DECL(bool)    VMR3TeleportedAndNotFullyResumedYet(PVM pVM);
 VMMR3DECL(int)          VMR3AtErrorRegister(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser);
Index: /trunk/src/VBox/VMM/VMMR3/EM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 61642)
+++ /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 61643)
@@ -1695,4 +1695,6 @@
                 case VMSTATE_FATAL_ERROR:
                 case VMSTATE_FATAL_ERROR_LS:
+                case VMSTATE_GURU_MEDITATION:
+                case VMSTATE_GURU_MEDITATION_LS:
                     Log2(("emR3ForcedActions: %s -> VINF_EM_SUSPEND\n", VMGetStateName(enmState) ));
                     STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
@@ -2036,4 +2038,6 @@
                 case VMSTATE_FATAL_ERROR:
                 case VMSTATE_FATAL_ERROR_LS:
+                case VMSTATE_GURU_MEDITATION:
+                case VMSTATE_GURU_MEDITATION_LS:
                     Log2(("emR3ForcedActions: %s -> VINF_EM_SUSPEND\n", VMGetStateName(enmState) ));
                     STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
@@ -2655,4 +2659,5 @@
                             /* switch to guru meditation mode */
                             pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
+                            VMR3SetGuruMeditation(pVM); /* This notifies the other EMTs. */
                             VMMR3FatalDump(pVM, pVCpu, rc);
                         }
@@ -2672,4 +2677,5 @@
                 {
                     TMR3NotifySuspend(pVM, pVCpu);
+                    VMR3SetGuruMeditation(pVM); /* This notifies the other EMTs. */
                     VMMR3FatalDump(pVM, pVCpu, rc);
                     emR3Debug(pVM, pVCpu, rc);
@@ -2701,4 +2707,5 @@
         Log(("EMR3ExecuteVM: returns %Rrc because of longjmp / fatal error; (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
         TMR3NotifySuspend(pVM, pVCpu);
+        VMR3SetGuruMeditation(pVM); /* This notifies the other EMTs. */
         VMMR3FatalDump(pVM, pVCpu, rc);
         emR3Debug(pVM, pVCpu, rc);
Index: /trunk/src/VBox/VMM/VMMR3/VM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VM.cpp	(revision 61642)
+++ /trunk/src/VBox/VMM/VMMR3/VM.cpp	(revision 61643)
@@ -123,5 +123,5 @@
 static void                 vmR3DoAtState(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld);
 static int                  vmR3TrySetState(PVM pVM, const char *pszWho, unsigned cTransitions, ...);
-static void                 vmR3SetStateLocked(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld);
+static void                 vmR3SetStateLocked(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld, bool fSetRatherThanClearFF);
 static void                 vmR3SetState(PVM pVM, VMSTATE enmStateNew, VMSTATE enmStateOld);
 static int                  vmR3SetErrorU(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(6, 7);
@@ -1595,5 +1595,5 @@
         {
             case VMSTATE_RUNNING_LS:
-                vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDING_LS, VMSTATE_RUNNING_LS);
+                vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDING_LS, VMSTATE_RUNNING_LS, false /*fSetRatherThanClearFF*/);
                 rc = VINF_SUCCESS;
                 break;
@@ -1609,15 +1609,15 @@
 
             case VMSTATE_OFF_LS:
-                vmR3SetStateLocked(pVM, pUVM, VMSTATE_OFF, VMSTATE_OFF_LS);
+                vmR3SetStateLocked(pVM, pUVM, VMSTATE_OFF, VMSTATE_OFF_LS, false /*fSetRatherThanClearFF*/);
                 rc = VERR_SSM_LIVE_POWERED_OFF;
                 break;
 
             case VMSTATE_FATAL_ERROR_LS:
-                vmR3SetStateLocked(pVM, pUVM, VMSTATE_FATAL_ERROR, VMSTATE_FATAL_ERROR_LS);
+                vmR3SetStateLocked(pVM, pUVM, VMSTATE_FATAL_ERROR, VMSTATE_FATAL_ERROR_LS, false /*fSetRatherThanClearFF*/);
                 rc = VERR_SSM_LIVE_FATAL_ERROR;
                 break;
 
             case VMSTATE_GURU_MEDITATION_LS:
-                vmR3SetStateLocked(pVM, pUVM, VMSTATE_GURU_MEDITATION, VMSTATE_GURU_MEDITATION_LS);
+                vmR3SetStateLocked(pVM, pUVM, VMSTATE_GURU_MEDITATION, VMSTATE_GURU_MEDITATION_LS, false /*fSetRatherThanClearFF*/);
                 rc = VERR_SSM_LIVE_GURU_MEDITATION;
                 break;
@@ -2339,7 +2339,7 @@
         enmVMState = pVM->enmVMState;
         if (enmVMState == VMSTATE_POWERING_OFF_LS)
-            vmR3SetStateLocked(pVM, pUVM, VMSTATE_OFF_LS, VMSTATE_POWERING_OFF_LS);
+            vmR3SetStateLocked(pVM, pUVM, VMSTATE_OFF_LS, VMSTATE_POWERING_OFF_LS, false /*fSetRatherThanClearFF*/);
         else
-            vmR3SetStateLocked(pVM, pUVM, VMSTATE_OFF,    VMSTATE_POWERING_OFF);
+            vmR3SetStateLocked(pVM, pUVM, VMSTATE_OFF,    VMSTATE_POWERING_OFF, false /*fSetRatherThanClearFF*/);
         RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     }
@@ -2778,10 +2778,10 @@
         {
             if (pUVM->vm.s.enmPrevVMState == VMSTATE_SUSPENDED)
-                vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDED, VMSTATE_SOFT_RESETTING);
+                vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDED, VMSTATE_SOFT_RESETTING, false /*fSetRatherThanClearFF*/);
             else
-                vmR3SetStateLocked(pVM, pUVM, VMSTATE_RUNNING,   VMSTATE_SOFT_RESETTING);
+                vmR3SetStateLocked(pVM, pUVM, VMSTATE_RUNNING,   VMSTATE_SOFT_RESETTING, false /*fSetRatherThanClearFF*/);
         }
         else
-            vmR3SetStateLocked(pVM, pUVM, VMSTATE_RUNNING_LS, VMSTATE_SOFT_RESETTING_LS);
+            vmR3SetStateLocked(pVM, pUVM, VMSTATE_RUNNING_LS, VMSTATE_SOFT_RESETTING_LS, false /*fSetRatherThanClearFF*/);
         RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     }
@@ -2895,10 +2895,10 @@
         {
             if (pUVM->vm.s.enmPrevVMState == VMSTATE_SUSPENDED)
-                vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDED, VMSTATE_RESETTING);
+                vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDED, VMSTATE_RESETTING, false /*fSetRatherThanClearFF*/);
             else
-                vmR3SetStateLocked(pVM, pUVM, VMSTATE_RUNNING,   VMSTATE_RESETTING);
+                vmR3SetStateLocked(pVM, pUVM, VMSTATE_RUNNING,   VMSTATE_RESETTING, false /*fSetRatherThanClearFF*/);
         }
         else
-            vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDING_LS, VMSTATE_RESETTING_LS);
+            vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDING_LS, VMSTATE_RESETTING_LS, false /*fSetRatherThanClearFF*/);
         RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
 
@@ -3486,10 +3486,14 @@
  * Sets the current VM state, with the AtStatCritSect already entered.
  *
- * @param   pVM                 The cross context VM structure.
- * @param   pUVM                The UVM handle.
- * @param   enmStateNew         The new state.
- * @param   enmStateOld         The old state.
- */
-static void vmR3SetStateLocked(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld)
+ * @param   pVM                     The cross context VM structure.
+ * @param   pUVM                    The UVM handle.
+ * @param   enmStateNew             The new state.
+ * @param   enmStateOld             The old state.
+ * @param   fSetRatherThanClearFF   The usual behavior is to clear the
+ *                                  VM_FF_CHECK_VM_STATE force flag, but for
+ *                                  some transitions (-> guru) we need to kick
+ *                                  the other EMTs to stop what they're doing.
+ */
+static void vmR3SetStateLocked(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld, bool fSetRatherThanClearFF)
 {
     vmR3ValidateStateTransition(enmStateOld, enmStateNew);
@@ -3497,7 +3501,12 @@
     AssertMsg(pVM->enmVMState == enmStateOld,
               ("%s != %s\n", VMR3GetStateName(pVM->enmVMState), VMR3GetStateName(enmStateOld)));
+
     pUVM->vm.s.enmPrevVMState = enmStateOld;
     pVM->enmVMState           = enmStateNew;
-    VM_FF_CLEAR(pVM, VM_FF_CHECK_VM_STATE);
+
+    if (!fSetRatherThanClearFF)
+        VM_FF_CLEAR(pVM, VM_FF_CHECK_VM_STATE);
+    else if (pVM->cCpus > 0)
+        VM_FF_SET(pVM, VM_FF_CHECK_VM_STATE);
 
     vmR3DoAtState(pVM, pUVM, enmStateNew, enmStateOld);
@@ -3519,5 +3528,5 @@
     AssertMsg(pVM->enmVMState == enmStateOld,
               ("%s != %s\n", VMR3GetStateName(pVM->enmVMState), VMR3GetStateName(enmStateOld)));
-    vmR3SetStateLocked(pVM, pUVM, enmStateNew, pVM->enmVMState);
+    vmR3SetStateLocked(pVM, pUVM, enmStateNew, pVM->enmVMState, false /*fSetRatherThanClearFF*/);
 
     RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
@@ -3572,5 +3581,5 @@
         if (enmStateCur == enmStateOld)
         {
-            vmR3SetStateLocked(pVM, pUVM, enmStateNew, enmStateOld);
+            vmR3SetStateLocked(pVM, pUVM, enmStateNew, enmStateOld, false /*fSetRatherThanClearFF*/);
             rc = i + 1;
             break;
@@ -3622,12 +3631,12 @@
 
 /**
- * Flag a guru meditation ... a hack.
- *
+ * Interface used by EM to signal that it's entering the guru meditation state.
+ *
+ * This will notifying other threads.
+ *
+ * @returns true if the state changed to Guru, false if no state change.
  * @param   pVM             The cross context VM structure.
- *
- * @todo    Rewrite this part. The guru meditation should be flagged
- *          immediately by the VMM and not by VMEmt.cpp when it's all over.
- */
-void vmR3SetGuruMeditation(PVM pVM)
+ */
+VMMR3_INT_DECL(bool) VMR3SetGuruMeditation(PVM pVM)
 {
     PUVM pUVM = pVM->pUVM;
@@ -3635,13 +3644,17 @@
 
     VMSTATE enmStateCur = pVM->enmVMState;
+    bool fRc = true;
     if (enmStateCur == VMSTATE_RUNNING)
-        vmR3SetStateLocked(pVM, pUVM, VMSTATE_GURU_MEDITATION, VMSTATE_RUNNING);
+        vmR3SetStateLocked(pVM, pUVM, VMSTATE_GURU_MEDITATION, VMSTATE_RUNNING, true /*fSetRatherThanClearFF*/);
     else if (enmStateCur == VMSTATE_RUNNING_LS)
     {
-        vmR3SetStateLocked(pVM, pUVM, VMSTATE_GURU_MEDITATION_LS, VMSTATE_RUNNING_LS);
+        vmR3SetStateLocked(pVM, pUVM, VMSTATE_GURU_MEDITATION_LS, VMSTATE_RUNNING_LS, true /*fSetRatherThanClearFF*/);
         SSMR3Cancel(pUVM);
     }
+    else
+        fRc = false;
 
     RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
+    return fRc;
 }
 
Index: /trunk/src/VBox/VMM/VMMR3/VMEmt.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VMEmt.cpp	(revision 61642)
+++ /trunk/src/VBox/VMM/VMMR3/VMEmt.cpp	(revision 61643)
@@ -237,6 +237,4 @@
                 rc = EMR3ExecuteVM(pVM, pVCpu);
                 Log(("vmR3EmulationThread: EMR3ExecuteVM() -> rc=%Rrc, enmVMState=%d\n", rc, pVM->enmVMState));
-                if (EMGetState(pVCpu) == EMSTATE_GURU_MEDITATION)
-                    vmR3SetGuruMeditation(pVM);
             }
         }
Index: /trunk/src/VBox/VMM/include/VMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/VMInternal.h	(revision 61642)
+++ /trunk/src/VBox/VMM/include/VMInternal.h	(revision 61643)
@@ -457,5 +457,4 @@
 DECLCALLBACK(int)   vmR3SetRuntimeErrorV(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list *pVa);
 void                vmSetRuntimeErrorCopy(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va);
-void                vmR3SetGuruMeditation(PVM pVM);
 void                vmR3SetTerminated(PVM pVM);
 
