VirtualBox

Changeset 23009 in vbox


Ignore:
Timestamp:
Sep 14, 2009 3:05:45 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
52301
Message:

VMM: State machine adjustments. Have only received basic testing.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/types.h

    r22975 r23009  
    156156    /** The VM is being powered on */
    157157    VMSTATE_POWERING_ON,
     158    /** The VM is being resumed. */
     159    VMSTATE_RESUMING,
    158160    /** The VM is runnning. */
    159161    VMSTATE_RUNNING,
     
    187189    /** The VM is switched off, awaiting destruction. */
    188190    VMSTATE_OFF,
     191    /** Live save: Waiting for cancellation and transition to VMSTATE_OFF. */
     192    VMSTATE_OFF_LS,
    189193    /** The VM is powered off because of a fatal error. */
    190194    VMSTATE_FATAL_ERROR,
  • trunk/include/VBox/vm.h

    r22893 r23009  
    678678    /** The state of the VM.
    679679     * This field is read only to everyone except the VM and EM. */
    680     VMSTATE                     enmVMState;
     680    VMSTATE volatile            enmVMState;
    681681    /** Forced action flags.
    682682     * See the VM_FF_* \#defines. Updated atomically.
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r22915 r23009  
    56185618 */
    56195619DECLCALLBACK(void)
    5620 Console::vmstateChangeCallback (PVM aVM, VMSTATE aState, VMSTATE aOldState,
    5621                                 void *aUser)
    5622 {
    5623     LogFlowFunc (("Changing state from %d to %d (aVM=%p)\n",
    5624                   aOldState, aState, aVM));
    5625 
    5626     Console *that = static_cast <Console *> (aUser);
    5627     AssertReturnVoid (that);
     5620Console::vmstateChangeCallback(PVM aVM, VMSTATE aState, VMSTATE aOldState,
     5621                               void *aUser)
     5622{
     5623    LogFlowFunc(("Changing state from %d to %d (aVM=%p)\n",
     5624                 aOldState, aState, aVM));
     5625
     5626    Console *that = static_cast<Console *> (aUser);
     5627    AssertReturnVoid(that);
    56285628
    56295629    AutoCaller autoCaller(that);
     
    56335633     * 1) powerDown() called from uninit() itself, or
    56345634     * 2) VM-(guest-)initiated power off. */
    5635     AssertReturnVoid (autoCaller.isOk() ||
    5636                       autoCaller.state() == InUninit);
     5635    AssertReturnVoid(   autoCaller.isOk()
     5636                     || autoCaller.state() == InUninit);
    56375637
    56385638    switch (aState)
     
    56515651             * VM-(guest-)initiated shutdown/poweroff.
    56525652             */
    5653             if (that->mMachineState != MachineState_Stopping &&
    5654                 that->mMachineState != MachineState_Saving &&
    5655                 that->mMachineState != MachineState_Restoring)
     5653            if (   that->mMachineState != MachineState_Stopping
     5654                && that->mMachineState != MachineState_Saving
     5655                && that->mMachineState != MachineState_Restoring)
    56565656            {
    5657                 LogFlowFunc (("VM has powered itself off but Console still "
    5658                               "thinks it is running. Notifying.\n"));
     5657                LogFlowFunc(("VM has powered itself off but Console still thinks it is running. Notifying.\n"));
    56595658
    56605659                /* prevent powerDown() from calling VMR3PowerOff() again */
    5661                 Assert (that->mVMPoweredOff == false);
     5660                Assert(that->mVMPoweredOff == false);
    56625661                that->mVMPoweredOff = true;
    56635662
    56645663                /* we are stopping now */
    5665                 that->setMachineState (MachineState_Stopping);
     5664                that->setMachineState(MachineState_Stopping);
    56665665
    56675666                /* Setup task object and thread to carry out the operation
     
    56705669                 * deadlock).
    56715670                 */
    5672                 std::auto_ptr <VMProgressTask> task (
    5673                     new VMProgressTask (that, NULL /* aProgress */,
    5674                                         true /* aUsesVMPtr */));
     5671                std::auto_ptr<VMProgressTask> task(new VMProgressTask(that, NULL /* aProgress */,
     5672                                                                      true /* aUsesVMPtr */));
    56755673
    56765674                 /* If creating a task is falied, this can currently mean one of
     
    56825680                if (!task->isOk())
    56835681                {
    5684                     LogFlowFunc (("Console is already being uninitialized.\n"));
     5682                    LogFlowFunc(("Console is already being uninitialized.\n"));
    56855683                    break;
    56865684                }
    56875685
    5688                 int vrc = RTThreadCreate (NULL, Console::powerDownThread,
    5689                                           (void *) task.get(), 0,
    5690                                           RTTHREADTYPE_MAIN_WORKER, 0,
    5691                                           "VMPowerDown");
    5692 
    5693                 AssertMsgRCBreak (vrc,
    5694                     ("Could not create VMPowerDown thread (%Rrc)\n", vrc));
     5686                int vrc = RTThreadCreate(NULL, Console::powerDownThread,
     5687                                         (void *) task.get(), 0,
     5688                                         RTTHREADTYPE_MAIN_WORKER, 0,
     5689                                         "VMPowerDown");
     5690                AssertMsgRCBreak(vrc, ("Could not create VMPowerDown thread (%Rrc)\n", vrc));
    56955691
    56965692                /* task is now owned by powerDownThread(), so release it */
     
    57325728                case MachineState_Stopping:
    57335729                    /* successfully powered down */
    5734                     that->setMachineState (MachineState_PoweredOff);
     5730                    that->setMachineState(MachineState_PoweredOff);
    57355731                    break;
    57365732                case MachineState_Saving:
     
    57395735                     * called from saveStateThread(), so only change the local
    57405736                     * state) */
    5741                     that->setMachineStateLocally (MachineState_Saved);
     5737                    that->setMachineStateLocally(MachineState_Saved);
    57425738                    break;
    57435739                case MachineState_Starting:
    57445740                    /* failed to start, but be patient: set back to PoweredOff
    57455741                     * (for similarity with the below) */
    5746                     that->setMachineState (MachineState_PoweredOff);
     5742                    that->setMachineState(MachineState_PoweredOff);
    57475743                    break;
    57485744                case MachineState_Restoring:
    57495745                    /* failed to load the saved state file, but be patient: set
    57505746                     * back to Saved (to preserve the saved state file) */
    5751                     that->setMachineState (MachineState_Saved);
     5747                    that->setMachineState(MachineState_Saved);
    57525748                    break;
    57535749            }
    5754 
    57555750            break;
    57565751        }
     
    57585753        case VMSTATE_SUSPENDED:
    57595754        {
    5760             if (aOldState == VMSTATE_RUNNING)
     5755            /** @todo state/live VMSTATE_SUSPENDING_LS. */
     5756            if ( aOldState == VMSTATE_SUSPENDING)
    57615757            {
    57625758                AutoWriteLock alock(that);
     
    57655761                    break;
    57665762
    5767                 /* Change the machine state from Running to Paused */
    5768                 Assert (that->mMachineState == MachineState_Running);
    5769                 that->setMachineState (MachineState_Paused);
     5763                /* Change the machine state from Running to Paused. */
     5764                AssertBreak(that->mMachineState == MachineState_Running);
     5765                that->setMachineState(MachineState_Paused);
    57705766            }
    5771 
    57725767            break;
    57735768        }
     
    57755770        case VMSTATE_RUNNING:
    57765771        {
    5777             if (aOldState == VMSTATE_CREATED ||
    5778                 aOldState == VMSTATE_SUSPENDED)
     5772            if (   aOldState == VMSTATE_POWERING_ON
     5773                || aOldState == VMSTATE_RESUMING)
    57795774            {
    57805775                AutoWriteLock alock(that);
     
    57875782                Assert (   (   (   that->mMachineState == MachineState_Starting
    57885783                                || that->mMachineState == MachineState_Paused)
    5789                             && aOldState == VMSTATE_CREATED)
     5784                            && aOldState == VMSTATE_POWERING_ON)
    57905785                        || (   (   that->mMachineState == MachineState_Restoring
    57915786                                || that->mMachineState == MachineState_Paused)
    5792                             && aOldState == VMSTATE_SUSPENDED));
     5787                            && aOldState == VMSTATE_RESUMING));
    57935788
    57945789                that->setMachineState (MachineState_Running);
     
    58135808             *       visible state for this yet.  */
    58145809            that->setMachineState(MachineState_Paused);
    5815 
    58165810            break;
    58175811        }
     
    58255819
    58265820            /* Guru are only for running VMs */
    5827             Assert (Global::IsOnline (that->mMachineState));
    5828 
    5829             that->setMachineState (MachineState_Stuck);
    5830 
     5821            Assert(Global::IsOnline (that->mMachineState));
     5822
     5823            that->setMachineState(MachineState_Stuck);
    58315824            break;
    58325825        }
  • trunk/src/VBox/VMM/PGMPhys.cpp

    r22947 r23009  
    17201720
    17211721            /* we're leaking hyper memory here if done at runtime. */
    1722             Assert(   VMR3GetState(pVM) == VMSTATE_OFF
    1723                    || VMR3GetState(pVM) == VMSTATE_DESTROYING
    1724                    || VMR3GetState(pVM) == VMSTATE_TERMINATED
    1725                    || VMR3GetState(pVM) == VMSTATE_CREATING);
     1722#ifdef VBOX_STRICT
     1723            VMSTATE const enmState = VMR3GetState(pVM);
     1724            AssertMsg(   enmState == VMSTATE_POWERING_OFF
     1725                      || enmState == VMSTATE_POWERING_OFF_LS
     1726                      || enmState == VMSTATE_OFF
     1727                      || enmState == VMSTATE_OFF_LS
     1728                      || enmState == VMSTATE_DESTROYING
     1729                      || enmState == VMSTATE_TERMINATED
     1730                      || enmState == VMSTATE_CREATING
     1731                      , ("%s\n", VMR3GetStateName(enmState)));
     1732#endif
    17261733            /*rc = MMHyperFree(pVM, pCur);
    17271734            AssertRCReturn(rc, rc); - not safe, see the alloc call. */
  • trunk/src/VBox/VMM/VM.cpp

    r23001 r23009  
    133133static int               vmR3InitDoCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
    134134static DECLCALLBACK(size_t) vmR3LogPrefixCallback(PRTLOGGER pLogger, char *pchBuf, size_t cchBuf, void *pvUser);
    135 static DECLCALLBACK(int) vmR3PowerOn(PVM pVM);
    136 static int               vmR3SuspendCommon(PVM pVM, bool fFatal);
    137 static DECLCALLBACK(int) vmR3Suspend(PVM pVM, bool fFatal);
    138 static DECLCALLBACK(int) vmR3Resume(PVM pVM);
    139 static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM);
    140 static DECLCALLBACK(int) vmR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
    141135static DECLCALLBACK(int) vmR3PowerOff(PVM pVM);
    142136static void              vmR3DestroyUVM(PUVM pUVM, uint32_t cMilliesEMTWait);
    143137static void              vmR3AtDtor(PVM pVM);
    144 static DECLCALLBACK(int) vmR3Reset(PVM pVM);
     138static bool              vmR3ValidateStateTransition(VMSTATE enmStateOld, VMSTATE enmStateNew);
     139static void              vmR3DoAtState(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld);
     140static bool              vmR3TrySetState(PVM pVM, VMSTATE enmStateNew, VMSTATE enmStateOld);
     141static unsigned          vmR3TrySetState2(PVM pVM, VMSTATE enmStateNew1, VMSTATE enmStateOld1, VMSTATE enmStateNew2, VMSTATE enmStateOld2);
     142static void              vmR3SetStateLocked(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld);
     143static void              vmR3SetState(PVM pVM, VMSTATE enmStateNew, VMSTATE enmStateOld);
     144static unsigned          vmR3SetState2(PVM pVM, VMSTATE enmStateNew1, VMSTATE enmStateOld1, VMSTATE enmStateNew2, VMSTATE enmStateOld2);
    145145static int               vmR3SetErrorU(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
    146146
     
    241241             */
    242242            PVMREQ pReq;
    243             rc = VMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3CreateU, 4,
    244                               pUVM, cCpus, pfnCFGMConstructor, pvUserCFGM);
     243            rc = VMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     244                              (PFNRT)vmR3CreateU, 4, pUVM, cCpus, pfnCFGMConstructor, pvUserCFGM);
    245245            if (RT_SUCCESS(rc))
    246246            {
     
    258258            }
    259259            else
    260                 AssertMsgFailed(("VMR3ReqCall failed rc=%Rrc\n", rc));
     260                AssertMsgFailed(("VMR3ReqCallU failed rc=%Rrc\n", rc));
    261261
    262262            /*
     
    674674                                         * Set the state and link into the global list.
    675675                                         */
    676                                         vmR3SetState(pVM, VMSTATE_CREATED);
     676                                        vmR3SetState(pVM, VMSTATE_CREATED, VMSTATE_CREATING);
    677677                                        pUVM->pNext = g_pUVMsHead;
    678678                                        g_pUVMsHead = pUVM;
     
    765765    {
    766766        PVMREQ pReq;
    767         rc = VMR3ReqCallU(pUVM, idCpu, &pReq, RT_INDEFINITE_WAIT, 0 /*fFlags*/,
     767        rc = VMR3ReqCallU(pUVM, idCpu, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
    768768                          (PFNRT)vmR3RegisterEMT, 2, pVM, idCpu);
    769769        if (RT_SUCCESS(rc))
     
    11431143 * @returns VBox error code on failure.
    11441144 * @param   pVM         VM to power on.
    1145  * @thread      Any thread.
    1146  * @vmstate     Created
    1147  * @vmstateto   Running
    1148  */
    1149 VMMR3DECL(int)   VMR3PowerOn(PVM pVM)
    1150 {
    1151     LogFlow(("VMR3PowerOn: pVM=%p\n", pVM));
    1152 
    1153     /*
    1154      * Validate input.
    1155      */
    1156     if (!pVM)
    1157     {
    1158         AssertMsgFailed(("Invalid VM pointer\n"));
    1159         return VERR_INVALID_PARAMETER;
    1160     }
    1161 
    1162     /*
    1163      * Request the operation in EMT (in order as VCPU 0 does all the work)
    1164      */
    1165     PVMREQ pReq;
    1166     int rc = VMR3ReqCall(pVM, VMCPUID_ALL, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3PowerOn, 1, pVM);
    1167     if (RT_SUCCESS(rc))
    1168     {
    1169         rc = pReq->iStatus;
    1170         VMR3ReqFree(pReq);
    1171     }
    1172 
    1173     LogFlow(("VMR3PowerOn: returns %Rrc\n", rc));
    1174     return rc;
    1175 }
    1176 
    1177 
    1178 /**
    1179  * Power on the virtual machine.
    1180  *
    1181  * @returns 0 on success.
    1182  * @returns VBox error code on failure.
    1183  * @param   pVM         VM to power on.
    11841145 * @thread  EMT
    11851146 */
     
    11991160
    12001161    /*
    1201      * Validate input.
    1202      */
    1203     if (pVM->enmVMState != VMSTATE_CREATED)
    1204     {
    1205         AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
    1206         return VERR_VM_INVALID_VM_STATE;
    1207     }
     1162     * Try change the state.
     1163     */
     1164    AssertMsgReturn(vmR3TrySetState(pVM, VMSTATE_POWERING_ON, VMSTATE_CREATED),
     1165                    ("%s\n", VMR3GetStateName(pVM->enmVMState)),
     1166                    VERR_VM_INVALID_VM_STATE);
    12081167
    12091168    /*
    12101169     * Change the state, notify the components and resume the execution.
    12111170     */
    1212     vmR3SetState(pVM, VMSTATE_RUNNING);
    12131171    PDMR3PowerOn(pVM);
     1172    vmR3SetState(pVM, VMSTATE_RUNNING, VMSTATE_POWERING_ON);
    12141173
    12151174    return VINF_SUCCESS;
     
    12181177
    12191178/**
     1179 * Powers on the virtual machine.
     1180 *
     1181 * @returns VBox status code.
     1182 *
     1183 * @param   pVM         The VM to power on.
     1184 *
     1185 * @thread      Any thread.
     1186 * @vmstate     Created
     1187 * @vmstateto   PoweringOn, Running
     1188 */
     1189VMMR3DECL(int) VMR3PowerOn(PVM pVM)
     1190{
     1191    LogFlow(("VMR3PowerOn: pVM=%p\n", pVM));
     1192    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     1193
     1194    /*
     1195     * Forward the request to the EMTs (EMT(0) first as it does all the
     1196     * work upfront).
     1197     */
     1198    PVMREQ pReq;
     1199    int rc = VMR3ReqCallU(pVM->pUVM, VMCPUID_ALL, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     1200                          (PFNRT)vmR3PowerOn, 1, pVM);
     1201    if (RT_SUCCESS(rc))
     1202    {
     1203        rc = pReq->iStatus;
     1204        VMR3ReqFree(pReq);
     1205    }
     1206
     1207    LogFlow(("VMR3PowerOn: returns %Rrc\n", rc));
     1208    return rc;
     1209}
     1210
     1211
     1212/**
     1213 * EMT worker for vmR3SuspendCommon.
     1214 *
     1215 * @returns VBox strict status code.
     1216 * @retval  VINF_EM_SUSPEND.
     1217 * @retval  VERR_VM_INVALID_VM_STATE.
     1218 *
     1219 * @param   pVM     VM to suspend.
     1220 * @param   fFatal  Whether it's a fatal error or normal suspend.
     1221 *
     1222 * @thread  EMT
     1223 */
     1224static DECLCALLBACK(int) vmR3Suspend(PVM pVM, bool fFatal)
     1225{
     1226    LogFlow(("vmR3Suspend: pVM=%p\n", pVM));
     1227
     1228    /*
     1229     * The first EMT switches the state to suspending.
     1230     */
     1231    PVMCPU pVCpu = VMMGetCpu(pVM);
     1232    if (pVCpu->idCpu == pVM->cCpus - 1)
     1233        AssertMsgReturn(vmR3TrySetState2(pVM,
     1234                                         VMSTATE_SUSPENDING, VMSTATE_RUNNING,
     1235                                         VMSTATE_SUSPENDING_LS, VMSTATE_RUNNING_LS),
     1236                        ("%s\n", VMR3GetStateName(pVM->enmVMState)),
     1237                        VERR_VM_INVALID_VM_STATE);
     1238
     1239    VMSTATE enmVMState = pVM->enmVMState;
     1240    AssertMsgReturn(    enmVMState == VMSTATE_SUSPENDING
     1241                    ||  enmVMState == VMSTATE_SUSPENDING_LS,
     1242                    ("%s\n", VMR3GetStateName(enmVMState)),
     1243                    VERR_INTERNAL_ERROR_5);
     1244
     1245    /*
     1246     * EMT(0) does the actually suspending *after* all the other CPUs has
     1247     * been thru here.
     1248     */
     1249    if (pVCpu->idCpu == 0)
     1250    {
     1251        /* Perform suspend notification. */
     1252        PDMR3Suspend(pVM);
     1253
     1254        /* Change to the final state. */
     1255        if (pVM->enmVMState != VMSTATE_SUSPENDING_LS)
     1256            vmR3SetState(pVM, fFatal ? VMSTATE_FATAL_ERROR : VMSTATE_SUSPENDED, VMSTATE_SUSPENDING);
     1257        else if (!fFatal)
     1258            vmR3SetState(pVM, VMSTATE_SUSPENDED_LS, VMSTATE_SUSPENDING_LS);
     1259        else
     1260        {
     1261            vmR3SetState(pVM, VMSTATE_FATAL_ERROR_LS, VMSTATE_SUSPENDING_LS);
     1262            SSMR3Cancel(pVM);
     1263        }
     1264    }
     1265
     1266    return VINF_EM_SUSPEND;
     1267}
     1268
     1269
     1270/**
     1271 * Common worker for VMR3Suspend and vmR3SetRuntimeErrorCommon.
     1272 *
     1273 * They both suspends the VM, but the latter ends up in the VMSTATE_FATAL_ERROR
     1274 * instead of VMSTATE_SUSPENDED.
     1275 *
     1276 * @returns VBox strict status code.
     1277 * @param   pVM                 The VM handle.
     1278 * @param   fFatal              Whether it's a fatal error or not.
     1279 *
     1280 * @thread      Any thread.
     1281 * @vmstate     Running or RunningLS
     1282 * @vmstateto   Suspending + Suspended/FatalError or SuspendingLS +
     1283 *              SuspendedLS/FatalErrorLS
     1284 */
     1285static int vmR3SuspendCommon(PVM pVM, bool fFatal)
     1286{
     1287    /*
     1288     * Forward the operation to EMT in reverse order so EMT(0) can do the
     1289     * actual suspending after the other ones have stopped running guest code.
     1290     */
     1291    PVMREQ pReq;
     1292    int rc = VMR3ReqCallU(pVM->pUVM, VMCPUID_ALL_REVERSE, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     1293                          (PFNRT)vmR3Suspend, 2, pVM, fFatal);
     1294    if (RT_SUCCESS(rc))
     1295    {
     1296        rc = pReq->iStatus;
     1297        VMR3ReqFree(pReq);
     1298    }
     1299
     1300    return rc;
     1301}
     1302
     1303
     1304/**
    12201305 * Suspends a running VM.
    12211306 *
    1222  * @returns 0 on success.
    1223  * @returns VBox error code on failure.
    1224  * @param   pVM     VM to suspend.
     1307 * @returns VBox status code. When called on EMT, this will be a strict status
     1308 *          code that has to be propagated up the call stack.
     1309 *
     1310 * @param   pVM     The VM to suspend.
     1311 *
    12251312 * @thread      Any thread.
    1226  * @vmstate     Running
    1227  * @vmstateto   Suspended
     1313 * @vmstate     Running or RunningLS
     1314 * @vmstateto   Suspending + Suspended or SuspendingLS + SuspendedLS
    12281315 */
    12291316VMMR3DECL(int) VMR3Suspend(PVM pVM)
    12301317{
    12311318    LogFlow(("VMR3Suspend: pVM=%p\n", pVM));
    1232 
    1233     /*
    1234      * Validate input and pass it on to the internal worker.
    1235      */
    12361319    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    12371320    int rc = vmR3SuspendCommon(pVM, false /*fFatal*/);
    1238 
    12391321    LogFlow(("VMR3Suspend: returns %Rrc\n", rc));
    1240     return rc;
    1241 }
    1242 
    1243 
    1244 /**
    1245  * Common worker for VMR3Suspend and vmR3SetRuntimeErrorCommon.
    1246  *
    1247  * They both suspends the VM, but the latter ends up in the VMSTATE_FATAL_ERROR
    1248  * instead of VMSTATE_SUSPENDED.
    1249  *
    1250  * @returns VBox status code.
    1251  * @param   pVM                 The VM handle.
    1252  * @param   fFatal              Whether it's a fatal error or not.
    1253  *
    1254  * @thread      Any thread.
    1255  * @vmstate     Running
    1256  * @vmstateto   Suspended, FatalError
    1257  */
    1258 static int vmR3SuspendCommon(PVM pVM, bool fFatal)
    1259 {
    1260     /*
    1261      * Request the operation in EMT. (in reverse order as VCPU 0 does the actual work)
    1262      */
    1263     PVMREQ pReq = NULL;
    1264     int rc = VMR3ReqCall(pVM, VMCPUID_ALL_REVERSE, &pReq, RT_INDEFINITE_WAIT,
    1265                          (PFNRT)vmR3Suspend, 2, pVM, fFatal);
    1266     if (RT_SUCCESS(rc))
    1267     {
    1268         rc = pReq->iStatus;
    1269         VMR3ReqFree(pReq);
    1270     }
    1271     else
    1272         Assert(pReq == NULL);
    1273 
    1274     return rc;
    1275 }
    1276 
    1277 
    1278 /**
    1279  * Suspends a running VM.
    1280  *
    1281  * @returns 0 on success.
    1282  * @returns VBox error code on failure.
    1283  * @param   pVM     VM to suspend.
    1284  * @param   fFatal  Whether it's a fatal error or normal suspend.
    1285  * @thread  EMT
    1286  */
    1287 static DECLCALLBACK(int) vmR3Suspend(PVM pVM, bool fFatal)
    1288 {
    1289     LogFlow(("vmR3Suspend: pVM=%p\n", pVM));
    1290 
    1291     /*
    1292      * Validate input.
    1293      */
    1294     if (pVM->enmVMState != VMSTATE_RUNNING)
    1295     {
    1296         AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
    1297         return VERR_VM_INVALID_VM_STATE;
    1298     }
    1299 
    1300     PVMCPU pVCpu = VMMGetCpu(pVM);
    1301     /* Only VCPU 0 does the actual work (*after* all the other CPUs has been here). */
    1302     if (pVCpu->idCpu != 0)
    1303         return VINF_EM_SUSPEND;
    1304 
    1305     /*
    1306      * Change the state, notify the components and resume the execution.
    1307      */
    1308     vmR3SetState(pVM, fFatal ? VMSTATE_FATAL_ERROR : VMSTATE_SUSPENDED);
    1309     PDMR3Suspend(pVM);
    1310 
    1311     return VINF_EM_SUSPEND;
    1312 }
    1313 
    1314 
    1315 /**
    1316  * Resume VM execution.
    1317  *
    1318  * @returns 0 on success.
    1319  * @returns VBox error code on failure.
    1320  * @param   pVM         The VM to resume.
    1321  * @thread      Any thread.
    1322  * @vmstate     Suspended
    1323  * @vmstateto   Running
    1324  */
    1325 VMMR3DECL(int)   VMR3Resume(PVM pVM)
    1326 {
    1327     LogFlow(("VMR3Resume: pVM=%p\n", pVM));
    1328 
    1329     /*
    1330      * Validate input.
    1331      */
    1332     if (!pVM)
    1333     {
    1334         AssertMsgFailed(("Invalid VM pointer\n"));
    1335         return VERR_INVALID_PARAMETER;
    1336     }
    1337 
    1338     /*
    1339      * Request the operation in EMT. (in VCPU order as VCPU 0 does the actual work)
    1340      */
    1341     PVMREQ pReq = NULL;
    1342     int rc = VMR3ReqCall(pVM, VMCPUID_ALL, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Resume, 1, pVM);
    1343     if (RT_SUCCESS(rc))
    1344     {
    1345         rc = pReq->iStatus;
    1346         VMR3ReqFree(pReq);
    1347     }
    1348     else
    1349         Assert(pReq == NULL);
    1350 
    1351     LogFlow(("VMR3Resume: returns %Rrc\n", rc));
    13521322    return rc;
    13531323}
     
    13661336    LogFlow(("vmR3Resume: pVM=%p\n", pVM));
    13671337
     1338    /*
     1339     * EMT(0) does all the work *before* the others wake up.
     1340     */
    13681341    PVMCPU pVCpu = VMMGetCpu(pVM);
    1369     /* Only VCPU 0 does the actual work (*before* the others wake up). */
    1370     if (pVCpu->idCpu != 0)
    1371         return VINF_EM_RESUME;
     1342    if (pVCpu->idCpu == 0)
     1343    {
     1344        AssertMsgReturn(vmR3TrySetState(pVM, VMSTATE_RESUMING, VMSTATE_SUSPENDED),
     1345                        ("%s\n", VMR3GetStateName(pVM->enmVMState)),
     1346                        VERR_VM_INVALID_VM_STATE);
     1347
     1348        /* Perform resume notifications. */
     1349        PDMR3Resume(pVM);
     1350
     1351        /* Advance to the final state. */
     1352        vmR3SetState(pVM, VMSTATE_RUNNING, VMSTATE_RESUMING);
     1353    }
     1354
     1355    /** @todo there is a race here: Someone could suspend, power off, raise a fatal
     1356     *        error (both kinds), save the vm, or start a live save operation before
     1357     *        we get here on all CPUs. Only safe way is a cross call, or to make
     1358     *        the last thread flip the state from Resuming to Running. While the
     1359     *        latter seems easy and perhaps more attractive, the former might be
     1360     *        better wrt TSC/TM... */
     1361    AssertMsgReturn(pVM->enmVMState == VMSTATE_RUNNING, ("%s\n", VMR3GetStateName(pVM->enmVMState)), VERR_VM_INVALID_VM_STATE);
     1362    return VINF_EM_RESUME;
     1363}
     1364
     1365
     1366
     1367
     1368/**
     1369 * Resume VM execution.
     1370 *
     1371 * @returns VBox status code. When called on EMT, this will be a strict status
     1372 *          code that has to be propagated up the call stack.
     1373 *
     1374 * @param   pVM         The VM to resume.
     1375 *
     1376 * @thread      Any thread.
     1377 * @vmstate     Suspended
     1378 * @vmstateto   Running
     1379 */
     1380VMMR3DECL(int) VMR3Resume(PVM pVM)
     1381{
     1382    LogFlow(("VMR3Resume: pVM=%p\n", pVM));
     1383    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     1384
     1385    /*
     1386     * Forward the request to the EMTs (EMT(0) first as it does all the
     1387     * work upfront).
     1388     */
     1389    PVMREQ pReq;
     1390    int rc = VMR3ReqCallU(pVM->pUVM, VMCPUID_ALL, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     1391                          (PFNRT)vmR3Resume, 1, pVM);
     1392    if (RT_SUCCESS(rc))
     1393    {
     1394        rc = pReq->iStatus;
     1395        VMR3ReqFree(pReq);
     1396    }
     1397
     1398    LogFlow(("VMR3Resume: returns %Rrc\n", rc));
     1399    return rc;
     1400}
     1401
     1402
     1403/**
     1404 * Worker for VMR3Save that validates the state and calls SSMR3Save.
     1405 *
     1406 * @returns VBox status code.
     1407 *
     1408 * @param   pVM             The VM handle.
     1409 * @param   pszFilename     The name of the save state file.
     1410 * @param   enmAfter        What to do afterwards.
     1411 * @param   pfnProgress     Progress callback. Optional.
     1412 * @param   pvUser          User argument for the progress callback.
     1413 * @param   ppSSM           Where to return the saved state handle in case of a
     1414 *                          live snapshot scenario.
     1415 * @thread  EMT
     1416 */
     1417static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
     1418{
     1419    LogFlow(("vmR3Save: pVM=%p pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p ppSSM=%p\n", pVM, pszFilename, pszFilename, enmAfter, pfnProgress, pvUser, ppSSM));
    13721420
    13731421    /*
    13741422     * Validate input.
    13751423     */
    1376     if (pVM->enmVMState != VMSTATE_SUSPENDED)
    1377     {
    1378         AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
    1379         return VERR_VM_INVALID_VM_STATE;
    1380     }
    1381 
    1382     /*
    1383      * Change the state, notify the components and resume the execution.
    1384      */
    1385     pVM->vm.s.fPreventSaveState = false;
    1386     vmR3SetState(pVM, VMSTATE_RUNNING);
    1387     PDMR3Resume(pVM);
    1388 
    1389     return VINF_EM_RESUME;
     1424    AssertPtr(pszFilename);
     1425    AssertPtr(pVM);
     1426    Assert(enmAfter == SSMAFTER_DESTROY || enmAfter == SSMAFTER_CONTINUE);
     1427    AssertPtr(ppSSM);
     1428    *ppSSM = NULL;
     1429
     1430    /*
     1431     * Change the state and perform/start the saving.
     1432     */
     1433    int rc;
     1434    if (vmR3TrySetState(pVM, VMSTATE_SAVING, VMSTATE_SUSPENDED))
     1435    {
     1436        rc = SSMR3Save(pVM, pszFilename, enmAfter, pfnProgress, pvUser);
     1437        vmR3SetState(pVM, VMSTATE_SUSPENDED, VMSTATE_SAVING);
     1438    }
     1439    else if (vmR3TrySetState(pVM, VMSTATE_RUNNING, VMSTATE_RUNNING_LS))
     1440    {
     1441        rc = SSMR3LiveToFile(pVM, pszFilename, enmAfter, pfnProgress, pvUser, ppSSM);
     1442        /* (We're not subject to cancellation just yet.) */
     1443    }
     1444
     1445    return rc;
     1446}
     1447
     1448
     1449/**
     1450 * Worker for VMR3Save continues a live save on EMT(0).
     1451 *
     1452 * @returns VBox status code.
     1453 *
     1454 * @param   pVM             The VM handle.
     1455 * @param   pSSM            The handle of saved state operation.
     1456 * @thread  EMT(0)
     1457 */
     1458static DECLCALLBACK(int) vmR3SaveLiveStep2(PVM pVM, PSSMHANDLE pSSM)
     1459{
     1460    LogFlow(("vmR3SaveLiveStep2: pVM=%p pSSM=%p\n", pVM, pSSM));
     1461    VM_ASSERT_EMT0(pVM);
     1462    Assert(pVM->enmVMState == VMSTATE_SUSPENDED_LS);
     1463
     1464    int rc = SSMR3LiveDoStep2(pSSM);
     1465    vmR3SetState(pVM, VMSTATE_SUSPENDED, VMSTATE_SUSPENDED_LS);
     1466
     1467    return rc;
    13901468}
    13911469
     
    13961474 * Can be used for both saving the state and creating snapshots.
    13971475 *
    1398  * When called for a VM in the RUNNING state, the saved state is created live
     1476 * When called for a VM in the Running state, the saved state is created live
    13991477 * and the VM is only suspended when the final part of the saving is preformed.
    1400  * The VM state will not be restored to RUNNING in this case and it's up to the
     1478 * The VM state will not be restored to Running in this case and it's up to the
    14011479 * caller to call VMR3Resume if this is desirable.  (The rational is that the
    14021480 * caller probably wish to reconfigure the disks before resuming the VM.)
     
    14041482 * @returns VBox status code.
    14051483 *
    1406  * @param   pVM                 VM which state should be saved.
    1407  * @param   pszFilename         Name of the save state file.
    1408  * @param   fContinueAfterwards Continue execution afterwards. When in doubt,
    1409  *                              set this to true.
     1484 * @param   pVM                 The VM which state should be saved.
     1485 * @param   pszFilename         The name of the save state file.
     1486 * @param   fContinueAfterwards Whether continue execution afterwards or not.
     1487 *                              When in doubt, set this to true.
    14101488 * @param   pfnProgress         Progress callback. Optional.
    14111489 * @param   pvUser              User argument for the progress callback.
    14121490 *
    1413  * @thread      Any thread. Will forward the request to EMT(0).
    1414  * @vmstate     Suspended, Running
    1415  * @vmstateto   Suspended.
     1491 * @thread      Non-EMT.
     1492 * @vmstate     Suspended or Running
     1493 * @vmstateto   Saving+Suspended or
     1494 *              RunningLS+SuspeningLS+SuspendedLS+Saving+Suspended.
    14161495 */
    14171496VMMR3DECL(int) VMR3Save(PVM pVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser)
     
    14241503     */
    14251504    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     1505    VM_ASSERT_OTHER_THREAD(pVM);
    14261506    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
    14271507    AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
     
    14341514    PSSMHANDLE  pSSM;
    14351515    PVMREQ      pReq;
    1436     int rc = VMR3ReqCall(pVM, 0 /* VCPU 0 */, &pReq, RT_INDEFINITE_WAIT,
    1437                          (PFNRT)vmR3Save, 6, pVM, pszFilename, enmAfter, pfnProgress, pvUser, &pSSM);
     1516    int rc = VMR3ReqCallU(pVM->pUVM, 0 /*idDstCpu*/, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     1517                          (PFNRT)vmR3Save, 6, pVM, pszFilename, enmAfter, pfnProgress, pvUser, &pSSM);
    14381518    if (RT_SUCCESS(rc))
    14391519    {
     
    14441524        &&  pSSM)
    14451525    {
    1446 #if 1
    1447         /**@todo*/ rc = VERR_NOT_IMPLEMENTED;
    1448 #else
     1526#if 0 /** @todo later*/
    14491527        /*
    14501528         * Live snapshot.
     
    14531531        if (RT_SUCCESS(rc))
    14541532        {
    1455             rc = VMR3ReqCall(pVM, 0 /* VCPU 0 */, &pReq, RT_INDEFINITE_WAIT,
    1456                              (PFNRT)vmR3SaveLive, 2, pVM, pSSM);
     1533            rc = vmR3SuspendCommon(pVM, false /*fFatal*/);
    14571534            if (RT_SUCCESS(rc))
    14581535            {
    1459                 rc = pReq->iStatus;
    1460                 VMR3ReqFree(pReq);
     1536                rc = VMR3ReqCallU(pVM->pUVM, 0 /*idDstCpu*/, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     1537                                  (PFNRT)vmR3SaveLiveStep2, 2, pVM, pSSM);
     1538                if (RT_SUCCESS(rc))
     1539                {
     1540                    rc = pReq->iStatus;
     1541                    VMR3ReqFree(pReq);
     1542                }
    14611543            }
    14621544        }
     1545        else
     1546            AssertLogRelMsg(   pVM->enmVMState == VMSTATE_RUNNING_LS
     1547                            || pVM->enmVMState == VMSTATE_RESETTING_LS
     1548                            || pVM->enmVMState == VMSTATE_POWERING_OFF_LS
     1549                            || pVM->enmVMState == VMSTATE_FATAL_ERROR_LS
     1550                            || pVM->enmVMState == VMSTATE_GURU_MEDITATION_LS,
     1551                            ("%s rc=%Rrc\n", pVM->enmVMState, rc));
     1552
     1553        int rc2 = SSMR3LiveDone(pSSM);
     1554        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     1555            rc = rc2;
     1556
     1557        /*
     1558         * Work the state.
     1559         */
     1560        if (pVM->enmVMState == VMSTATE_SUSPENDED)
     1561            Log(("VMR3Save: Suspended; rc=%Rrc\n", rc));
     1562        else if (vmR3TrySetState(pVM, VMSTATE_RUNNING, VMSTATE_RUNNING_LS))
     1563            Log(("VMR3Save: Cancelled while running; rc=%Rrc\n", rc));
     1564        else if (vmR3TrySetState(pVM, VMSTATE_SUSPEND, VMSTATE_SUSPEND_LS))
     1565            Log(("VMR3Save: Cancelled while suspended; rc=%Rrc\n", rc));
     1566        else if (vmR3TrySetState(pVM, VMSTATE_POWERING_OFF, VMSTATE_POWERING_OFF_LS))
     1567        {
     1568            /** @todo needs more work. */
     1569            Log(("VMR3Save: Powering off; rc=%Rrc\n", rc));
     1570        }
     1571        else if (vmR3TrySetState(pVM, VMSTATE_RESETTING, VMSTATE_RESETTING_LS))
     1572        {
     1573            /** @todo needs more work. */
     1574            Log(("VMR3Save: Resetting; rc=%Rrc\n", rc));
     1575        }
     1576        else if (vmR3TrySetState(pVM, VMSTATE_FATAL_ERROR, VMSTATE_FATAL_ERROR_LS))
     1577            Log(("VMR3Save: Fatal error; rc=%Rrc\n", rc));
     1578        else if (vmR3TrySetState(pVM, VMSTATE_GURU_MEDITATION, VMSTATE_GURU_MEDITATION_LS))
     1579            Log(("VMR3Save: Guru meditation; rc=%Rrc\n", rc));
     1580        else
     1581        {
     1582            AssertLogRelMsgFailed(("%s rc=%Rrc\n", pVM->enmVMState, rc));
     1583            rc = VERR_INTERNAL_ERROR_4;
     1584        }
     1585#else
     1586        rc = VERR_NOT_IMPLEMENTED;
     1587        SSMR3LiveDone(pSSM);
    14631588#endif
    14641589    }
     
    14701595
    14711596/**
    1472  * Worker for VMR3Save that validates the state and calls SSMR3Save.
    1473  *
    1474  * @returns 0 on success.
    1475  * @returns VBox error code on failure.
    1476  * @param   pVM             VM which state should be saved.
    1477  * @param   pszFilename     Name of the save state file.
    1478  * @param   enmAfter        What to do afterwards.
    1479  * @param   pfnProgress     Progress callback. Optional.
    1480  * @param   pvUser          User argument for the progress callback.
    1481  * @param   ppSSM           Where to return the saved state handle in case of a
    1482  *                          live snapshot scenario.
    1483  * @thread  EMT
    1484  */
    1485 static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
    1486 {
    1487     LogFlow(("vmR3Save: pVM=%p pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p ppSSM=%p\n", pVM, pszFilename, pszFilename, enmAfter, pfnProgress, pvUser, ppSSM));
    1488 
    1489     /*
    1490      * Validate input.
    1491      */
    1492     /** @todo SMP: Check that vmR3SetState always done by EMT(0). If not add a vmR3TrySetState(). */
    1493     *ppSSM = NULL;
    1494     AssertMsgReturn(   pVM->enmVMState == VMSTATE_SUSPENDED
    1495                     || pVM->enmVMState == VMSTATE_RUNNING,
    1496                     ("%d\n", pVM->enmVMState),
    1497                     VERR_VM_INVALID_VM_STATE);
    1498 
    1499     /* If we are in an inconsistent state, then we don't allow state saving. */
    1500     if (pVM->vm.s.fPreventSaveState)    /** @todo Incorporate VMINT::fPreventSaveState into the VMSTATE. There is a defect for this. */
    1501     {
    1502         LogRel(("VMM: vmR3Save: saving the VM state is not allowed at this moment\n"));
    1503         return VERR_VM_SAVE_STATE_NOT_ALLOWED;
    1504     }
    1505 
    1506     /*
    1507      * Change the state and perform/start the saveing.
    1508      */
    1509     int rc;
    1510     if (pVM->enmVMState == VMSTATE_RUNNING)
    1511     {
    1512         /** @todo state mess. */
    1513         rc = SSMR3LiveToFile(pVM, pszFilename, enmAfter, pfnProgress, pvUser, ppSSM);
    1514     }
    1515     else
    1516     {
    1517         vmR3SetState(pVM, VMSTATE_SAVING); /** @todo Should probably use a different state for live snapshots and/or live migration. Will fix the state machine later. */
    1518         rc = SSMR3Save(pVM, pszFilename, enmAfter, pfnProgress, pvUser);
    1519         vmR3SetState(pVM, VMSTATE_SUSPENDED);
    1520     }
    1521 
    1522     return rc;
    1523 }
    1524 
    1525 
    1526 /**
    15271597 * Loads a new VM state.
    15281598 *
     
    15301600 * resume the VM instead of powering it on.
    15311601 *
    1532  * @returns 0 on success.
    1533  * @returns VBox error code on failure.
    1534  * @param   pVM             VM which state should be saved.
    1535  * @param   pszFilename     Name of the save state file.
    1536  * @param   pfnProgress     Progress callback. Optional.
    1537  * @param   pvUser          User argument for the progress callback.
    1538  * @thread      Any thread.
    1539  * @vmstate     Created, Suspended
    1540  * @vmstateto   Suspended
    1541  */
    1542 VMMR3DECL(int)   VMR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
    1543 {
    1544     LogFlow(("VMR3Load: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
    1545 
    1546     /*
    1547      * Validate input.
    1548      */
    1549     if (!pVM)
    1550     {
    1551         AssertMsgFailed(("Invalid VM pointer\n"));
    1552         return VERR_INVALID_PARAMETER;
    1553     }
    1554     if (!pszFilename)
    1555     {
    1556         AssertMsgFailed(("Must specify a filename to load the state from, wise guy!\n"));
    1557         return VERR_INVALID_PARAMETER;
    1558     }
    1559 
    1560     /*
    1561      * Request the operation in EMT.
    1562      */
    1563     PVMREQ pReq;
    1564     int rc = VMR3ReqCall(pVM, 0 /* VCPU 0 */, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Load, 4, pVM, pszFilename, pfnProgress, pvUser);
    1565     if (RT_SUCCESS(rc))
    1566     {
    1567         rc = pReq->iStatus;
    1568         VMR3ReqFree(pReq);
    1569     }
    1570 
    1571     LogFlow(("VMR3Load: returns %Rrc\n", rc));
    1572     return rc;
    1573 }
    1574 
    1575 
    1576 /**
    1577  * Loads a new VM state.
    1578  *
    1579  * To restore a saved state on VM startup, call this function and then
    1580  * resume the VM instead of powering it on.
    1581  *
    1582  * @returns 0 on success.
    1583  * @returns VBox error code on failure.
    1584  * @param   pVM             VM which state should be saved.
    1585  * @param   pszFilename     Name of the save state file.
     1602 * @returns VBox status code.
     1603 * @param   pVM             The VM handle.
     1604 * @param   pszFilename     The name of the save state file.
    15861605 * @param   pfnProgress     Progress callback. Optional.
    15871606 * @param   pvUser          User argument for the progress callback.
     
    15931612
    15941613    /*
    1595      * Validate input.
    1596      */
    1597     if (    pVM->enmVMState != VMSTATE_SUSPENDED
    1598         &&  pVM->enmVMState != VMSTATE_CREATED)
    1599     {
    1600         AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
     1614     * Validate input (paranoia).
     1615     */
     1616    AssertPtr(pVM);
     1617    AssertPtr(pszFilename);
     1618
     1619    /*
     1620     * Change the state and perform the load.
     1621     *
     1622     * Always perform a relocation round afterwards to make sure hypervisor
     1623     * selectors and such are correct.
     1624     */
     1625    if (!vmR3TrySetState2(pVM,
     1626                          VMSTATE_LOADING, VMSTATE_CREATED,
     1627                          VMSTATE_LOADING, VMSTATE_SUSPENDED))
    16011628        return VMSetError(pVM, VERR_VM_INVALID_VM_STATE, RT_SRC_POS, N_("Invalid VM state (%s) for restoring state from '%s'"),
    16021629                          VMR3GetStateName(pVM->enmVMState), pszFilename);
    1603     }
    1604 
    1605     /*
    1606      * Change the state and perform the load.
    1607      */
    1608     vmR3SetState(pVM, VMSTATE_LOADING);
     1630
    16091631    int rc = SSMR3Load(pVM, pszFilename, SSMAFTER_RESUME, pfnProgress,  pvUser);
    16101632    if (RT_SUCCESS(rc))
    16111633    {
    1612         /* Not paranoia anymore; the saved guest might use different hypervisor selectors. We must call VMR3Relocate. */
    1613         VMR3Relocate(pVM, 0);
    1614         vmR3SetState(pVM, VMSTATE_SUSPENDED);
     1634        VMR3Relocate(pVM, 0 /*offDelta*/);
     1635        vmR3SetState(pVM, VMSTATE_SUSPENDED, VMSTATE_LOADING);
    16151636    }
    16161637    else
    16171638    {
    1618         vmR3SetState(pVM, VMSTATE_LOAD_FAILURE);
    1619         rc = VMSetError(pVM, rc, RT_SRC_POS, N_("Unable to restore the virtual machine's saved state from '%s'.  It may be damaged or from an older version of VirtualBox.  Please discard the saved state before starting the virtual machine"), pszFilename);
     1639        vmR3SetState(pVM, VMSTATE_LOAD_FAILURE, VMSTATE_LOADING);
     1640        rc = VMSetError(pVM, rc, RT_SRC_POS,
     1641                        N_("Unable to restore the virtual machine's saved state from '%s'.  It may be damaged or from an older version of VirtualBox.  Please discard the saved state before starting the virtual machine"),
     1642                        pszFilename);
    16201643    }
    16211644
    16221645    return rc;
     1646}
     1647
     1648
     1649/**
     1650 * Loads a VM state into a newly created VM or a one that is suspended.
     1651 *
     1652 * To restore a saved state on VM startup, call this function and then resume
     1653 * the VM instead of powering it on.
     1654 *
     1655 * @returns VBox status code.
     1656 *
     1657 * @param   pVM             The VM handle.
     1658 * @param   pszFilename     The name of the save state file.
     1659 * @param   pfnProgress     Progress callback. Optional.
     1660 * @param   pvUser          User argument for the progress callback.
     1661 *
     1662 * @thread      Any thread.
     1663 * @vmstate     Created, Suspended
     1664 * @vmstateto   Loading+Suspended
     1665 */
     1666VMMR3DECL(int) VMR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
     1667{
     1668    LogFlow(("VMR3Load: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
     1669
     1670    /*
     1671     * Validate input.
     1672     */
     1673    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     1674    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
     1675
     1676    /*
     1677     * Request the operation in EMT.
     1678     */
     1679    PVMREQ pReq;
     1680    int rc = VMR3ReqCallU(pVM->pUVM, 0 /*idDstCpu*/, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     1681                          (PFNRT)vmR3Load, 4, pVM, pszFilename, pfnProgress, pvUser);
     1682    if (RT_SUCCESS(rc))
     1683    {
     1684        rc = pReq->iStatus;
     1685        VMR3ReqFree(pReq);
     1686    }
     1687
     1688    LogFlow(("VMR3Load: returns %Rrc\n", rc));
     1689    return rc;
     1690}
     1691
     1692
     1693/**
     1694 * Worker for VMR3PowerOff that does the actually powering off on EMT(0) after
     1695 * cycling thru the other EMTs first.
     1696 *
     1697 * @returns VBox status code.
     1698 *
     1699 * @param   pVM     The VM handle.
     1700 *
     1701 * @thread      EMT.
     1702 */
     1703static DECLCALLBACK(int) vmR3PowerOff(PVM pVM)
     1704{
     1705    LogFlow(("vmR3PowerOff: pVM=%p\n", pVM));
     1706
     1707    /*
     1708     * The first EMT thru here will change the state to PoweringOff.
     1709     */
     1710    PVMCPU pVCpu = VMMGetCpu(pVM);
     1711    if (pVCpu->idCpu == pVM->cCpus - 1)
     1712    {
     1713        PUVM pUVM = pVM->pUVM;
     1714        RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);
     1715
     1716        VMSTATE enmStateNew;
     1717        VMSTATE enmStateOld = pVM->enmVMState;
     1718        switch (enmStateOld)
     1719        {
     1720            case VMSTATE_RUNNING:
     1721            case VMSTATE_SUSPENDED:
     1722            case VMSTATE_DEBUGGING:
     1723            case VMSTATE_LOAD_FAILURE:
     1724            case VMSTATE_GURU_MEDITATION:
     1725            case VMSTATE_FATAL_ERROR:
     1726                enmStateNew = VMSTATE_POWERING_OFF;
     1727                break;
     1728
     1729            case VMSTATE_RUNNING_LS:
     1730            case VMSTATE_DEBUGGING_LS:
     1731            case VMSTATE_GURU_MEDITATION_LS:
     1732            case VMSTATE_FATAL_ERROR_LS:
     1733                enmStateNew = VMSTATE_POWERING_OFF_LS;
     1734                break;
     1735
     1736            default:
     1737                AssertLogRelMsgFailed(("%s\n", VMR3GetStateName(enmStateOld)));
     1738                RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     1739                return VERR_VM_INVALID_VM_STATE;
     1740        }
     1741
     1742        vmR3SetStateLocked(pVM, pUVM, enmStateNew, enmStateOld);
     1743        RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     1744    }
     1745
     1746    /*
     1747     * Check the state.
     1748     */
     1749    VMSTATE const enmVMState = pVM->enmVMState;
     1750    AssertMsgReturn(   enmVMState == VMSTATE_POWERING_OFF
     1751                    || enmVMState == VMSTATE_POWERING_OFF_LS,
     1752                    ("%s\n", VMR3GetStateName(enmVMState)),
     1753                    VERR_VM_INVALID_VM_STATE);
     1754
     1755    /*
     1756     * EMT(0) does the actual power off work here *after* all the other EMTs
     1757     * have been thru and entered the STOPPED state.
     1758     */
     1759    VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STOPPED);
     1760    if (pVCpu->idCpu == 0)
     1761    {
     1762        /*
     1763         * For debugging purposes, we will log a summary of the guest state at this point.
     1764         */
     1765        if (enmVMState != VMSTATE_GURU_MEDITATION)
     1766        {
     1767            /** @todo SMP support? */
     1768            PVMCPU pVCpu = VMMGetCpu(pVM);
     1769
     1770            /** @todo make the state dumping at VMR3PowerOff optional. */
     1771            RTLogRelPrintf("****************** Guest state at power off ******************\n");
     1772            DBGFR3Info(pVM, "cpumguest", "verbose", DBGFR3InfoLogRelHlp());
     1773            RTLogRelPrintf("***\n");
     1774            DBGFR3Info(pVM, "mode", NULL, DBGFR3InfoLogRelHlp());
     1775            RTLogRelPrintf("***\n");
     1776            DBGFR3Info(pVM, "activetimers", NULL, DBGFR3InfoLogRelHlp());
     1777            RTLogRelPrintf("***\n");
     1778            DBGFR3Info(pVM, "gdt", NULL, DBGFR3InfoLogRelHlp());
     1779            /** @todo dump guest call stack. */
     1780#if 1 // "temporary" while debugging #1589
     1781            RTLogRelPrintf("***\n");
     1782            uint32_t esp = CPUMGetGuestESP(pVCpu);
     1783            if (    CPUMGetGuestSS(pVCpu) == 0
     1784                &&  esp < _64K)
     1785            {
     1786                uint8_t abBuf[PAGE_SIZE];
     1787                RTLogRelPrintf("***\n"
     1788                               "ss:sp=0000:%04x ", esp);
     1789                uint32_t Start = esp & ~(uint32_t)63;
     1790                int rc = PGMPhysSimpleReadGCPhys(pVM, abBuf, Start, 0x100);
     1791                if (RT_SUCCESS(rc))
     1792                    RTLogRelPrintf("0000:%04x TO 0000:%04x:\n"
     1793                                   "%.*Rhxd\n",
     1794                                   Start, Start + 0x100 - 1,
     1795                                   0x100, abBuf);
     1796                else
     1797                    RTLogRelPrintf("rc=%Rrc\n", rc);
     1798
     1799                /* grub ... */
     1800                if (esp < 0x2000 && esp > 0x1fc0)
     1801                {
     1802                    rc = PGMPhysSimpleReadGCPhys(pVM, abBuf, 0x8000, 0x800);
     1803                    if (RT_SUCCESS(rc))
     1804                        RTLogRelPrintf("0000:8000 TO 0000:87ff:\n"
     1805                                       "%.*Rhxd\n",
     1806                                       0x800, abBuf);
     1807                }
     1808                /* microsoft cdrom hang ... */
     1809                if (true)
     1810                {
     1811                    rc = PGMPhysSimpleReadGCPhys(pVM, abBuf, 0x8000, 0x200);
     1812                    if (RT_SUCCESS(rc))
     1813                        RTLogRelPrintf("2000:0000 TO 2000:01ff:\n"
     1814                                       "%.*Rhxd\n",
     1815                                       0x200, abBuf);
     1816                }
     1817            }
     1818#endif
     1819            RTLogRelPrintf("************** End of Guest state at power off ***************\n");
     1820        }
     1821
     1822        /*
     1823         * Perform the power off notifications and advance the state to
     1824         * Off or OffLS.
     1825         */
     1826        PDMR3PowerOff(pVM);
     1827        vmR3SetState2(pVM,
     1828                      VMSTATE_OFF,    VMSTATE_POWERING_OFF,
     1829                      VMSTATE_OFF_LS, VMSTATE_POWERING_OFF_LS);
     1830    }
     1831    return VINF_EM_OFF;
    16231832}
    16241833
     
    16511860     */
    16521861    PVMREQ pReq = NULL;
    1653     int rc = VMR3ReqCall(pVM, VMCPUID_ALL_REVERSE, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3PowerOff, 1, pVM);
     1862    int rc = VMR3ReqCallU(pVM->pUVM, VMCPUID_ALL_REVERSE, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     1863                          (PFNRT)vmR3PowerOff, 1, pVM);
    16541864    if (RT_SUCCESS(rc))
    16551865    {
     
    16661876
    16671877/**
    1668  * Power Off the VM.
    1669  *
    1670  * @returns 0 on success.
    1671  * @returns VBox error code on failure.
    1672  * @param   pVM     VM which should be destroyed.
    1673  * @thread      EMT.
    1674  */
    1675 static DECLCALLBACK(int) vmR3PowerOff(PVM pVM)
    1676 {
    1677     LogFlow(("vmR3PowerOff: pVM=%p\n", pVM));
    1678 
    1679     /*
    1680      * Validate input.
    1681      */
    1682     if (    pVM->enmVMState != VMSTATE_RUNNING
    1683         &&  pVM->enmVMState != VMSTATE_SUSPENDED
    1684         &&  pVM->enmVMState != VMSTATE_LOAD_FAILURE
    1685         &&  pVM->enmVMState != VMSTATE_FATAL_ERROR
    1686         &&  pVM->enmVMState != VMSTATE_GURU_MEDITATION)
    1687     {
    1688         AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
    1689         return VERR_VM_INVALID_VM_STATE;
    1690     }
    1691 
    1692     /*
    1693      * EMT(0) does the actual power off work here *after* all the other EMTs
    1694      * have been thru and entered the STOPPED state.
    1695      */
    1696     PVMCPU pVCpu = VMMGetCpu(pVM);
    1697     VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STOPPED);
    1698     if (pVCpu->idCpu != 0)
    1699         return VINF_EM_OFF;
    1700 
    1701     /*
    1702      * For debugging purposes, we will log a summary of the guest state at this point.
    1703      */
    1704     if (pVM->enmVMState != VMSTATE_GURU_MEDITATION)
    1705     {
    1706         /* @todo SMP support? */
    1707         PVMCPU pVCpu = VMMGetCpu(pVM);
    1708 
    1709         /** @todo make the state dumping at VMR3PowerOff optional. */
    1710         RTLogRelPrintf("****************** Guest state at power off ******************\n");
    1711         DBGFR3Info(pVM, "cpumguest", "verbose", DBGFR3InfoLogRelHlp());
    1712         RTLogRelPrintf("***\n");
    1713         DBGFR3Info(pVM, "mode", NULL, DBGFR3InfoLogRelHlp());
    1714         RTLogRelPrintf("***\n");
    1715         DBGFR3Info(pVM, "activetimers", NULL, DBGFR3InfoLogRelHlp());
    1716         RTLogRelPrintf("***\n");
    1717         DBGFR3Info(pVM, "gdt", NULL, DBGFR3InfoLogRelHlp());
    1718         /** @todo dump guest call stack. */
    1719 #if 1 // temporary while debugging #1589
    1720         RTLogRelPrintf("***\n");
    1721         uint32_t esp = CPUMGetGuestESP(pVCpu);
    1722         if (    CPUMGetGuestSS(pVCpu) == 0
    1723             &&  esp < _64K)
    1724         {
    1725             uint8_t abBuf[PAGE_SIZE];
    1726             RTLogRelPrintf("***\n"
    1727                            "ss:sp=0000:%04x ", esp);
    1728             uint32_t Start = esp & ~(uint32_t)63;
    1729             int rc = PGMPhysSimpleReadGCPhys(pVM, abBuf, Start, 0x100);
    1730             if (RT_SUCCESS(rc))
    1731                 RTLogRelPrintf("0000:%04x TO 0000:%04x:\n"
    1732                                "%.*Rhxd\n",
    1733                                Start, Start + 0x100 - 1,
    1734                                0x100, abBuf);
    1735             else
    1736                 RTLogRelPrintf("rc=%Rrc\n", rc);
    1737 
    1738             /* grub ... */
    1739             if (esp < 0x2000 && esp > 0x1fc0)
    1740             {
    1741                 rc = PGMPhysSimpleReadGCPhys(pVM, abBuf, 0x8000, 0x800);
    1742                 if (RT_SUCCESS(rc))
    1743                     RTLogRelPrintf("0000:8000 TO 0000:87ff:\n"
    1744                                    "%.*Rhxd\n",
    1745                                    0x800, abBuf);
    1746             }
    1747             /* microsoft cdrom hang ... */
    1748             if (true)
    1749             {
    1750                 rc = PGMPhysSimpleReadGCPhys(pVM, abBuf, 0x8000, 0x200);
    1751                 if (RT_SUCCESS(rc))
    1752                     RTLogRelPrintf("2000:0000 TO 2000:01ff:\n"
    1753                                    "%.*Rhxd\n",
    1754                                    0x200, abBuf);
    1755             }
    1756         }
    1757 #endif
    1758         RTLogRelPrintf("************** End of Guest state at power off ***************\n");
    1759     }
    1760 
    1761     /*
    1762      * Change the state to OFF and notify the components.
    1763      */
    1764     vmR3SetState(pVM, VMSTATE_OFF);
    1765     PDMR3PowerOff(pVM);
    1766 
    1767     return VINF_EM_OFF;
    1768 }
    1769 
    1770 
    1771 /**
    17721878 * Destroys the VM.
    1773  * The VM must be powered off (or never really powered on) to call this function.
    1774  * The VM handle is destroyed and can no longer be used up successful return.
     1879 *
     1880 * The VM must be powered off (or never really powered on) to call this
     1881 * function. The VM handle is destroyed and can no longer be used up successful
     1882 * return.
    17751883 *
    17761884 * @returns VBox status code.
    1777  * @param   pVM     VM which should be destroyed.
    1778  * @thread      Any thread but the emulation thread.
     1885 *
     1886 * @param   pVM     The handle of the VM which should be destroyed.
     1887 *
     1888 * @thread      EMT(0) or any none emulation thread.
    17791889 * @vmstate     Off, Created
    17801890 * @vmstateto   N/A
    17811891 */
    1782 VMMR3DECL(int)   VMR3Destroy(PVM pVM)
     1892VMMR3DECL(int) VMR3Destroy(PVM pVM)
    17831893{
    17841894    LogFlow(("VMR3Destroy: pVM=%p\n", pVM));
     
    17891899    if (!pVM)
    17901900        return VERR_INVALID_PARAMETER;
    1791     AssertPtrReturn(pVM, VERR_INVALID_POINTER);
    1792     AssertMsgReturn(   pVM->enmVMState == VMSTATE_OFF
    1793                     || pVM->enmVMState == VMSTATE_CREATED,
    1794                     ("Invalid VM state %d\n", pVM->enmVMState),
    1795                     VERR_VM_INVALID_VM_STATE);
     1901    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     1902    Assert(VMMGetCpuId(pVM) == 0 || VMMGetCpuId(pVM) == NIL_VMCPUID);
    17961903
    17971904    /*
    17981905     * Change VM state to destroying and unlink the VM.
    17991906     */
    1800     vmR3SetState(pVM, VMSTATE_DESTROYING);
     1907    AssertLogRelMsgReturn(vmR3TrySetState(pVM, VMSTATE_DESTROYING, VMSTATE_OFF),
     1908                          ("%s\n", VMR3GetStateName(pVM->enmVMState)),
     1909                          VERR_VM_INVALID_VM_STATE);
    18011910
    18021911    /** @todo lock this when we start having multiple machines in a process... */
     
    18171926    /*
    18181927     * Notify registered at destruction listeners.
    1819      * (That's the debugger console.)
    18201928     */
    18211929    vmR3AtDtor(pVM);
    18221930
    18231931    /*
    1824      * If we are the EMT of VCPU 0, then we'll delay the cleanup till later.
     1932     * EMT(0) does the final cleanup, so if we're it calling VMR3Destroy then
     1933     * we'll have to postpone parts of it till later.  Otherwise, call
     1934     * vmR3Destroy on each of the EMTs in ending with EMT(0) doing the bulk
     1935     * of the cleanup.
    18251936     */
    18261937    if (VMMGetCpuId(pVM) == 0)
     
    18301941        VM_FF_SET(pVM, VM_FF_TERMINATE);
    18311942
    1832         /* Inform all other VCPUs too. */
     1943        /* Terminate the other EMTs. */
    18331944        for (VMCPUID idCpu = 1; idCpu < pVM->cCpus; idCpu++)
    18341945        {
    1835             /*
    1836              * Request EMT to do the larger part of the destruction.
    1837              */
    18381946            PVMREQ pReq = NULL;
    1839             int rc = VMR3ReqCallU(pUVM, idCpu, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3Destroy, 1, pVM);
     1947            int rc = VMR3ReqCallU(pUVM, idCpu, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     1948                                  (PFNRT)vmR3Destroy, 1, pVM);
    18401949            if (RT_SUCCESS(rc))
    18411950                rc = pReq->iStatus;
    1842             AssertRC(rc);
     1951            AssertLogRelRC(rc);
    18431952            VMR3ReqFree(pReq);
    18441953        }
     
    18461955    else
    18471956    {
    1848         /*
    1849          * Request EMT to do the larger part of the destruction. (in reverse order as VCPU 0 does the real cleanup)
    1850          */
     1957        /* vmR3Destroy on all EMTs, ending with EMT(0). */
    18511958        PVMREQ pReq = NULL;
    1852         int rc = VMR3ReqCallU(pUVM, VMCPUID_ALL_REVERSE, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3Destroy, 1, pVM);
     1959        int rc = VMR3ReqCallU(pUVM, VMCPUID_ALL_REVERSE, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     1960                              (PFNRT)vmR3Destroy, 1, pVM);
    18531961        if (RT_SUCCESS(rc))
    18541962            rc = pReq->iStatus;
    1855         AssertRC(rc);
     1963        AssertLogRelRC(rc);
    18561964        VMR3ReqFree(pReq);
    18571965
    1858         /*
    1859          * Now do the final bit where the heap and VM structures are freed up.
    1860          * This will also wait 30 secs for the emulation threads to terminate.
    1861          */
     1966        /* Wait for EMTs and destroy the UVM. */
    18621967        vmR3DestroyUVM(pUVM, 30000);
    18631968    }
     
    18711976 * Internal destruction worker.
    18721977 *
    1873  * This will do nearly all of the job, including sacking the EMT.
    1874  *
    1875  * @returns VBox status.
    1876  * @param   pVM     VM handle.
     1978 * This is either called from VMR3Destroy via VMR3ReqCallU or from
     1979 * vmR3EmulationThreadWithId when EMT(0) terminates after having called
     1980 * VMR3Destroy().
     1981 *
     1982 * When called on EMT(0), it will performed the great bulk of the destruction.
     1983 * When called on the other EMTs, they will do nothing and the whole purpose is
     1984 * to return VINF_EM_TERMINATE so they break out of their run loops.
     1985 *
     1986 * @returns VINF_EM_TERMINATE.
     1987 * @param   pVM     The VM handle.
    18771988 */
    18781989DECLCALLBACK(int) vmR3Destroy(PVM pVM)
    18791990{
    1880     PUVM pUVM = pVM->pUVM;
     1991    PUVM   pUVM = pVM->pUVM;
    18811992    PVMCPU pVCpu = VMMGetCpu(pVM);
    1882 
    1883     NOREF(pUVM);
    1884     LogFlow(("vmR3Destroy: pVM=%p pUVM=%p\n", pVM, pUVM));
    1885     VM_ASSERT_EMT(pVM);
    1886 
    1887     /* Only VCPU 0 does the full cleanup. */
    1888     if (pVCpu->idCpu != 0)
    1889         return VINF_EM_TERMINATE;
    1890 
    1891     /*
    1892      * Dump statistics to the log.
    1893      */
     1993    Assert(pVCpu);
     1994    LogFlow(("vmR3Destroy: pVM=%p pUVM=%p pVCpu=%p idCpu=%u\n", pVM, pUVM, pVCpu, pVCpu->idCpu));
     1995
     1996    /*
     1997     * Only VCPU 0 does the full cleanup.
     1998    */
     1999    if (pVCpu->idCpu == 0)
     2000    {
     2001
     2002        /*
     2003         * Dump statistics to the log.
     2004         */
    18942005#if defined(VBOX_WITH_STATISTICS) || defined(LOG_ENABLED)
    1895     RTLogFlags(NULL, "nodisabled nobuffered");
     2006        RTLogFlags(NULL, "nodisabled nobuffered");
    18962007#endif
    18972008#ifdef VBOX_WITH_STATISTICS
    1898     STAMR3Dump(pVM, "*");
     2009        STAMR3Dump(pVM, "*");
    18992010#else
    1900     LogRel(("************************* Statistics *************************\n"));
    1901     STAMR3DumpToReleaseLog(pVM, "*");
    1902     LogRel(("********************* End of statistics **********************\n"));
     2011        LogRel(("************************* Statistics *************************\n"));
     2012        STAMR3DumpToReleaseLog(pVM, "*");
     2013        LogRel(("********************* End of statistics **********************\n"));
    19032014#endif
    19042015
    1905     /*
    1906      * Destroy the VM components.
    1907      */
    1908     int rc = TMR3Term(pVM);
    1909     AssertRC(rc);
     2016        /*
     2017         * Destroy the VM components.
     2018         */
     2019        int rc = TMR3Term(pVM);
     2020        AssertRC(rc);
    19102021#ifdef VBOX_WITH_DEBUGGER
    1911     rc = DBGCTcpTerminate(pVM, pUVM->vm.s.pvDBGC);
    1912     pVM->pUVM->vm.s.pvDBGC = NULL;
     2022        rc = DBGCTcpTerminate(pVM, pUVM->vm.s.pvDBGC);
     2023        pUVM->vm.s.pvDBGC = NULL;
    19132024#endif
    1914     AssertRC(rc);
    1915     rc = DBGFR3Term(pVM);
    1916     AssertRC(rc);
    1917     rc = PDMR3Term(pVM);
    1918     AssertRC(rc);
    1919     rc = EMR3Term(pVM);
    1920     AssertRC(rc);
    1921     rc = IOMR3Term(pVM);
    1922     AssertRC(rc);
    1923     rc = CSAMR3Term(pVM);
    1924     AssertRC(rc);
    1925     rc = PATMR3Term(pVM);
    1926     AssertRC(rc);
    1927     rc = TRPMR3Term(pVM);
    1928     AssertRC(rc);
    1929     rc = SELMR3Term(pVM);
    1930     AssertRC(rc);
    1931     rc = REMR3Term(pVM);
    1932     AssertRC(rc);
    1933     rc = HWACCMR3Term(pVM);
    1934     AssertRC(rc);
    1935     rc = PGMR3Term(pVM);
    1936     AssertRC(rc);
    1937     rc = VMMR3Term(pVM); /* Terminates the ring-0 code! */
    1938     AssertRC(rc);
    1939     rc = CPUMR3Term(pVM);
    1940     AssertRC(rc);
    1941     SSMR3Term(pVM);
    1942     rc = PDMR3CritSectTerm(pVM);
    1943     AssertRC(rc);
    1944     rc = MMR3Term(pVM);
    1945     AssertRC(rc);
    1946 
    1947     /*
    1948      * We're done in this thread (EMT).
    1949      */
    1950     ASMAtomicUoWriteBool(&pVM->pUVM->vm.s.fTerminateEMT, true);
    1951     ASMAtomicWriteU32(&pVM->fGlobalForcedActions, VM_FF_TERMINATE);
    1952     LogFlow(("vmR3Destroy: returning %Rrc\n", VINF_EM_TERMINATE));
     2025        AssertRC(rc);
     2026        rc = DBGFR3Term(pVM);
     2027        AssertRC(rc);
     2028        rc = PDMR3Term(pVM);
     2029        AssertRC(rc);
     2030        rc = EMR3Term(pVM);
     2031        AssertRC(rc);
     2032        rc = IOMR3Term(pVM);
     2033        AssertRC(rc);
     2034        rc = CSAMR3Term(pVM);
     2035        AssertRC(rc);
     2036        rc = PATMR3Term(pVM);
     2037        AssertRC(rc);
     2038        rc = TRPMR3Term(pVM);
     2039        AssertRC(rc);
     2040        rc = SELMR3Term(pVM);
     2041        AssertRC(rc);
     2042        rc = REMR3Term(pVM);
     2043        AssertRC(rc);
     2044        rc = HWACCMR3Term(pVM);
     2045        AssertRC(rc);
     2046        rc = PGMR3Term(pVM);
     2047        AssertRC(rc);
     2048        rc = VMMR3Term(pVM); /* Terminates the ring-0 code! */
     2049        AssertRC(rc);
     2050        rc = CPUMR3Term(pVM);
     2051        AssertRC(rc);
     2052        SSMR3Term(pVM);
     2053        rc = PDMR3CritSectTerm(pVM);
     2054        AssertRC(rc);
     2055        rc = MMR3Term(pVM);
     2056        AssertRC(rc);
     2057
     2058        /*
     2059         * We're done in this thread (EMT).
     2060         */
     2061        ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
     2062        ASMAtomicWriteU32(&pVM->fGlobalForcedActions, VM_FF_TERMINATE);
     2063        LogFlow(("vmR3Destroy: returning %Rrc\n", VINF_EM_TERMINATE));
     2064    }
    19532065    return VINF_EM_TERMINATE;
    19542066}
     
    19562068
    19572069/**
    1958  * Destroys the shared VM structure, leaving only UVM behind.
    1959  *
    1960  * This is called by EMT right before terminating.
     2070 * Called at the end of the EMT procedure to take care of the final cleanup.
     2071 *
     2072 * Currently only EMT(0) will do work here.  It will destroy the shared VM
     2073 * structure if it is still around.  If EMT(0) was the caller of VMR3Destroy it
     2074 * will destroy UVM and nothing will be left behind upon exit.  But if some
     2075 * other thread is calling VMR3Destroy, they will clean up UVM after all EMTs
     2076 * has exitted.
    19612077 *
    19622078 * @param   pUVM        The UVM handle.
    1963  */
    1964 void vmR3DestroyFinalBitFromEMT(PUVM pUVM)
    1965 {
     2079 * @param   idCpu       The virtual CPU id.
     2080 */
     2081void vmR3DestroyFinalBitFromEMT(PUVM pUVM, VMCPUID idCpu)
     2082{
     2083    /*
     2084     * Only EMT(0) has work to do here.
     2085     */
     2086    if (idCpu != 0)
     2087        return;
     2088    Assert(   !pUVM->pVM
     2089           || VMMGetCpuId(pUVM->pVM) == 0);
     2090
     2091    /*
     2092     * If we have a shared VM structure, change its state to Terminated and
     2093     * tell GVMM to destroy it.
     2094     */
    19662095    if (pUVM->pVM)
    19672096    {
    1968         PVMCPU pVCpu = VMMGetCpu(pUVM->pVM);
    1969 
    1970         /* VCPU 0 does all the cleanup work. */
    1971         if (pVCpu->idCpu != 0)
    1972             return;
    1973 
    1974         /*
    1975          * Modify state and then terminate MM.
    1976          * (MM must be delayed until this point so we don't destroy the callbacks and the request packet.)
    1977          */
    1978         vmR3SetState(pUVM->pVM, VMSTATE_TERMINATED);
    1979 
    1980         /*
    1981          * Tell GVMM to destroy the VM and free its resources.
    1982          */
     2097        vmR3SetState(pUVM->pVM, VMSTATE_TERMINATED, VMSTATE_DESTROYING);
    19832098        int rc = SUPR3CallVMMR0Ex(pUVM->pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
    1984         AssertRC(rc);
     2099        AssertLogRelRC(rc);
    19852100        pUVM->pVM = NULL;
    19862101    }
    19872102
    19882103    /*
    1989      * Did an EMT call VMR3Destroy and end up having to do all the work?
     2104     * If EMT(0) called VMR3Destroy, then it will destroy UVM as well.
    19902105     */
    19912106    if (pUVM->vm.s.fEMTDoesTheCleanup)
     
    19982113 *
    19992114 * This is called as the final step in the VM destruction or as the cleanup
    2000  * in case of a creation failure. If EMT called VMR3Destroy, meaning
     2115 * in case of a creation failure. If EMT(0) called VMR3Destroy, meaning
    20012116 * VMINTUSERPERVM::fEMTDoesTheCleanup is true, it will call this as
    20022117 * vmR3DestroyFinalBitFromEMT completes.
     
    22752390
    22762391/**
    2277  * Reset the current VM.
    2278  *
    2279  * @returns VBox status code.
    2280  * @param   pVM     VM to reset.
    2281  */
    2282 VMMR3DECL(int)   VMR3Reset(PVM pVM)
    2283 {
    2284     int rc = VINF_SUCCESS;
    2285 
    2286     /*
    2287      * Check the state.
    2288      */
    2289     if (!pVM)
    2290         return VERR_INVALID_PARAMETER;
    2291     if (    pVM->enmVMState != VMSTATE_RUNNING
    2292         &&  pVM->enmVMState != VMSTATE_SUSPENDED)
    2293     {
    2294         AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
    2295         return VERR_VM_INVALID_VM_STATE;
    2296     }
    2297 
    2298     /*
    2299      * Queue reset request to the emulation thread
    2300      * and wait for it to be processed. (in reverse order as VCPU 0 does the real cleanup)
    2301      */
    2302     PVMREQ pReq = NULL;
    2303     rc = VMR3ReqCall(pVM, VMCPUID_ALL_REVERSE, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Reset, 1, pVM);
    2304     if (RT_SUCCESS(rc))
    2305         rc = pReq->iStatus;
    2306     AssertRC(rc);
    2307     VMR3ReqFree(pReq);
    2308 
    2309     return rc;
    2310 }
    2311 
    2312 
    2313 /**
    23142392 * Worker which checks integrity of some internal structures.
    23152393 * This is yet another attempt to track down that AVL tree crash.
     
    23382416
    23392417    /*
     2418     * The first EMT will try change the state to resetting.
     2419     */
     2420    if (pVCpu->idCpu == pVM->cCpus - 1)
     2421    {
     2422        PUVM pUVM = pVM->pUVM;
     2423        RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);
     2424        VMSTATE enmStateOld = pVM->enmVMState;
     2425        switch (enmStateOld)
     2426        {
     2427            case VMSTATE_RUNNING:
     2428            case VMSTATE_SUSPENDED:
     2429                vmR3SetStateLocked(pVM, pUVM, VMSTATE_RESETTING, enmStateOld);
     2430                RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     2431                break;
     2432
     2433            case VMSTATE_RUNNING_LS:
     2434                vmR3SetStateLocked(pVM, pUVM, VMSTATE_RESETTING_LS, enmStateOld);
     2435                RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     2436
     2437                SSMR3Cancel(pVM);
     2438                break;
     2439
     2440            default:
     2441                AssertLogRelMsgFailed(("%s\n", VMR3GetStateName(enmStateOld)));
     2442                RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     2443                return VERR_VM_INVALID_VM_STATE;
     2444        }
     2445    }
     2446
     2447    /*
     2448     * Check the state.
     2449     */
     2450    VMSTATE enmVMState = pVM->enmVMState;
     2451    AssertLogRelMsgReturn(   enmVMState == VMSTATE_RESETTING
     2452                          || enmVMState == VMSTATE_RESETTING_LS,
     2453                          ("%s\n", VMR3GetStateName(enmVMState)),
     2454                          VERR_VM_INVALID_VM_STATE);
     2455
     2456    /*
    23402457     * EMT(0) does the full cleanup *after* all the other EMTs has been
    23412458     * thru here and been told to enter the EMSTATE_WAIT_SIPI state.
    2342      */
     2459     *
     2460     * Because there are per-cpu reset routines and order may/is important,
     2461     * the following sequence looks a bit ugly...
     2462     */
     2463    if (pVCpu->idCpu == 0)
     2464        vmR3CheckIntegrity(pVM);
     2465
     2466    /* Reset the VCpu state. */
    23432467    VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED);
    23442468
     
    23462470    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_ALL_MASK & ~VMCPU_FF_REQUEST);
    23472471
    2348     if (pVCpu->idCpu != 0)
    2349     {
    2350         CPUMR3ResetCpu(pVCpu);
    2351         return VINF_EM_RESET;
    2352     }
    2353 
    2354     /*
    2355      * As a safety precaution we temporarily change the state while resetting.
    2356      * (If VMR3Reset was not called from EMT we might have change state... let's ignore that fact for now.)
    2357      */
    2358     VMSTATE enmVMState = pVM->enmVMState;
    2359     Assert(enmVMState == VMSTATE_SUSPENDED || enmVMState == VMSTATE_RUNNING);
    2360     vmR3SetState(pVM, VMSTATE_RESETTING);
    2361     vmR3CheckIntegrity(pVM);
    2362 
    2363 
    23642472    /*
    23652473     * Reset the VM components.
    23662474     */
    2367     PATMR3Reset(pVM);
    2368     CSAMR3Reset(pVM);
    2369     PGMR3Reset(pVM);                    /* We clear VM RAM in PGMR3Reset. It's vital PDMR3Reset is executed
    2370                                          * _afterwards_. E.g. ACPI sets up RAM tables during init/reset. */
    2371     MMR3Reset(pVM);
    2372     PDMR3Reset(pVM);
    2373     SELMR3Reset(pVM);
    2374     TRPMR3Reset(pVM);
    2375     REMR3Reset(pVM);
    2376     IOMR3Reset(pVM);
    2377     CPUMR3Reset(pVM);
    2378     TMR3Reset(pVM);
    2379     EMR3Reset(pVM);
    2380     HWACCMR3Reset(pVM);                 /* This must come *after* PATM, CSAM, CPUM, SELM and TRPM. */
     2475    if (pVCpu->idCpu == 0)
     2476    {
     2477        PATMR3Reset(pVM);
     2478        CSAMR3Reset(pVM);
     2479        PGMR3Reset(pVM);                    /* We clear VM RAM in PGMR3Reset. It's vital PDMR3Reset is executed
     2480                                             * _afterwards_. E.g. ACPI sets up RAM tables during init/reset. */
     2481        MMR3Reset(pVM);
     2482        PDMR3Reset(pVM);
     2483        SELMR3Reset(pVM);
     2484        TRPMR3Reset(pVM);
     2485        REMR3Reset(pVM);
     2486        IOMR3Reset(pVM);
     2487        CPUMR3Reset(pVM);
     2488    }
     2489    CPUMR3ResetCpu(pVCpu);
     2490    if (pVCpu->idCpu == 0)
     2491    {
     2492        TMR3Reset(pVM);
     2493        EMR3Reset(pVM);
     2494        HWACCMR3Reset(pVM);                 /* This must come *after* PATM, CSAM, CPUM, SELM and TRPM. */
    23812495
    23822496#ifdef LOG_ENABLED
    2383     /*
    2384      * Debug logging.
    2385      */
    2386     RTLogPrintf("\n\nThe VM was reset:\n");
    2387     DBGFR3Info(pVM, "cpum", "verbose", NULL);
     2497        /*
     2498         * Debug logging.
     2499         */
     2500        RTLogPrintf("\n\nThe VM was reset:\n");
     2501        DBGFR3Info(pVM, "cpum", "verbose", NULL);
    23882502#endif
    23892503
    2390     /*
    2391      * Restore the state.
    2392      */
    2393     vmR3CheckIntegrity(pVM);
    2394     Assert(pVM->enmVMState == VMSTATE_RESETTING);
    2395     vmR3SetState(pVM, enmVMState);
     2504        /*
     2505         * Since EMT(0) is the last to go thru here, it will advance the state.
     2506         */
     2507        PUVM pUVM = pVM->pUVM;
     2508        RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);
     2509        if (pUVM->vm.s.enmPrevVMState == VMSTATE_SUSPENDED)
     2510            vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDED, VMSTATE_RESETTING);
     2511        else
     2512            vmR3SetStateLocked(pVM, pUVM, VMSTATE_RUNNING, pVM->enmVMState);
     2513        RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     2514
     2515        vmR3CheckIntegrity(pVM);
     2516    }
    23962517
    23972518    return VINF_EM_RESET;
     2519}
     2520
     2521
     2522/**
     2523 * Reset the current VM.
     2524 *
     2525 * @returns VBox status code.
     2526 * @param   pVM     VM to reset.
     2527 */
     2528VMMR3DECL(int) VMR3Reset(PVM pVM)
     2529{
     2530    LogFlow(("VMR3Reset:\n"));
     2531    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     2532
     2533    /*
     2534     * Forward the query on
     2535     * Queue reset request to the emulation thread
     2536     * and wait for it to be processed. (in reverse order as VCPU 0 does the real cleanup)
     2537     */
     2538    PVMREQ pReq = NULL;
     2539    int rc = VMR3ReqCallU(pVM->pUVM, VMCPUID_ALL_REVERSE, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     2540                          (PFNRT)vmR3Reset, 1, pVM);
     2541    if (RT_SUCCESS(rc))
     2542        rc = pReq->iStatus;
     2543    AssertLogRelRC(rc);
     2544    VMR3ReqFree(pReq);
     2545
     2546    return rc;
    23982547}
    23992548
     
    24262575        case VMSTATE_LOADING:           return "LOADING";
    24272576        case VMSTATE_POWERING_ON:       return "POWERING_ON";
     2577        case VMSTATE_RESUMING:          return "RESUMING";
    24282578        case VMSTATE_RUNNING:           return "RUNNING";
    24292579        case VMSTATE_RUNNING_LS:        return "RUNNING_LS";
     
    24312581        case VMSTATE_RESETTING_LS:      return "RESETTING_LS";
    24322582        case VMSTATE_SUSPENDED:         return "SUSPENDED";
     2583        case VMSTATE_SUSPENDED_LS:      return "SUSPENDED_LS";
     2584        case VMSTATE_SUSPENDING:        return "SUSPENDING";
    24332585        case VMSTATE_SUSPENDING_LS:     return "SUSPENDING_LS";
    24342586        case VMSTATE_SAVING:            return "SAVING";
     
    24542606
    24552607/**
    2456  * Validates the state tansition.
     2608 * Validates the state transition in strict builds.
     2609 *
     2610 * @returns true if valid, false if not.
     2611 *
     2612 * @param   enmStateOld         The old (current) state.
     2613 * @param   enmStateNew         The proposed new state.
    24572614 */
    24582615static bool vmR3ValidateStateTransition(VMSTATE enmStateOld, VMSTATE enmStateNew)
     
    24792636
    24802637        case VMSTATE_POWERING_ON:
     2638            AssertMsgReturn(   enmStateNew == VMSTATE_RUNNING
     2639                            || enmStateNew == VMSTATE_FATAL_ERROR /*?*/
     2640                            , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
     2641            break;
     2642
     2643        case VMSTATE_RESUMING:
    24812644            AssertMsgReturn(   enmStateNew == VMSTATE_RUNNING
    24822645                            || enmStateNew == VMSTATE_FATAL_ERROR /*?*/
     
    25262689                            || enmStateNew == VMSTATE_SAVING
    25272690                            || enmStateNew == VMSTATE_RESETTING
    2528                             || enmStateNew == VMSTATE_RUNNING
     2691                            || enmStateNew == VMSTATE_RESUMING
     2692                            || enmStateNew == VMSTATE_LOADING
    25292693                            , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
    25302694            break;
     
    25412705
    25422706        case VMSTATE_DEBUGGING:
     2707            AssertMsgReturn(   enmStateNew == VMSTATE_RUNNING
     2708                            || enmStateNew == VMSTATE_POWERING_OFF
     2709                            , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
     2710            break;
     2711
     2712        case VMSTATE_DEBUGGING_LS:
    25432713            AssertMsgReturn(   enmStateNew == VMSTATE_RUNNING_LS
    25442714                            || enmStateNew == VMSTATE_POWERING_OFF_LS
     
    25512721
    25522722        case VMSTATE_POWERING_OFF_LS:
    2553             AssertMsgReturn(enmStateNew == VMSTATE_POWERING_OFF, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
     2723            AssertMsgReturn(   enmStateNew == VMSTATE_POWERING_OFF
     2724                            || enmStateNew == VMSTATE_OFF_LS
     2725                            , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
    25542726            break;
    25552727
     
    25582730            break;
    25592731
     2732        case VMSTATE_OFF_LS:
     2733            AssertMsgReturn(enmStateNew == VMSTATE_OFF, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
     2734            break;
     2735
    25602736        case VMSTATE_FATAL_ERROR:
    25612737            AssertMsgReturn(enmStateNew == VMSTATE_POWERING_OFF, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
     
    25632739
    25642740        case VMSTATE_FATAL_ERROR_LS:
    2565             AssertMsgReturn(enmStateNew == VMSTATE_FATAL_ERROR, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
     2741            AssertMsgReturn(   enmStateNew == VMSTATE_FATAL_ERROR
     2742                            || enmStateNew == VMSTATE_POWERING_OFF_LS
     2743                            , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
    25662744            break;
    25672745
     
    25732751
    25742752        case VMSTATE_GURU_MEDITATION_LS:
    2575             AssertMsgReturn(enmStateNew == VMSTATE_GURU_MEDITATION, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
     2753            AssertMsgReturn(   enmStateNew == VMSTATE_GURU_MEDITATION
     2754                            || enmStateNew == VMSTATE_POWERING_OFF_LS
     2755                            , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
    25762756            break;
    25772757
     
    25952775
    25962776/**
    2597  * Sets the current VM state.
    2598  *
    2599  * @returns The current VM state.
    2600  * @param   pVM             VM handle.
    2601  * @param   enmStateNew     The new state.
    2602  */
    2603 void vmR3SetState(PVM pVM, VMSTATE enmStateNew)
    2604 {
    2605     PUVM        pUVM  = pVM->pUVM;
    2606 #ifdef DEBUG_bird /** @todo remove when sorted out. */
    2607     VM_ASSERT_EMT0(pVM);
    2608 #endif
    2609 
    2610     /*
    2611      * Validate state machine transitions before doing the actual change.
    2612      */
    2613     VMSTATE enmStateOld = pVM->enmVMState;
    2614     vmR3ValidateStateTransition(enmStateOld, enmStateNew);
    2615     pVM->enmVMState = enmStateNew;
     2777 * Does the state change callouts.
     2778 *
     2779 * The caller owns the AtStateCritSect.
     2780 *
     2781 * @param   pVM                 The VM handle.
     2782 * @param   pUVM                The UVM handle.
     2783 * @param   enmStateNew         The New state.
     2784 * @param   enmStateOld         The old state.
     2785 */
     2786static void vmR3DoAtState(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld)
     2787{
    26162788    LogRel(("Changing the VM state from '%s' to '%s'.\n", VMR3GetStateName(enmStateOld),  VMR3GetStateName(enmStateNew)));
    26172789
    2618     /*
    2619      * Call the at state change callbacks.
    2620      */
    2621     RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);
    26222790    for (PVMATSTATE pCur = pUVM->vm.s.pAtState; pCur; pCur = pCur->pNext)
    26232791    {
    26242792        pCur->pfnAtState(pVM, enmStateNew, enmStateOld, pCur->pvUser);
    2625         if (    pVM->enmVMState != enmStateNew
     2793        if (    enmStateNew     != VMSTATE_DESTROYING
    26262794            &&  pVM->enmVMState == VMSTATE_DESTROYING)
    26272795            break;
     
    26322800                   "difficult to follow.\n"));
    26332801    }
     2802}
     2803
     2804
     2805/**
     2806 * Sets the current VM state, with the AtStatCritSect already entered.
     2807 *
     2808 * @param   pVM                 The VM handle.
     2809 * @param   pUVM                The UVM handle.
     2810 * @param   enmStateNew         The new state.
     2811 * @param   enmStateOld         The old state.
     2812 */
     2813static void vmR3SetStateLocked(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld)
     2814{
     2815    vmR3ValidateStateTransition(enmStateOld, enmStateNew);
     2816
     2817    Assert(pVM->enmVMState == enmStateOld);
     2818    pUVM->vm.s.enmPrevVMState = enmStateOld;
     2819    pVM->enmVMState           = enmStateNew;
     2820
     2821    vmR3DoAtState(pVM, pUVM, enmStateNew, enmStateOld);
     2822}
     2823
     2824
     2825/**
     2826 * Tries to set the VM state.
     2827 *
     2828 * @returns true on success, false on failure.
     2829 * @param   pVM             VM handle.
     2830 * @param   enmStateNew     The new state.
     2831 */
     2832static bool vmR3TrySetState(PVM pVM, VMSTATE enmStateNew, VMSTATE enmStateOld)
     2833{
     2834    vmR3ValidateStateTransition(enmStateOld, enmStateNew);
     2835
     2836    bool fRc = true;
     2837    PUVM pUVM = pVM->pUVM;
     2838    RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);
     2839    if (pVM->enmVMState == enmStateOld)
     2840    {
     2841        pVM->enmVMState = enmStateNew;
     2842        vmR3DoAtState(pVM, pUVM, enmStateNew, enmStateOld);
     2843    }
     2844    else
     2845    {
     2846        Log(("vmR3TrySetState: failed enmVMState=%s, enmStateOld=%s, enmStateNew=%s\n",
     2847             VMR3GetStateName(pVM->enmVMState), VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)));
     2848        fRc = false;
     2849    }
    26342850    RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     2851    return fRc;
     2852}
     2853
     2854
     2855/**
     2856 * Tries to set the VM state give two alternative transisions.
     2857 *
     2858 * @returns 1 if the first alternative, 2 if the second, and 0 on failure.
     2859 * @param  pVM              The VM handle.
     2860 * @param  enmStateNew1     New state, alternative 1.
     2861 * @param  enmStateOld1     Old state, alternative 1.
     2862 * @param  enmStateNew2     New state, alternative 2.
     2863 * @param  enmStateOld2     Old state, alternative 2.
     2864 */
     2865static unsigned vmR3TrySetState2(PVM pVM, VMSTATE enmStateNew1, VMSTATE enmStateOld1, VMSTATE enmStateNew2, VMSTATE enmStateOld2)
     2866{
     2867    vmR3ValidateStateTransition(enmStateOld1, enmStateNew1);
     2868    vmR3ValidateStateTransition(enmStateOld2, enmStateNew2);
     2869
     2870    PUVM pUVM = pVM->pUVM;
     2871    RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);
     2872
     2873    unsigned rc;
     2874    VMSTATE  enmStateOld = pVM->enmVMState;
     2875    if (enmStateOld == enmStateOld1)
     2876    {
     2877        vmR3SetStateLocked(pVM, pUVM, enmStateNew1, enmStateOld1);
     2878        rc = 1;
     2879    }
     2880    else if (enmStateOld == enmStateOld2)
     2881    {
     2882        vmR3SetStateLocked(pVM, pUVM, enmStateNew2, enmStateOld2);
     2883        rc = 2;
     2884    }
     2885    else
     2886        rc = 0;
     2887
     2888    RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     2889    return rc;
     2890}
     2891
     2892
     2893/**
     2894 * Sets the current VM state.
     2895 *
     2896 * @param   pVM             VM handle.
     2897 * @param   enmStateNew     The new state.
     2898 * @param   enmStateOld     The old state (for asserting only).
     2899 */
     2900static void vmR3SetState(PVM pVM, VMSTATE enmStateNew, VMSTATE enmStateOld)
     2901{
     2902    PUVM pUVM = pVM->pUVM;
     2903    RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);
     2904
     2905    AssertMsg(enmStateOld == pVM->enmVMState, ("\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(pVM->enmVMState)));
     2906    vmR3SetStateLocked(pVM, pUVM, enmStateNew, pVM->enmVMState);
     2907
     2908    RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     2909}
     2910
     2911
     2912/**
     2913 * Sets the current VM state to one of the two specified new states depending on
     2914 * the what the current (old) state is.
     2915 *
     2916 * @returns 1 if the first alternative, 2 if the second.
     2917 * @param  pVM              The VM handle.
     2918 * @param  enmStateNew1     New state, alternative 1.
     2919 * @param  enmStateOld1     Old state, alternative 1.
     2920 * @param  enmStateNew2     New state, alternative 2.
     2921 * @param  enmStateOld2     Old state, alternative 2.
     2922 */
     2923static unsigned vmR3SetState2(PVM pVM, VMSTATE enmStateNew1, VMSTATE enmStateOld1, VMSTATE enmStateNew2, VMSTATE enmStateOld2)
     2924{
     2925    vmR3ValidateStateTransition(enmStateOld1, enmStateNew1);
     2926    vmR3ValidateStateTransition(enmStateOld2, enmStateNew2);
     2927
     2928    PUVM pUVM = pVM->pUVM;
     2929    RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);
     2930
     2931    unsigned rc;
     2932    VMSTATE  enmStateOld = pVM->enmVMState;
     2933    if (enmStateOld == enmStateOld1)
     2934    {
     2935        vmR3SetStateLocked(pVM, pUVM, enmStateNew1, enmStateOld1);
     2936        rc = 1;
     2937    }
     2938    else
     2939    {
     2940        AssertLogRelMsg(enmStateOld == enmStateOld2,
     2941                        ("%s, expected %s or %s (-> %s or %s)\n",
     2942                         VMR3GetStateName(enmStateOld),
     2943                         VMR3GetStateName(enmStateOld1),
     2944                         VMR3GetStateName(enmStateOld2),
     2945                         VMR3GetStateName(enmStateNew1),
     2946                         VMR3GetStateName(enmStateNew2)));
     2947        vmR3SetStateLocked(pVM, pUVM, enmStateNew2, enmStateOld2);
     2948        rc = 2;
     2949    }
     2950
     2951    RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);
     2952    return rc;
     2953}
     2954
     2955
     2956/**
     2957 * Flag a guru meditation ... a hack.
     2958 *
     2959 * @param   pVM             The VM handle
     2960 *
     2961 * @todo    Rewrite this part. The guru meditation should be flagged
     2962 *          immediately by the VMM and not by VMEmt.cpp when it's all over.
     2963 */
     2964void vmR3SetGuruMeditation(PVM pVM)
     2965{
     2966    if (vmR3TrySetState(pVM, VMSTATE_GURU_MEDITATION, VMSTATE_RUNNING))
     2967        return;
     2968    if (vmR3TrySetState(pVM, VMSTATE_GURU_MEDITATION_LS, VMSTATE_RUNNING_LS))
     2969        SSMR3Cancel(pVM);
    26352970}
    26362971
     
    26482983 * @thread  Any.
    26492984 */
    2650 VMMR3DECL(int)   VMR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser)
     2985VMMR3DECL(int) VMR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser)
    26512986{
    26522987    LogFlow(("VMR3AtStateRegister: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser));
     
    31393474        rc = vmR3SuspendCommon(pVM, true /*fFatal*/);
    31403475    else if (fFlags & VMSETRTERR_FLAGS_SUSPEND)
    3141         rc = VMR3Suspend(pVM);
     3476        rc = vmR3SuspendCommon(pVM, false /*fFatal*/);
    31423477
    31433478    /*
  • trunk/src/VBox/VMM/VMEmt.cpp

    r21144 r23009  
    224224            &&  pUVM->pVM)
    225225        {
    226             PVM     pVM  = pUVM->pVM;
    227             PVMCPU pVCpu = &pVM->aCpus[idCpu];
     226            PVM     pVM   = pUVM->pVM;
     227            PVMCPU  pVCpu = &pVM->aCpus[idCpu];
    228228            if (    pVM->enmVMState == VMSTATE_RUNNING
    229229                &&  VMCPUSTATE_IS_STARTED(VMCPU_GET_STATE(pVCpu)))
     
    231231                rc = EMR3ExecuteVM(pVM, pVCpu);
    232232                Log(("vmR3EmulationThread: EMR3ExecuteVM() -> rc=%Rrc, enmVMState=%d\n", rc, pVM->enmVMState));
    233                 if (   EMGetState(pVCpu) == EMSTATE_GURU_MEDITATION
    234                     && pVM->enmVMState == VMSTATE_RUNNING)
    235                     vmR3SetState(pVM, VMSTATE_GURU_MEDITATION);
     233                if (EMGetState(pVCpu) == EMSTATE_GURU_MEDITATION)
     234                    vmR3SetGuruMeditation(pVM);
    236235            }
    237236        }
     
    241240
    242241    /*
    243      * Exiting.
     242     * Cleanup and exit.
     243     * If EMT(0) called VMR3Destroy, EMT(0) will do all the terminating here.
    244244     */
    245245    Log(("vmR3EmulationThread: Terminating emulation thread! Thread=%#x pUVM=%p rc=%Rrc enmBefore=%d enmVMState=%d\n",
    246246         ThreadSelf, pUVM, rc, enmBefore, pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_TERMINATED));
    247     if (pUVM->vm.s.fEMTDoesTheCleanup)
     247    if (    pUVM->vm.s.fEMTDoesTheCleanup
     248        &&  idCpu == 0)
    248249    {
    249250        Log(("vmR3EmulationThread: executing delayed Destroy\n"));
    250251        Assert(pUVM->pVM);
    251252        vmR3Destroy(pUVM->pVM);
    252         vmR3DestroyFinalBitFromEMT(pUVM);
     253        vmR3DestroyFinalBitFromEMT(pUVM, idCpu);
     254        /* The pUVM structure is now invliad. */
     255        pUVCpu = NULL;
     256        pUVM = NULL;
    253257    }
    254258    else
    255259    {
    256         vmR3DestroyFinalBitFromEMT(pUVM);
    257 
     260        vmR3DestroyFinalBitFromEMT(pUVM, idCpu);
    258261        pUVCpu->vm.s.NativeThreadEMT = NIL_RTNATIVETHREAD;
    259262    }
  • trunk/src/VBox/VMM/VMInternal.h

    r22986 r23009  
    166166    /** VM Runtime Error Message. */
    167167    R3PTRTYPE(PVMRUNTIMEERROR)      pRuntimeErrorR3;
    168     /** Set by VMR3SuspendNoSave; cleared by VMR3Resume; signals the VM is in an
    169      * inconsistent state and saving is not allowed. */
    170     bool                            fPreventSaveState;
    171168} VMINT;
    172169/** Pointer to the VM Internal Data (part of the VM structure). */
     
    207204    /** Force EMT to terminate. */
    208205    bool volatile                   fTerminateEMT;
    209     /** If set the EMT does the final VM cleanup when it exits.
     206    /** If set the EMT(0) does the final VM cleanup when it exits.
    210207     * If clear the VMR3Destroy() caller does so. */
    211208    bool                            fEMTDoesTheCleanup;
    212209
    213     /** Critical section for pAtState. */
     210    /** Critical section for pAtState and enmPrevVMState. */
    214211    RTCRITSECT                      AtStateCritSect;
    215212    /** List of registered state change callbacks. */
     
    217214    /** List of registered state change callbacks. */
    218215    PVMATSTATE                     *ppAtStateNext;
     216    /** The previous VM state.
     217     * This is mainly used for the 'Resetting' state, but may come in handy later
     218     * and when debugging. */
     219    VMSTATE                         enmPrevVMState;
    219220
    220221    /** Critical section for pAtError and pAtRuntimeError. */
     
    416417DECLCALLBACK(int)   vmR3SetRuntimeErrorV(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list *pVa);
    417418void                vmSetRuntimeErrorCopy(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va);
    418 void                vmR3DestroyFinalBitFromEMT(PUVM pUVM);
    419 void                vmR3SetState(PVM pVM, VMSTATE enmStateNew);
     419void                vmR3DestroyFinalBitFromEMT(PUVM pUVM, VMCPUID idCpu);
     420void                vmR3SetGuruMeditation(PVM pVM);
    420421
    421422RT_C_DECLS_END
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette