Index: /trunk/Config.kmk
===================================================================
--- /trunk/Config.kmk	(revision 46787)
+++ /trunk/Config.kmk	(revision 46788)
@@ -1643,5 +1643,5 @@
  LIB_DDU         = $(PATH_STAGE_LIB)/VBoxDDU.lib
 endif
-if1of ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH), win.amd64)
+if1of ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH), win.amd64 linux.amd64)
  VBOX_LIB_VMM_LAZY      = $(PATH_STAGE_LIB)/VMMR3LazyImp$(VBOX_SUFF_LIB)
 else
Index: /trunk/include/VBox/vmm/pdmdev.h
===================================================================
--- /trunk/include/VBox/vmm/pdmdev.h	(revision 46787)
+++ /trunk/include/VBox/vmm/pdmdev.h	(revision 46788)
@@ -3441,4 +3441,23 @@
     DECLR3CALLBACKMEMBER(int, pfnCallR0,(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg));
 
+    /**
+     * Gets the reason for the most recent VM suspend.
+     *
+     * @returns The suspend reason. VMSUSPENDREASON_INVALID is returned if no
+     *          suspend has been made or if the pDevIns is invalid.
+     * @param   pDevIns             The device instance.
+     */
+    DECLR3CALLBACKMEMBER(VMSUSPENDREASON, pfnVMGetSuspendReason,(PPDMDEVINS pDevIns));
+
+    /**
+     * Gets the reason for the most recent VM resume.
+     *
+     * @returns The resume reason. VMRESUMEREASON_INVALID is returned if no
+     *          resume has been made or if the pDevIns is invalid.
+     * @param   pDevIns             The device instance.
+     */
+    DECLR3CALLBACKMEMBER(VMRESUMEREASON, pfnVMGetResumeReason,(PPDMDEVINS pDevIns));
+
+
     /** Space reserved for future members.
      * @{ */
@@ -3450,6 +3469,6 @@
     DECLR3CALLBACKMEMBER(void, pfnReserved6,(void));
     DECLR3CALLBACKMEMBER(void, pfnReserved7,(void));
-    DECLR3CALLBACKMEMBER(void, pfnReserved8,(void));
-    DECLR3CALLBACKMEMBER(void, pfnReserved9,(void));
+    /*DECLR3CALLBACKMEMBER(void, pfnReserved8,(void));
+    DECLR3CALLBACKMEMBER(void, pfnReserved9,(void));*/
     /*DECLR3CALLBACKMEMBER(void, pfnReserved10,(void));*/
     /** @} */
@@ -3627,5 +3646,5 @@
 
 /** Current PDMDEVHLPR3 version number. */
-#define PDM_DEVHLPR3_VERSION                    PDM_VERSION_MAKE(0xffe7, 12, 0)
+#define PDM_DEVHLPR3_VERSION                    PDM_VERSION_MAKE(0xffe7, 12, 1)
 
 
@@ -5084,4 +5103,20 @@
 
 /**
+ * @copydoc PDMDEVHLP::pfnVMGetSuspendReason
+ */
+DECLINLINE(VMSUSPENDREASON) PDMDevHlpVMGetSuspendReason(PPDMDEVINS pDevIns)
+{
+    return pDevIns->pHlpR3->pfnVMGetSuspendReason(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLP::pfnVMGetResumeReason
+ */
+DECLINLINE(VMRESUMEREASON) PDMDevHlpVMGetResumeReason(PPDMDEVINS pDevIns)
+{
+    return pDevIns->pHlpR3->pfnVMGetResumeReason(pDevIns);
+}
+
+/**
  * @copydoc PDMDEVHLPR3::pfnGetUVM
  */
Index: /trunk/include/VBox/vmm/pdmdrv.h
===================================================================
--- /trunk/include/VBox/vmm/pdmdrv.h	(revision 46787)
+++ /trunk/include/VBox/vmm/pdmdrv.h	(revision 46788)
@@ -1298,4 +1298,35 @@
                                                   PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
                                                   const char *pcszId));
+    /**
+     * Gets the reason for the most recent VM suspend.
+     *
+     * @returns The suspend reason. VMSUSPENDREASON_INVALID is returned if no
+     *          suspend has been made or if the pDrvIns is invalid.
+     * @param   pDrvIns             The driver instance.
+     */
+    DECLR3CALLBACKMEMBER(VMSUSPENDREASON, pfnVMGetSuspendReason,(PPDMDRVINS pDrvIns));
+
+    /**
+     * Gets the reason for the most recent VM resume.
+     *
+     * @returns The resume reason. VMRESUMEREASON_INVALID is returned if no
+     *          resume has been made or if the pDrvIns is invalid.
+     * @param   pDrvIns             The driver instance.
+     */
+    DECLR3CALLBACKMEMBER(VMRESUMEREASON, pfnVMGetResumeReason,(PPDMDRVINS pDrvIns));
+
+    /** @name Space reserved for minor interface changes.
+     * @{ */
+    DECLR3CALLBACKMEMBER(void, pfnReserved0,(PPDMDRVINS pDrvIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved1,(PPDMDRVINS pDrvIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved2,(PPDMDRVINS pDrvIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved3,(PPDMDRVINS pDrvIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved4,(PPDMDRVINS pDrvIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved5,(PPDMDRVINS pDrvIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved6,(PPDMDRVINS pDrvIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved7,(PPDMDRVINS pDrvIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved8,(PPDMDRVINS pDrvIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved9,(PPDMDRVINS pDrvIns));
+    /** @}  */
 
     /** Just a safety precaution. */
@@ -1303,5 +1334,5 @@
 } PDMDRVHLPR3;
 /** Current DRVHLP version number. */
-#define PDM_DRVHLPR3_VERSION                    PDM_VERSION_MAKE(0xf0fb, 2, 0)
+#define PDM_DRVHLPR3_VERSION                    PDM_VERSION_MAKE(0xf0fb, 3, 0)
 
 #endif /* IN_RING3 */
@@ -1778,4 +1809,21 @@
 }
 
+/**
+ * @copydoc PDMDRVHLP::pfnVMGetSuspendReason
+ */
+DECLINLINE(VMSUSPENDREASON) PDMDrvHlpVMGetSuspendReason(PPDMDRVINS pDrvIns)
+{
+    return pDrvIns->pHlpR3->pfnVMGetSuspendReason(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnVMGetResumeReason
+ */
+DECLINLINE(VMRESUMEREASON) PDMDrvHlpVMGetResumeReason(PPDMDRVINS pDrvIns)
+{
+    return pDrvIns->pHlpR3->pfnVMGetResumeReason(pDrvIns);
+}
+
+
 /** Pointer to callbacks provided to the VBoxDriverRegister() call. */
 typedef struct PDMDRVREGCB *PPDMDRVREGCB;
Index: /trunk/include/VBox/vmm/pdmusb.h
===================================================================
--- /trunk/include/VBox/vmm/pdmusb.h	(revision 46787)
+++ /trunk/include/VBox/vmm/pdmusb.h	(revision 46788)
@@ -678,4 +678,36 @@
     DECLR3CALLBACKMEMBER(void, pfnAsyncNotificationCompleted, (PPDMUSBINS pUsbIns));
 
+    /**
+     * Gets the reason for the most recent VM suspend.
+     *
+     * @returns The suspend reason. VMSUSPENDREASON_INVALID is returned if no
+     *          suspend has been made or if the pUsbIns is invalid.
+     * @param   pUsbIns             The driver instance.
+     */
+    DECLR3CALLBACKMEMBER(VMSUSPENDREASON, pfnVMGetSuspendReason,(PPDMUSBINS pUsbIns));
+
+    /**
+     * Gets the reason for the most recent VM resume.
+     *
+     * @returns The resume reason. VMRESUMEREASON_INVALID is returned if no
+     *          resume has been made or if the pUsbIns is invalid.
+     * @param   pUsbIns             The driver instance.
+     */
+    DECLR3CALLBACKMEMBER(VMRESUMEREASON, pfnVMGetResumeReason,(PPDMUSBINS pUsbIns));
+
+    /** @name Space reserved for minor interface changes.
+     * @{ */
+    DECLR3CALLBACKMEMBER(void, pfnReserved0,(PPDMUSBINS pUsbIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved1,(PPDMUSBINS pUsbIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved2,(PPDMUSBINS pUsbIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved3,(PPDMUSBINS pUsbIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved4,(PPDMUSBINS pUsbIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved5,(PPDMUSBINS pUsbIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved6,(PPDMUSBINS pUsbIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved7,(PPDMUSBINS pUsbIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved8,(PPDMUSBINS pUsbIns));
+    DECLR3CALLBACKMEMBER(void, pfnReserved9,(PPDMUSBINS pUsbIns));
+    /** @}  */
+
     /** Just a safety precaution. */
     uint32_t                        u32TheEnd;
@@ -687,5 +719,5 @@
 
 /** Current USBHLP version number. */
-#define PDM_USBHLP_VERSION                      PDM_VERSION_MAKE(0xeefe, 2, 0)
+#define PDM_USBHLP_VERSION                      PDM_VERSION_MAKE(0xeefe, 3, 0)
 
 #endif /* IN_RING3 */
Index: /trunk/include/VBox/vmm/vmapi.h
===================================================================
--- /trunk/include/VBox/vmm/vmapi.h	(revision 46787)
+++ /trunk/include/VBox/vmm/vmapi.h	(revision 46788)
@@ -332,4 +332,56 @@
 } VMINITCOMPLETED;
 
+
+/** Reason for VM resume. */
+typedef enum VMRESUMEREASON
+{
+    VMRESUMEREASON_INVALID = 0,
+    /** User decided to do so. */
+    VMRESUMEREASON_USER,
+    /** VM reconfiguration (like changing DVD). */
+    VMRESUMEREASON_RECONFIG,
+    /** The host resumed. */
+    VMRESUMEREASON_HOST_RESUME,
+    /** Restored state. */
+    VMRESUMEREASON_STATE_RESTORED,
+    /** Snapshot / saved state. */
+    VMRESUMEREASON_STATE_SAVED,
+    /** Teleported to a new box / instance. */
+    VMRESUMEREASON_TELEPORTED,
+    /** Teleportation failed. */
+    VMRESUMEREASON_TELEPORT_FAILED,
+    /** FTM temporarily suspended the VM. */
+    VMRESUMEREASON_FTM_SYNC,
+    /** End of valid reasons. */
+    VMRESUMEREASON_END,
+    /** Blow the type up to 32-bits. */
+    VMRESUMEREASON_32BIT_HACK = 0x7fffffff
+} VMRESUMEREASON;
+
+/** Reason for VM suspend. */
+typedef enum VMSUSPENDREASON
+{
+    VMSUSPENDREASON_INVALID = 0,
+    /** User decided to do so. */
+    VMSUSPENDREASON_USER,
+    /** VM reconfiguration (like changing DVD). */
+    VMSUSPENDREASON_RECONFIG,
+    /** The VM is suspending itself. */
+    VMSUSPENDREASON_VM,
+    /** The Vm is suspending because of a runtime error. */
+    VMSUSPENDREASON_RUNTIME_ERROR,
+    /** The host was suspended. */
+    VMSUSPENDREASON_HOST_SUSPEND,
+    /** The host is running low on battery power. */
+    VMSUSPENDREASON_HOST_BATTERY_LOW,
+    /** FTM is temporarily suspending the VM. */
+    VMSUSPENDREASON_FTM_SYNC,
+    /** End of valid reasons. */
+    VMSUSPENDREASON_END,
+    /** Blow the type up to 32-bits. */
+    VMSUSPENDREASON_32BIT_HACK = 0x7fffffff
+} VMSUSPENDREASON;
+
+
 /**
  * Progress callback.
@@ -353,6 +405,8 @@
                                    PVM *ppVM, PUVM *ppUVM);
 VMMR3DECL(int)          VMR3PowerOn(PUVM pUVM);
-VMMR3DECL(int)          VMR3Suspend(PUVM pUVM);
-VMMR3DECL(int)          VMR3Resume(PUVM pUVM);
+VMMR3DECL(int)          VMR3Suspend(PUVM pUVM, VMSUSPENDREASON enmReason);
+VMMR3DECL(VMSUSPENDREASON) VMR3GetSuspendReason(PUVM);
+VMMR3DECL(int)          VMR3Resume(PUVM pUVM, VMRESUMEREASON enmReason);
+VMMR3DECL(VMRESUMEREASON) VMR3GetResumeReason(PUVM);
 VMMR3DECL(int)          VMR3Reset(PUVM pUVM);
 VMMR3DECL(int)          VMR3Save(PUVM pUVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser, bool *pfSuspended);
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 46787)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 46788)
@@ -3617,5 +3617,5 @@
             /* disable the callback to prevent Console-level state change */
             pConsole->mVMStateChangeCallbackDisabled = true;
-            int rc = VMR3Suspend(pUVM);
+            int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG);
             pConsole->mVMStateChangeCallbackDisabled = false;
             AssertRCReturn(rc, rc);
@@ -3680,5 +3680,5 @@
         /* disable the callback to prevent Console-level state change */
         pConsole->mVMStateChangeCallbackDisabled = true;
-        rc = VMR3Resume(pUVM);
+        rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG);
         pConsole->mVMStateChangeCallbackDisabled = false;
         AssertRC(rc);
@@ -3866,5 +3866,5 @@
             /* disable the callback to prevent Console-level state change */
             pConsole->mVMStateChangeCallbackDisabled = true;
-            int rc = VMR3Suspend(pUVM);
+            int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG);
             pConsole->mVMStateChangeCallbackDisabled = false;
             AssertRCReturn(rc, rc);
@@ -3929,5 +3929,5 @@
         /* disable the callback to prevent Console-level state change */
         pConsole->mVMStateChangeCallbackDisabled = true;
-        rc = VMR3Resume(pUVM);
+        rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG);
         pConsole->mVMStateChangeCallbackDisabled = false;
         AssertRC(rc);
@@ -4109,5 +4109,5 @@
             /* disable the callback to prevent Console-level state change */
             pConsole->mVMStateChangeCallbackDisabled = true;
-            int rc = VMR3Suspend(pUVM);
+            int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG);
             pConsole->mVMStateChangeCallbackDisabled = false;
             AssertRCReturn(rc, rc);
@@ -4191,5 +4191,5 @@
         /* disable the callback to prevent Console-level state change */
         pConsole->mVMStateChangeCallbackDisabled = true;
-        rc = VMR3Resume(pUVM);
+        rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG);
         pConsole->mVMStateChangeCallbackDisabled = false;
         AssertRC(rc);
@@ -4533,5 +4533,5 @@
             /* disable the callback to prevent Console-level state change */
             pThis->mVMStateChangeCallbackDisabled = true;
-            int rc = VMR3Suspend(pUVM);
+            int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG);
             pThis->mVMStateChangeCallbackDisabled = false;
             AssertRCReturn(rc, rc);
@@ -4569,5 +4569,5 @@
         /* disable the callback to prevent Console-level state change */
         pThis->mVMStateChangeCallbackDisabled = true;
-        rc = VMR3Resume(pUVM);
+        rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG);
         pThis->mVMStateChangeCallbackDisabled = false;
         AssertRC(rc);
@@ -5578,5 +5578,5 @@
         /* disable the callback to prevent Console-level state change */
         mVMStateChangeCallbackDisabled = true;
-        int vrc2 = VMR3Suspend(ptrVM.rawUVM());
+        int vrc2 = VMR3Suspend(ptrVM.rawUVM(), VMSUSPENDREASON_RECONFIG);
         mVMStateChangeCallbackDisabled = false;
         AssertRCReturn(vrc2, E_FAIL);
@@ -5607,5 +5607,5 @@
         /* disable the callback to prevent Console-level state change */
         mVMStateChangeCallbackDisabled = true;
-        int vrc2 = VMR3Resume(ptrVM.rawUVM());
+        int vrc2 = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_RECONFIG);
         mVMStateChangeCallbackDisabled = false;
         if (RT_FAILURE(vrc2))
@@ -5649,5 +5649,5 @@
         /* disable the callback to prevent Console-level state change */
         mVMStateChangeCallbackDisabled = true;
-        int vrc2 = VMR3Suspend(ptrVM.rawUVM());
+        int vrc2 = VMR3Suspend(ptrVM.rawUVM(), VMSUSPENDREASON_RECONFIG);
         mVMStateChangeCallbackDisabled = false;
         AssertRCReturn(vrc2, E_FAIL);
@@ -5683,5 +5683,5 @@
         /* disable the callback to prevent Console-level state change */
         mVMStateChangeCallbackDisabled = true;
-        int vrc2 = VMR3Resume(ptrVM.rawUVM());
+        int vrc2 = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_RECONFIG);
         mVMStateChangeCallbackDisabled = false;
         AssertRC(vrc2);
@@ -5753,5 +5753,10 @@
 
     /** @todo r=klaus make use of aReason */
-    int vrc = VMR3Suspend(ptrVM.rawUVM());
+    VMSUSPENDREASON enmReason = VMSUSPENDREASON_USER;
+    if (aReason == Reason_HostSuspend)
+        enmReason = VMSUSPENDREASON_HOST_SUSPEND;
+    else if (aReason == Reason_HostBatteryLow)
+        enmReason = VMSUSPENDREASON_HOST_BATTERY_LOW;
+    int vrc = VMR3Suspend(ptrVM.rawUVM(), enmReason);
 
     HRESULT hrc = S_OK;
@@ -5794,5 +5799,4 @@
         LogRel(("Resuming VM execution, reason \"%s\"\n", Global::stringifyReason(aReason)));
 
-    /** @todo r=klaus make use of aReason */
     int vrc;
     if (VMR3GetStateU(ptrVM.rawUVM()) == VMSTATE_CREATED)
@@ -5807,5 +5811,10 @@
     }
     else
-        vrc = VMR3Resume(ptrVM.rawUVM());
+    {
+        VMRESUMEREASON enmReason = VMRESUMEREASON_USER;
+        if (aReason == Reason_HostResume)
+            enmReason = VMRESUMEREASON_HOST_RESUME;
+        vrc = VMR3Resume(ptrVM.rawUVM(), enmReason);
+    }
 
     HRESULT rc = RT_SUCCESS(vrc) ? S_OK :
@@ -5858,5 +5867,10 @@
         /* release the lock before a VMR3* call (EMT will call us back)! */
         alock.release();
-        int vrc = VMR3Suspend(ptrVM.rawUVM());
+        VMSUSPENDREASON enmReason = VMSUSPENDREASON_USER;
+        if (aReason == Reason_HostSuspend)
+            enmReason = VMSUSPENDREASON_HOST_SUSPEND;
+        else if (aReason == Reason_HostBatteryLow)
+            enmReason = VMSUSPENDREASON_HOST_BATTERY_LOW;
+        int vrc = VMR3Suspend(ptrVM.rawUVM(), enmReason);
         alock.acquire();
 
@@ -5967,5 +5981,5 @@
             {
                 alock.release();
-                VMR3Resume(ptrVM.rawUVM());
+                VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_RESTORED);
                 alock.acquire();
             }
@@ -9090,5 +9104,5 @@
 #endif
                             if (RT_SUCCESS(vrc))
-                                vrc = VMR3Resume(pConsole->mpUVM);
+                                vrc = VMR3Resume(pConsole->mpUVM, VMRESUMEREASON_STATE_RESTORED);
                             AssertLogRelRC(vrc);
                         }
@@ -9630,5 +9644,5 @@
                 SafeVMPtr ptrVM(that);
                 alock.release();
-                int vrc = VMR3Resume(ptrVM.rawUVM());
+                int vrc = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_SAVED);
                 alock.acquire();
                 if (RT_FAILURE(vrc))
@@ -9688,5 +9702,5 @@
                         SafeVMPtr ptrVM(that);
                         alock.release();
-                        int vrc = VMR3Resume(ptrVM.rawUVM()); AssertLogRelRC(vrc);
+                        int vrc = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_SAVED); AssertLogRelRC(vrc);
                         alock.acquire();
                         if (RT_FAILURE(vrc))
@@ -9747,5 +9761,4 @@
     LogFlowFunc(("Saving the state to '%s'...\n", task->mSavedStateFile.c_str()));
 
-    /** @todo r=klaus make use of task->mReason */
     bool fSuspenededBySave;
     int vrc = VMR3Save(task->mpUVM,
Index: /trunk/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp	(revision 46787)
+++ /trunk/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp	(revision 46788)
@@ -888,5 +888,5 @@
                         {
                             autoLock.release();
-                            int rc = VMR3Resume(pState->mpUVM);
+                            int rc = VMR3Resume(pState->mpUVM, VMRESUMEREASON_TELEPORT_FAILED);
                             AssertLogRelMsgRC(rc, ("VMR3Resume -> %Rrc\n", rc));
                             autoLock.acquire();
@@ -1413,5 +1413,5 @@
                 {
                     if (!strcmp(szCmd, "hand-over-resume"))
-                        vrc = VMR3Resume(pState->mpUVM);
+                        vrc = VMR3Resume(pState->mpUVM, VMRESUMEREASON_TELEPORTED);
                     else
                         pState->mptrConsole->setMachineState(MachineState_Paused);
Index: /trunk/src/VBox/VMM/VMMR3/FTM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/FTM.cpp	(revision 46787)
+++ /trunk/src/VBox/VMM/VMMR3/FTM.cpp	(revision 46788)
@@ -638,5 +638,5 @@
     bool fSuspended = false;
 
-    int rc = VMR3Suspend(pVM->pUVM);
+    int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_FTM_SYNC);
     AssertRCReturn(rc, rc);
 
@@ -668,5 +668,5 @@
     AssertRCReturn(rc, rc);
 
-    rc = VMR3Resume(pVM->pUVM);
+    rc = VMR3Resume(pVM->pUVM, VMRESUMEREASON_FTM_SYNC);
     AssertRC(rc);
 
Index: /trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp	(revision 46787)
+++ /trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp	(revision 46788)
@@ -2215,5 +2215,5 @@
     PDMDEV_ASSERT_DEVINS(pDevIns);
     PVM pVM = pDevIns->Internal.s.pVMR3;
-    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
+    VM_ASSERT_EMT(pVM);
     LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
              pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
@@ -2256,4 +2256,30 @@
              pDevIns->iInstance, rc));
     return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLP,pfnVMGetSuspendReason} */
+static DECLCALLBACK(VMSUSPENDREASON) pdmR3DevHlp_VMGetSuspendReason(PPDMDEVINS pDevIns)
+{
+    PDMDEV_ASSERT_DEVINS(pDevIns);
+    PVM pVM = pDevIns->Internal.s.pVMR3;
+    VM_ASSERT_EMT(pVM);
+    VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
+    LogFlow(("pdmR3DevHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
+             pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
+    return enmReason;
+}
+
+
+/** @interface_method_impl{PDMDEVHLP,pfnVMGetResumeReason} */
+static DECLCALLBACK(VMRESUMEREASON) pdmR3DevHlp_VMGetResumeReason(PPDMDEVINS pDevIns)
+{
+    PDMDEV_ASSERT_DEVINS(pDevIns);
+    PVM pVM = pDevIns->Internal.s.pVMR3;
+    VM_ASSERT_EMT(pVM);
+    VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
+    LogFlow(("pdmR3DevHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
+             pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
+    return enmReason;
 }
 
@@ -3256,10 +3282,10 @@
     {
         /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
-        rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 1, pVM->pUVM);
+        rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 2, pVM->pUVM, VMSUSPENDREASON_VM);
         AssertRC(rc);
         rc = VINF_EM_SUSPEND;
     }
     else
-        rc = VMR3Suspend(pVM->pUVM);
+        rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
 
     LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
@@ -3281,5 +3307,5 @@
      * Suspend the VM first then do the saving.
      */
-    int rc = VMR3Suspend(pVM->pUVM);
+    int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
     if (RT_SUCCESS(rc))
     {
@@ -3494,6 +3520,6 @@
     pdmR3DevHlp_LdrGetR0InterfaceSymbols,
     pdmR3DevHlp_CallR0,
-    0,
-    0,
+    pdmR3DevHlp_VMGetSuspendReason,
+    pdmR3DevHlp_VMGetResumeReason,
     0,
     0,
@@ -3735,6 +3761,6 @@
     pdmR3DevHlp_LdrGetR0InterfaceSymbols,
     pdmR3DevHlp_CallR0,
-    0,
-    0,
+    pdmR3DevHlp_VMGetSuspendReason,
+    pdmR3DevHlp_VMGetResumeReason,
     0,
     0,
Index: /trunk/src/VBox/VMM/VMMR3/PDMDriver.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PDMDriver.cpp	(revision 46787)
+++ /trunk/src/VBox/VMM/VMMR3/PDMDriver.cpp	(revision 46788)
@@ -1758,4 +1758,31 @@
 
 
+
+/** @interface_method_impl{PDMDRVHLP,pfnVMGetSuspendReason} */
+static DECLCALLBACK(VMSUSPENDREASON) pdmR3DrvHlp_VMGetSuspendReason(PPDMDRVINS pDrvIns)
+{
+    PDMDRV_ASSERT_DRVINS(pDrvIns);
+    PVM pVM = pDrvIns->Internal.s.pVMR3;
+    VM_ASSERT_EMT(pVM);
+    VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
+    LogFlow(("pdmR3DrvHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
+             pDrvIns->pReg->szName, pDrvIns->iInstance, enmReason));
+    return enmReason;
+}
+
+
+/** @interface_method_impl{PDMDRVHLP,pfnVMGetResumeReason} */
+static DECLCALLBACK(VMRESUMEREASON) pdmR3DrvHlp_VMGetResumeReason(PPDMDRVINS pDrvIns)
+{
+    PDMDRV_ASSERT_DRVINS(pDrvIns);
+    PVM pVM = pDrvIns->Internal.s.pVMR3;
+    VM_ASSERT_EMT(pVM);
+    VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
+    LogFlow(("pdmR3DrvHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
+             pDrvIns->pReg->szName, pDrvIns->iInstance, enmReason));
+    return enmReason;
+}
+
+
 /**
  * The driver helper structure.
@@ -1805,4 +1832,16 @@
     pdmR3DrvHlp_FTSetCheckpoint,
     pdmR3DrvHlp_BlkCacheRetain,
+    pdmR3DrvHlp_VMGetSuspendReason,
+    pdmR3DrvHlp_VMGetResumeReason,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
     PDM_DRVHLPR3_VERSION /* u32TheEnd */
 };
Index: /trunk/src/VBox/VMM/VMMR3/PDMUsb.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PDMUsb.cpp	(revision 46787)
+++ /trunk/src/VBox/VMM/VMMR3/PDMUsb.cpp	(revision 46788)
@@ -1465,4 +1465,30 @@
 
 
+/** @interface_method_impl{PDMUSBHLP,pfnVMGetSuspendReason} */
+static DECLCALLBACK(VMSUSPENDREASON) pdmR3UsbHlp_VMGetSuspendReason(PPDMUSBINS pUsbIns)
+{
+    PDMUSB_ASSERT_USBINS(pUsbIns);
+    PVM pVM = pUsbIns->Internal.s.pVM;
+    VM_ASSERT_EMT(pVM);
+    VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
+    LogFlow(("pdmR3UsbHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
+             pUsbIns->pReg->szName, pUsbIns->iInstance, enmReason));
+    return enmReason;
+}
+
+
+/** @interface_method_impl{PDMUSBHLP,pfnVMGetResumeReason} */
+static DECLCALLBACK(VMRESUMEREASON) pdmR3UsbHlp_VMGetResumeReason(PPDMUSBINS pUsbIns)
+{
+    PDMUSB_ASSERT_USBINS(pUsbIns);
+    PVM pVM = pUsbIns->Internal.s.pVM;
+    VM_ASSERT_EMT(pVM);
+    VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
+    LogFlow(("pdmR3UsbHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
+             pUsbIns->pReg->szName, pUsbIns->iInstance, enmReason));
+    return enmReason;
+}
+
+
 /**
  * The USB device helper structure.
@@ -1488,4 +1514,16 @@
     pdmR3UsbHlp_SetAsyncNotification,
     pdmR3UsbHlp_AsyncNotificationCompleted,
+    pdmR3UsbHlp_VMGetSuspendReason,
+    pdmR3UsbHlp_VMGetResumeReason,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
     PDM_USBHLP_VERSION
 };
Index: /trunk/src/VBox/VMM/VMMR3/VM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VM.cpp	(revision 46787)
+++ /trunk/src/VBox/VMM/VMMR3/VM.cpp	(revision 46788)
@@ -1343,6 +1343,6 @@
 static DECLCALLBACK(VBOXSTRICTRC) vmR3Suspend(PVM pVM, PVMCPU pVCpu, void *pvUser)
 {
-    LogFlow(("vmR3Suspend: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu));
-    Assert(!pvUser); NOREF(pvUser);
+    VMSUSPENDREASON enmReason = (VMSUSPENDREASON)(uintptr_t)pvUser;
+    LogFlow(("vmR3Suspend: pVM=%p pVCpu=%p/#%u enmReason=%d\n", pVM, pVCpu, pVCpu->idCpu, enmReason));
 
     /*
@@ -1358,4 +1358,5 @@
         if (RT_FAILURE(rc))
             return rc;
+        pVM->pUVM->vm.s.enmSuspendReason = enmReason;
     }
 
@@ -1391,5 +1392,6 @@
  *          code that has to be propagated up the call stack.
  *
- * @param   pUVM    The VM to suspend.
+ * @param   pUVM        The VM to suspend.
+ * @param   enmReason   The reason for suspending.
  *
  * @thread      Any thread.
@@ -1397,8 +1399,9 @@
  * @vmstateto   Suspending + Suspended or SuspendingExtLS + SuspendedExtLS
  */
-VMMR3DECL(int) VMR3Suspend(PUVM pUVM)
+VMMR3DECL(int) VMR3Suspend(PUVM pUVM, VMSUSPENDREASON enmReason)
 {
     LogFlow(("VMR3Suspend: pUVM=%p\n", pUVM));
     UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
+    AssertReturn(enmReason > VMSUSPENDREASON_INVALID && enmReason < VMSUSPENDREASON_END, VERR_INVALID_PARAMETER);
 
     /*
@@ -1407,5 +1410,5 @@
      */
     int rc = VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
-                                vmR3Suspend, NULL);
+                                vmR3Suspend, (void *)(uintptr_t)enmReason);
     LogFlow(("VMR3Suspend: returns %Rrc\n", rc));
     return rc;
@@ -1414,4 +1417,18 @@
 
 /**
+ * Retrieves the reason for the most recent suspend.
+ *
+ * @returns Suspend reason. VMSUSPENDREASON_INVALID if no suspend has been done
+ *          or the handle is invalid.
+ * @param   pUVM        The user mode VM handle.
+ */
+VMMR3DECL(VMSUSPENDREASON) VMR3GetSuspendReason(PUVM pUVM)
+{
+    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VMSUSPENDREASON_INVALID);
+    return pUVM->vm.s.enmSuspendReason;
+}
+
+
+/**
  * EMT rendezvous worker for VMR3Resume.
  *
@@ -1421,10 +1438,10 @@
  * @param   pVM             Pointer to the VM.
  * @param   pVCpu           Pointer to the VMCPU of the EMT.
- * @param   pvUser          Ignored.
+ * @param   pvUser          Reason.
  */
 static DECLCALLBACK(VBOXSTRICTRC) vmR3Resume(PVM pVM, PVMCPU pVCpu, void *pvUser)
 {
-    LogFlow(("vmR3Resume: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu));
-    Assert(!pvUser); NOREF(pvUser);
+    VMRESUMEREASON enmReason = (VMRESUMEREASON)(uintptr_t)pvUser;
+    LogFlow(("vmR3Resume: pVM=%p pVCpu=%p/#%u enmReason=%d\n", pVM, pVCpu, pVCpu->idCpu, enmReason));
 
     /*
@@ -1437,4 +1454,5 @@
         if (RT_FAILURE(rc))
             return rc;
+        pVM->pUVM->vm.s.enmResumeReason = enmReason;
     }
 
@@ -1473,4 +1491,5 @@
  *
  * @param   pVM         The VM to resume.
+ * @param   enmReason   The reason we're resuming.
  *
  * @thread      Any thread.
@@ -1478,5 +1497,5 @@
  * @vmstateto   Running
  */
-VMMR3DECL(int) VMR3Resume(PUVM pUVM)
+VMMR3DECL(int) VMR3Resume(PUVM pUVM, VMRESUMEREASON enmReason)
 {
     LogFlow(("VMR3Resume: pUVM=%p\n", pUVM));
@@ -1484,4 +1503,5 @@
     PVM pVM = pUVM->pVM;
     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
+    AssertReturn(enmReason > VMRESUMEREASON_INVALID && enmReason < VMRESUMEREASON_END, VERR_INVALID_PARAMETER);
 
     /*
@@ -1490,7 +1510,21 @@
      */
     int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
-                                vmR3Resume, NULL);
+                                vmR3Resume, (void *)(uintptr_t)enmReason);
     LogFlow(("VMR3Resume: returns %Rrc\n", rc));
     return rc;
+}
+
+
+/**
+ * Retrieves the reason for the most recent resume.
+ *
+ * @returns Resume reason. VMRESUMEREASON_INVALID if no suspend has been
+ *          done or the handle is invalid.
+ * @param   pUVM        The user mode VM handle.
+ */
+VMMR3DECL(VMRESUMEREASON) VMR3GetResumeReason(PUVM pUVM)
+{
+    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VMRESUMEREASON_INVALID);
+    return pUVM->vm.s.enmResumeReason;
 }
 
@@ -4052,5 +4086,5 @@
                                 vmR3SetRuntimeErrorChangeState, NULL);
     else if (fFlags & VMSETRTERR_FLAGS_SUSPEND)
-        rc = VMR3Suspend(pUVM);
+        rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RUNTIME_ERROR);
     else
         rc = VINF_SUCCESS;
Index: /trunk/src/VBox/VMM/include/VMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/VMInternal.h	(revision 46787)
+++ /trunk/src/VBox/VMM/include/VMInternal.h	(revision 46788)
@@ -228,4 +228,9 @@
      * and when debugging. */
     VMSTATE                         enmPrevVMState;
+
+    /** Reason for the most recent suspend operation. */
+    VMSUSPENDREASON                 enmSuspendReason;
+    /** Reason for the most recent operation. */
+    VMRESUMEREASON                  enmResumeReason;
 
     /** Critical section for pAtError and pAtRuntimeError. */
