Index: /trunk/Config.kmk
===================================================================
--- /trunk/Config.kmk	(revision 22783)
+++ /trunk/Config.kmk	(revision 22784)
@@ -505,4 +505,16 @@
 endif
 
+#
+# Config items for enabling work in progress.
+#
+# It's good pratice to add stuff here even if it is currently disabled by
+# default.
+#
+# Note! Please, do *not* add stuff to the global DEFS unless it is *really*
+#       necessary!  The other guys will hate for it you when they have to
+#       recompile everything when the feature is enabled or disabled.  Put
+#       the ifdefs in target or template definitions.
+#
+
 ## For experimenting with disabling preemption instead of interrupts
 # when working VT-x/AMD-V in VMMR0.
@@ -511,4 +523,7 @@
  VBOX_WITH_VMMR0_DISABLE_PREEMPTION = 1
 endif
+
+## Enabled the live migration API changes.
+#VBOX_WITH_LIVE_MIGRATION = 1
 
 #
Index: /trunk/include/VBox/vmapi.h
===================================================================
--- /trunk/include/VBox/vmapi.h	(revision 22783)
+++ /trunk/include/VBox/vmapi.h	(revision 22784)
@@ -370,5 +370,5 @@
 typedef FNVMPROGRESS *PFNVMPROGRESS;
 
-VMMR3DECL(int)  VMR3Save(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
+VMMR3DECL(int)  VMR3Save(PVM pVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser);
 VMMR3DECL(int)  VMR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
 VMMR3DECL(int)  VMR3PowerOff(PVM pVM);
Index: /trunk/src/VBox/Frontends/VBoxBFE/VMControl.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxBFE/VMControl.cpp	(revision 22783)
+++ /trunk/src/VBox/Frontends/VBoxBFE/VMControl.cpp	(revision 22784)
@@ -161,5 +161,5 @@
     startProgressInfo("Saving");
     rc = VMR3ReqCall(pVM, VMCPUID_ANY, &pReq, RT_INDEFINITE_WAIT,
-                     (PFNRT)VMR3Save, 4, pVM, g_pszStateFile, &callProgressInfo, (uintptr_t)NULL);
+                     (PFNRT)VMR3Save, 5, pVM, g_pszStateFile, false /*fContinueAftewards*/, &callProgressInfo, (uintptr_t)NULL);
     endProgressInfo();
     if (RT_SUCCESS(rc))
Index: /trunk/src/VBox/Main/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 22783)
+++ /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 22784)
@@ -2386,4 +2386,5 @@
     MachineState_T lastMachineState = mMachineState;
 
+#ifndef VBOX_WITH_LIVE_MIGRATION /** @todo update the API docs. */
     if (mMachineState == MachineState_Running)
     {
@@ -2391,8 +2392,10 @@
         CheckComRCReturnRC(rc);
     }
+#endif
 
     HRESULT rc = S_OK;
 
-    bool fTakingSnapshotOnline = (mMachineState == MachineState_Paused);
+    bool const fTakingSnapshotOnline = (   mMachineState == MachineState_Running
+                                        || mMachineState == MachineState_Paused);
 
     /*
@@ -2450,6 +2453,5 @@
 
         /*
-         *  state file is non-null only when the VM is paused
-         *  (i.e. creating a snapshot online)
+         *  The state file is non-null only when creating a online or live snapshot.
          */
         ComAssertBreak(    (!stateFilePath.isNull() && fTakingSnapshotOnline)
@@ -7316,4 +7318,5 @@
         int vrc = VMR3Save(that->mpVM,
                            task->mSavedStateFile.c_str(),
+                           task->mIsSnapshot /*fContinueAfterwards*/,
                            Console::stateProgressCallback,
                            static_cast<VMProgressTask*>(task.get()));
Index: /trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineImpl.cpp	(revision 22783)
+++ /trunk/src/VBox/Main/MachineImpl.cpp	(revision 22784)
@@ -7927,4 +7927,7 @@
     AssertReturn(    (    !Global::IsOnlineOrTransient (mData->mMachineState)
                        || mData->mMachineState == MachineState_Paused
+#ifdef VBOX_WITH_LIVE_MIGRATION
+                       || mData->mMachineState == MachineState_Running
+#endif
                      )
                   && mSnapshotData.mLastState == MachineState_Null
@@ -7933,5 +7936,6 @@
                   && mSnapshotData.mCombinedProgress.isNull(), E_FAIL);
 
-    bool fTakingSnapshotOnline = (mData->mMachineState == MachineState_Paused);
+    bool const fTakingSnapshotOnline = (   mData->mMachineState == MachineState_Running
+                                        || mData->mMachineState == MachineState_Paused);
 
     if (    !fTakingSnapshotOnline
Index: /trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Main/Makefile.kmk	(revision 22783)
+++ /trunk/src/VBox/Main/Makefile.kmk	(revision 22784)
@@ -216,5 +216,6 @@
 	$(if $(VBOX_WITH_PDM_ASYNC_COMPLETION),VBOX_WITH_PDM_ASYNC_COMPLETION,) \
 	$(if $(VBOX_WITH_DBUS),VBOX_WITH_DBUS,) \
-	$(if $(VBOX_USB_WITH_SYSFS),VBOX_USB_WITH_SYSFS,)
+	$(if $(VBOX_USB_WITH_SYSFS),VBOX_USB_WITH_SYSFS,) \
+	$(if $(VBOX_WITH_LIVE_MIGRATION),VBOX_WITH_LIVE_MIGRATION,)
 ifdef VBOX_WITH_USB
  VBoxSVC_DEFS += \
@@ -529,5 +530,6 @@
 	$(if $(VBOX_WITH_SMC),VBOX_WITH_SMC,) \
 	$(if $(VBOX_WITH_LPC),VBOX_WITH_LPC,) \
-	$(if $(VBOX_WITH_PDM_ASYNC_COMPLETION),VBOX_WITH_PDM_ASYNC_COMPLETION,)
+	$(if $(VBOX_WITH_PDM_ASYNC_COMPLETION),VBOX_WITH_PDM_ASYNC_COMPLETION,) \
+	$(if $(VBOX_WITH_LIVE_MIGRATION),VBOX_WITH_LIVE_MIGRATION,)
 ifdef VBOX_WITH_USB
 VBoxC_DEFS += \
Index: /trunk/src/VBox/VMM/VM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VM.cpp	(revision 22783)
+++ /trunk/src/VBox/VMM/VM.cpp	(revision 22784)
@@ -135,5 +135,5 @@
 static DECLCALLBACK(int) vmR3Suspend(PVM pVM);
 static DECLCALLBACK(int) vmR3Resume(PVM pVM);
-static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
+static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser);
 static DECLCALLBACK(int) vmR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
 static DECLCALLBACK(int) vmR3PowerOff(PVM pVM);
@@ -1386,5 +1386,58 @@
  * Save current VM state.
  *
- * To save and terminate the VM, the VM must be suspended before the call.
+ * Can be used for both saving the state and creating snapshots.
+ *
+ * When called for a VM in the RUNNING state, the saved state is created live
+ * and the VM is only suspended when the final part of the saving is preformed.
+ * The VM state will not be restored to RUNNING in this case and it's up to the
+ * caller to call VMR3Resume if this is desirable.  (The rational is that the
+ * caller probably wish to reconfigure the disks before resuming the VM.)
+ *
+ * @returns VBox status code.
+ *
+ * @param   pVM                 VM which state should be saved.
+ * @param   pszFilename         Name of the save state file.
+ * @param   fContinueAftewards  Continue execution afterwards. When in doubt,
+ *                              set this to true.
+ * @param   pfnProgress         Progress callback. Optional.
+ * @param   pvUser              User argument for the progress callback.
+ *
+ * @thread      Any thread. Will forward the request to EMT(0).
+ * @vmstate     Suspended, Running
+ * @vmstateto   Suspended.
+ */
+VMMR3DECL(int) VMR3Save(PVM pVM, const char *pszFilename, bool fContinueAftewards, PFNVMPROGRESS pfnProgress, void *pvUser)
+{
+    LogFlow(("VMR3Save: pVM=%p pszFilename=%p:{%s} fContinueAftewards=%RTbool pfnProgress=%p pvUser=%p\n",
+             pVM, pszFilename, pszFilename, fContinueAftewards, pfnProgress, pvUser));
+
+    /*
+     * Validate input.
+     */
+    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
+    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
+    AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
+    AssertPtrNullReturn(pfnProgress, VERR_INVALID_POINTER);
+
+    /*
+     * Request the operation in EMT(0).
+     */
+    SSMAFTER enmAfter = fContinueAftewards ? SSMAFTER_CONTINUE : SSMAFTER_DESTROY;
+    PVMREQ pReq;
+    int rc = VMR3ReqCall(pVM, 0 /* VCPU 0 */, &pReq, RT_INDEFINITE_WAIT,
+                         (PFNRT)vmR3Save, 5, pVM, pszFilename, enmAfter, pfnProgress, pvUser);
+    if (RT_SUCCESS(rc))
+    {
+        rc = pReq->iStatus;
+        VMR3ReqFree(pReq);
+    }
+
+    LogFlow(("VMR3Save: returns %Rrc\n", rc));
+    return rc;
+}
+
+
+/**
+ * Worker for VMR3Save that validates the state and calls SSMR3Save.
  *
  * @returns 0 on success.
@@ -1392,72 +1445,24 @@
  * @param   pVM             VM which state should be saved.
  * @param   pszFilename     Name of the save state file.
- * @param   pfnProgress     Progress callback. Optional.
- * @param   pvUser          User argument for the progress callback.
- * @thread      Any thread.
- * @vmstate     Suspended
- * @vmstateto   Unchanged state.
- */
-VMMR3DECL(int) VMR3Save(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
-{
-    LogFlow(("VMR3Save: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
-
-    /*
-     * Validate input.
-     */
-    if (!pVM)
-    {
-        AssertMsgFailed(("Invalid VM pointer\n"));
-        return VERR_INVALID_PARAMETER;
-    }
-    if (!pszFilename)
-    {
-        AssertMsgFailed(("Must specify a filename to save the state to, wise guy!\n"));
-        return VERR_INVALID_PARAMETER;
-    }
-
-    /*
-     * Request the operation in EMT.
-     */
-    PVMREQ pReq;
-    int rc = VMR3ReqCall(pVM, 0 /* VCPU 0 */, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Save, 4, pVM, pszFilename, pfnProgress, pvUser);
-    if (RT_SUCCESS(rc))
-    {
-        rc = pReq->iStatus;
-        VMR3ReqFree(pReq);
-    }
-
-    LogFlow(("VMR3Save: returns %Rrc\n", rc));
-    return rc;
-}
-
-
-/**
- * Save current VM state.
- *
- * To save and terminate the VM, the VM must be suspended before the call.
- *
- * @returns 0 on success.
- * @returns VBox error code on failure.
- * @param   pVM             VM which state should be saved.
- * @param   pszFilename     Name of the save state file.
+ * @param   enmAfter        What to do afterwards.
  * @param   pfnProgress     Progress callback. Optional.
  * @param   pvUser          User argument for the progress callback.
  * @thread  EMT
  */
-static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
-{
-    LogFlow(("vmR3Save: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
+static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser)
+{
+    LogFlow(("vmR3Save: pVM=%p pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
 
     /*
      * Validate input.
      */
-    if (pVM->enmVMState != VMSTATE_SUSPENDED)
-    {
-        AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
-        return VERR_VM_INVALID_VM_STATE;
-    }
+    /** @todo SMP: Check that vmR3SetState always done by EMT(0). If not add a vmR3TrySetState(). */
+    AssertMsgReturn(   pVM->enmVMState == VMSTATE_SUSPENDED
+                    || pVM->enmVMState == VMSTATE_RUNNING,
+                    ("%d\n", pVM->enmVMState),
+                    VERR_VM_INVALID_VM_STATE);
 
     /* If we are in an inconsistent state, then we don't allow state saving. */
-    if (pVM->vm.s.fPreventSaveState)
+    if (pVM->vm.s.fPreventSaveState)    /** @todo Incorporate VMINT::fPreventSaveState into the VMSTATE. There is a defect for this. */
     {
         LogRel(("VMM: vmR3Save: saving the VM state is not allowed at this moment\n"));
@@ -1468,6 +1473,6 @@
      * Change the state and perform the save.
      */
-    vmR3SetState(pVM, VMSTATE_SAVING);
-    int rc = SSMR3Save(pVM, pszFilename, SSMAFTER_CONTINUE, pfnProgress,  pvUser);
+    vmR3SetState(pVM, VMSTATE_SAVING); /** @todo Should probably use a different state for live snapshots and/or live migration. Will fix the state machine later. */
+    int rc = SSMR3Save(pVM, pszFilename, enmAfter, pfnProgress,  pvUser);
     vmR3SetState(pVM, VMSTATE_SUSPENDED);
 
