Changeset 23009 in vbox
- Timestamp:
- Sep 14, 2009 3:05:45 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 52301
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/types.h
r22975 r23009 156 156 /** The VM is being powered on */ 157 157 VMSTATE_POWERING_ON, 158 /** The VM is being resumed. */ 159 VMSTATE_RESUMING, 158 160 /** The VM is runnning. */ 159 161 VMSTATE_RUNNING, … … 187 189 /** The VM is switched off, awaiting destruction. */ 188 190 VMSTATE_OFF, 191 /** Live save: Waiting for cancellation and transition to VMSTATE_OFF. */ 192 VMSTATE_OFF_LS, 189 193 /** The VM is powered off because of a fatal error. */ 190 194 VMSTATE_FATAL_ERROR, -
trunk/include/VBox/vm.h
r22893 r23009 678 678 /** The state of the VM. 679 679 * This field is read only to everyone except the VM and EM. */ 680 VMSTATE 680 VMSTATE volatile enmVMState; 681 681 /** Forced action flags. 682 682 * See the VM_FF_* \#defines. Updated atomically. -
trunk/src/VBox/Main/ConsoleImpl.cpp
r22915 r23009 5618 5618 */ 5619 5619 DECLCALLBACK(void) 5620 Console::vmstateChangeCallback 5621 5622 { 5623 LogFlowFunc 5624 5625 5626 Console *that = static_cast 5627 AssertReturnVoid 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); 5628 5628 5629 5629 AutoCaller autoCaller(that); … … 5633 5633 * 1) powerDown() called from uninit() itself, or 5634 5634 * 2) VM-(guest-)initiated power off. */ 5635 AssertReturnVoid (autoCaller.isOk() ||5636 autoCaller.state() == InUninit);5635 AssertReturnVoid( autoCaller.isOk() 5636 || autoCaller.state() == InUninit); 5637 5637 5638 5638 switch (aState) … … 5651 5651 * VM-(guest-)initiated shutdown/poweroff. 5652 5652 */ 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) 5656 5656 { 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")); 5659 5658 5660 5659 /* prevent powerDown() from calling VMR3PowerOff() again */ 5661 Assert 5660 Assert(that->mVMPoweredOff == false); 5662 5661 that->mVMPoweredOff = true; 5663 5662 5664 5663 /* we are stopping now */ 5665 that->setMachineState 5664 that->setMachineState(MachineState_Stopping); 5666 5665 5667 5666 /* Setup task object and thread to carry out the operation … … 5670 5669 * deadlock). 5671 5670 */ 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 */)); 5675 5673 5676 5674 /* If creating a task is falied, this can currently mean one of … … 5682 5680 if (!task->isOk()) 5683 5681 { 5684 LogFlowFunc 5682 LogFlowFunc(("Console is already being uninitialized.\n")); 5685 5683 break; 5686 5684 } 5687 5685 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)); 5695 5691 5696 5692 /* task is now owned by powerDownThread(), so release it */ … … 5732 5728 case MachineState_Stopping: 5733 5729 /* successfully powered down */ 5734 that->setMachineState 5730 that->setMachineState(MachineState_PoweredOff); 5735 5731 break; 5736 5732 case MachineState_Saving: … … 5739 5735 * called from saveStateThread(), so only change the local 5740 5736 * state) */ 5741 that->setMachineStateLocally 5737 that->setMachineStateLocally(MachineState_Saved); 5742 5738 break; 5743 5739 case MachineState_Starting: 5744 5740 /* failed to start, but be patient: set back to PoweredOff 5745 5741 * (for similarity with the below) */ 5746 that->setMachineState 5742 that->setMachineState(MachineState_PoweredOff); 5747 5743 break; 5748 5744 case MachineState_Restoring: 5749 5745 /* failed to load the saved state file, but be patient: set 5750 5746 * back to Saved (to preserve the saved state file) */ 5751 that->setMachineState 5747 that->setMachineState(MachineState_Saved); 5752 5748 break; 5753 5749 } 5754 5755 5750 break; 5756 5751 } … … 5758 5753 case VMSTATE_SUSPENDED: 5759 5754 { 5760 if (aOldState == VMSTATE_RUNNING) 5755 /** @todo state/live VMSTATE_SUSPENDING_LS. */ 5756 if ( aOldState == VMSTATE_SUSPENDING) 5761 5757 { 5762 5758 AutoWriteLock alock(that); … … 5765 5761 break; 5766 5762 5767 /* Change the machine state from Running to Paused */5768 Assert 5769 that->setMachineState 5763 /* Change the machine state from Running to Paused. */ 5764 AssertBreak(that->mMachineState == MachineState_Running); 5765 that->setMachineState(MachineState_Paused); 5770 5766 } 5771 5772 5767 break; 5773 5768 } … … 5775 5770 case VMSTATE_RUNNING: 5776 5771 { 5777 if ( aOldState == VMSTATE_CREATED ||5778 aOldState == VMSTATE_SUSPENDED)5772 if ( aOldState == VMSTATE_POWERING_ON 5773 || aOldState == VMSTATE_RESUMING) 5779 5774 { 5780 5775 AutoWriteLock alock(that); … … 5787 5782 Assert ( ( ( that->mMachineState == MachineState_Starting 5788 5783 || that->mMachineState == MachineState_Paused) 5789 && aOldState == VMSTATE_ CREATED)5784 && aOldState == VMSTATE_POWERING_ON) 5790 5785 || ( ( that->mMachineState == MachineState_Restoring 5791 5786 || that->mMachineState == MachineState_Paused) 5792 && aOldState == VMSTATE_ SUSPENDED));5787 && aOldState == VMSTATE_RESUMING)); 5793 5788 5794 5789 that->setMachineState (MachineState_Running); … … 5813 5808 * visible state for this yet. */ 5814 5809 that->setMachineState(MachineState_Paused); 5815 5816 5810 break; 5817 5811 } … … 5825 5819 5826 5820 /* 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); 5831 5824 break; 5832 5825 } -
trunk/src/VBox/VMM/PGMPhys.cpp
r22947 r23009 1720 1720 1721 1721 /* 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 1726 1733 /*rc = MMHyperFree(pVM, pCur); 1727 1734 AssertRCReturn(rc, rc); - not safe, see the alloc call. */ -
trunk/src/VBox/VMM/VM.cpp
r23001 r23009 133 133 static int vmR3InitDoCompleted(PVM pVM, VMINITCOMPLETED enmWhat); 134 134 static 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);141 135 static DECLCALLBACK(int) vmR3PowerOff(PVM pVM); 142 136 static void vmR3DestroyUVM(PUVM pUVM, uint32_t cMilliesEMTWait); 143 137 static void vmR3AtDtor(PVM pVM); 144 static DECLCALLBACK(int) vmR3Reset(PVM pVM); 138 static bool vmR3ValidateStateTransition(VMSTATE enmStateOld, VMSTATE enmStateNew); 139 static void vmR3DoAtState(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld); 140 static bool vmR3TrySetState(PVM pVM, VMSTATE enmStateNew, VMSTATE enmStateOld); 141 static unsigned vmR3TrySetState2(PVM pVM, VMSTATE enmStateNew1, VMSTATE enmStateOld1, VMSTATE enmStateNew2, VMSTATE enmStateOld2); 142 static void vmR3SetStateLocked(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld); 143 static void vmR3SetState(PVM pVM, VMSTATE enmStateNew, VMSTATE enmStateOld); 144 static unsigned vmR3SetState2(PVM pVM, VMSTATE enmStateNew1, VMSTATE enmStateOld1, VMSTATE enmStateNew2, VMSTATE enmStateOld2); 145 145 static int vmR3SetErrorU(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...); 146 146 … … 241 241 */ 242 242 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); 245 245 if (RT_SUCCESS(rc)) 246 246 { … … 258 258 } 259 259 else 260 AssertMsgFailed(("VMR3ReqCall failed rc=%Rrc\n", rc));260 AssertMsgFailed(("VMR3ReqCallU failed rc=%Rrc\n", rc)); 261 261 262 262 /* … … 674 674 * Set the state and link into the global list. 675 675 */ 676 vmR3SetState(pVM, VMSTATE_CREATED );676 vmR3SetState(pVM, VMSTATE_CREATED, VMSTATE_CREATING); 677 677 pUVM->pNext = g_pUVMsHead; 678 678 g_pUVMsHead = pUVM; … … 765 765 { 766 766 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, 768 768 (PFNRT)vmR3RegisterEMT, 2, pVM, idCpu); 769 769 if (RT_SUCCESS(rc)) … … 1143 1143 * @returns VBox error code on failure. 1144 1144 * @param pVM VM to power on. 1145 * @thread Any thread.1146 * @vmstate Created1147 * @vmstateto Running1148 */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.1184 1145 * @thread EMT 1185 1146 */ … … 1199 1160 1200 1161 /* 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); 1208 1167 1209 1168 /* 1210 1169 * Change the state, notify the components and resume the execution. 1211 1170 */ 1212 vmR3SetState(pVM, VMSTATE_RUNNING);1213 1171 PDMR3PowerOn(pVM); 1172 vmR3SetState(pVM, VMSTATE_RUNNING, VMSTATE_POWERING_ON); 1214 1173 1215 1174 return VINF_SUCCESS; … … 1218 1177 1219 1178 /** 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 */ 1189 VMMR3DECL(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 */ 1224 static 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 */ 1285 static 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 /** 1220 1305 * Suspends a running VM. 1221 1306 * 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 * 1225 1312 * @thread Any thread. 1226 * @vmstate Running 1227 * @vmstateto Suspend ed1313 * @vmstate Running or RunningLS 1314 * @vmstateto Suspending + Suspended or SuspendingLS + SuspendedLS 1228 1315 */ 1229 1316 VMMR3DECL(int) VMR3Suspend(PVM pVM) 1230 1317 { 1231 1318 LogFlow(("VMR3Suspend: pVM=%p\n", pVM)); 1232 1233 /*1234 * Validate input and pass it on to the internal worker.1235 */1236 1319 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1237 1320 int rc = vmR3SuspendCommon(pVM, false /*fFatal*/); 1238 1239 1321 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_ERROR1248 * 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 Running1256 * @vmstateto Suspended, FatalError1257 */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 else1272 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 EMT1286 */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 Suspended1323 * @vmstateto Running1324 */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 else1349 Assert(pReq == NULL);1350 1351 LogFlow(("VMR3Resume: returns %Rrc\n", rc));1352 1322 return rc; 1353 1323 } … … 1366 1336 LogFlow(("vmR3Resume: pVM=%p\n", pVM)); 1367 1337 1338 /* 1339 * EMT(0) does all the work *before* the others wake up. 1340 */ 1368 1341 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 */ 1380 VMMR3DECL(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 */ 1417 static 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)); 1372 1420 1373 1421 /* 1374 1422 * Validate input. 1375 1423 */ 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 */ 1458 static 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; 1390 1468 } 1391 1469 … … 1396 1474 * Can be used for both saving the state and creating snapshots. 1397 1475 * 1398 * When called for a VM in the R UNNINGstate, the saved state is created live1476 * When called for a VM in the Running state, the saved state is created live 1399 1477 * and the VM is only suspended when the final part of the saving is preformed. 1400 * The VM state will not be restored to R UNNINGin this case and it's up to the1478 * The VM state will not be restored to Running in this case and it's up to the 1401 1479 * caller to call VMR3Resume if this is desirable. (The rational is that the 1402 1480 * caller probably wish to reconfigure the disks before resuming the VM.) … … 1404 1482 * @returns VBox status code. 1405 1483 * 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. 1410 1488 * @param pfnProgress Progress callback. Optional. 1411 1489 * @param pvUser User argument for the progress callback. 1412 1490 * 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. 1416 1495 */ 1417 1496 VMMR3DECL(int) VMR3Save(PVM pVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser) … … 1424 1503 */ 1425 1504 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1505 VM_ASSERT_OTHER_THREAD(pVM); 1426 1506 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 1427 1507 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER); … … 1434 1514 PSSMHANDLE pSSM; 1435 1515 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); 1438 1518 if (RT_SUCCESS(rc)) 1439 1519 { … … 1444 1524 && pSSM) 1445 1525 { 1446 #if 1 1447 /**@todo*/ rc = VERR_NOT_IMPLEMENTED; 1448 #else 1526 #if 0 /** @todo later*/ 1449 1527 /* 1450 1528 * Live snapshot. … … 1453 1531 if (RT_SUCCESS(rc)) 1454 1532 { 1455 rc = VMR3ReqCall(pVM, 0 /* VCPU 0 */, &pReq, RT_INDEFINITE_WAIT, 1456 (PFNRT)vmR3SaveLive, 2, pVM, pSSM); 1533 rc = vmR3SuspendCommon(pVM, false /*fFatal*/); 1457 1534 if (RT_SUCCESS(rc)) 1458 1535 { 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 } 1461 1543 } 1462 1544 } 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); 1463 1588 #endif 1464 1589 } … … 1470 1595 1471 1596 /** 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 a1482 * live snapshot scenario.1483 * @thread EMT1484 */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_SUSPENDED1495 || 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 else1516 {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 /**1527 1597 * Loads a new VM state. 1528 1598 * … … 1530 1600 * resume the VM instead of powering it on. 1531 1601 * 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. 1586 1605 * @param pfnProgress Progress callback. Optional. 1587 1606 * @param pvUser User argument for the progress callback. … … 1593 1612 1594 1613 /* 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)) 1601 1628 return VMSetError(pVM, VERR_VM_INVALID_VM_STATE, RT_SRC_POS, N_("Invalid VM state (%s) for restoring state from '%s'"), 1602 1629 VMR3GetStateName(pVM->enmVMState), pszFilename); 1603 } 1604 1605 /* 1606 * Change the state and perform the load. 1607 */ 1608 vmR3SetState(pVM, VMSTATE_LOADING); 1630 1609 1631 int rc = SSMR3Load(pVM, pszFilename, SSMAFTER_RESUME, pfnProgress, pvUser); 1610 1632 if (RT_SUCCESS(rc)) 1611 1633 { 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); 1615 1636 } 1616 1637 else 1617 1638 { 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); 1620 1643 } 1621 1644 1622 1645 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 */ 1666 VMMR3DECL(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 */ 1703 static 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; 1623 1832 } 1624 1833 … … 1651 1860 */ 1652 1861 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); 1654 1864 if (RT_SUCCESS(rc)) 1655 1865 { … … 1666 1876 1667 1877 /** 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_RUNNING1683 && pVM->enmVMState != VMSTATE_SUSPENDED1684 && pVM->enmVMState != VMSTATE_LOAD_FAILURE1685 && pVM->enmVMState != VMSTATE_FATAL_ERROR1686 && 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 EMTs1694 * 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 #15891720 RTLogRelPrintf("***\n");1721 uint32_t esp = CPUMGetGuestESP(pVCpu);1722 if ( CPUMGetGuestSS(pVCpu) == 01723 && 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 else1736 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 #endif1758 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 /**1772 1878 * 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. 1775 1883 * 1776 1884 * @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. 1779 1889 * @vmstate Off, Created 1780 1890 * @vmstateto N/A 1781 1891 */ 1782 VMMR3DECL(int) 1892 VMMR3DECL(int) VMR3Destroy(PVM pVM) 1783 1893 { 1784 1894 LogFlow(("VMR3Destroy: pVM=%p\n", pVM)); … … 1789 1899 if (!pVM) 1790 1900 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); 1796 1903 1797 1904 /* 1798 1905 * Change VM state to destroying and unlink the VM. 1799 1906 */ 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); 1801 1910 1802 1911 /** @todo lock this when we start having multiple machines in a process... */ … … 1817 1926 /* 1818 1927 * Notify registered at destruction listeners. 1819 * (That's the debugger console.)1820 1928 */ 1821 1929 vmR3AtDtor(pVM); 1822 1930 1823 1931 /* 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. 1825 1936 */ 1826 1937 if (VMMGetCpuId(pVM) == 0) … … 1830 1941 VM_FF_SET(pVM, VM_FF_TERMINATE); 1831 1942 1832 /* Inform all other VCPUs too. */1943 /* Terminate the other EMTs. */ 1833 1944 for (VMCPUID idCpu = 1; idCpu < pVM->cCpus; idCpu++) 1834 1945 { 1835 /*1836 * Request EMT to do the larger part of the destruction.1837 */1838 1946 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); 1840 1949 if (RT_SUCCESS(rc)) 1841 1950 rc = pReq->iStatus; 1842 Assert RC(rc);1951 AssertLogRelRC(rc); 1843 1952 VMR3ReqFree(pReq); 1844 1953 } … … 1846 1955 else 1847 1956 { 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). */ 1851 1958 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); 1853 1961 if (RT_SUCCESS(rc)) 1854 1962 rc = pReq->iStatus; 1855 Assert RC(rc);1963 AssertLogRelRC(rc); 1856 1964 VMR3ReqFree(pReq); 1857 1965 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. */ 1862 1967 vmR3DestroyUVM(pUVM, 30000); 1863 1968 } … … 1871 1976 * Internal destruction worker. 1872 1977 * 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. 1877 1988 */ 1878 1989 DECLCALLBACK(int) vmR3Destroy(PVM pVM) 1879 1990 { 1880 PUVM pUVM= pVM->pUVM;1991 PUVM pUVM = pVM->pUVM; 1881 1992 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 */ 1894 2005 #if defined(VBOX_WITH_STATISTICS) || defined(LOG_ENABLED) 1895 RTLogFlags(NULL, "nodisabled nobuffered");2006 RTLogFlags(NULL, "nodisabled nobuffered"); 1896 2007 #endif 1897 2008 #ifdef VBOX_WITH_STATISTICS 1898 STAMR3Dump(pVM, "*");2009 STAMR3Dump(pVM, "*"); 1899 2010 #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")); 1903 2014 #endif 1904 2015 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); 1910 2021 #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; 1913 2024 #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 } 1953 2065 return VINF_EM_TERMINATE; 1954 2066 } … … 1956 2068 1957 2069 /** 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. 1961 2077 * 1962 2078 * @param pUVM The UVM handle. 1963 */ 1964 void vmR3DestroyFinalBitFromEMT(PUVM pUVM) 1965 { 2079 * @param idCpu The virtual CPU id. 2080 */ 2081 void 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 */ 1966 2095 if (pUVM->pVM) 1967 2096 { 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); 1983 2098 int rc = SUPR3CallVMMR0Ex(pUVM->pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL); 1984 Assert RC(rc);2099 AssertLogRelRC(rc); 1985 2100 pUVM->pVM = NULL; 1986 2101 } 1987 2102 1988 2103 /* 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. 1990 2105 */ 1991 2106 if (pUVM->vm.s.fEMTDoesTheCleanup) … … 1998 2113 * 1999 2114 * 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, meaning2115 * in case of a creation failure. If EMT(0) called VMR3Destroy, meaning 2001 2116 * VMINTUSERPERVM::fEMTDoesTheCleanup is true, it will call this as 2002 2117 * vmR3DestroyFinalBitFromEMT completes. … … 2275 2390 2276 2391 /** 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_RUNNING2292 && 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 thread2300 * 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 /**2314 2392 * Worker which checks integrity of some internal structures. 2315 2393 * This is yet another attempt to track down that AVL tree crash. … … 2338 2416 2339 2417 /* 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 /* 2340 2457 * EMT(0) does the full cleanup *after* all the other EMTs has been 2341 2458 * 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. */ 2343 2467 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED); 2344 2468 … … 2346 2470 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_ALL_MASK & ~VMCPU_FF_REQUEST); 2347 2471 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 2364 2472 /* 2365 2473 * Reset the VM components. 2366 2474 */ 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. */ 2381 2495 2382 2496 #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); 2388 2502 #endif 2389 2503 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 } 2396 2517 2397 2518 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 */ 2528 VMMR3DECL(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; 2398 2547 } 2399 2548 … … 2426 2575 case VMSTATE_LOADING: return "LOADING"; 2427 2576 case VMSTATE_POWERING_ON: return "POWERING_ON"; 2577 case VMSTATE_RESUMING: return "RESUMING"; 2428 2578 case VMSTATE_RUNNING: return "RUNNING"; 2429 2579 case VMSTATE_RUNNING_LS: return "RUNNING_LS"; … … 2431 2581 case VMSTATE_RESETTING_LS: return "RESETTING_LS"; 2432 2582 case VMSTATE_SUSPENDED: return "SUSPENDED"; 2583 case VMSTATE_SUSPENDED_LS: return "SUSPENDED_LS"; 2584 case VMSTATE_SUSPENDING: return "SUSPENDING"; 2433 2585 case VMSTATE_SUSPENDING_LS: return "SUSPENDING_LS"; 2434 2586 case VMSTATE_SAVING: return "SAVING"; … … 2454 2606 2455 2607 /** 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. 2457 2614 */ 2458 2615 static bool vmR3ValidateStateTransition(VMSTATE enmStateOld, VMSTATE enmStateNew) … … 2479 2636 2480 2637 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: 2481 2644 AssertMsgReturn( enmStateNew == VMSTATE_RUNNING 2482 2645 || enmStateNew == VMSTATE_FATAL_ERROR /*?*/ … … 2526 2689 || enmStateNew == VMSTATE_SAVING 2527 2690 || enmStateNew == VMSTATE_RESETTING 2528 || enmStateNew == VMSTATE_RUNNING 2691 || enmStateNew == VMSTATE_RESUMING 2692 || enmStateNew == VMSTATE_LOADING 2529 2693 , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false); 2530 2694 break; … … 2541 2705 2542 2706 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: 2543 2713 AssertMsgReturn( enmStateNew == VMSTATE_RUNNING_LS 2544 2714 || enmStateNew == VMSTATE_POWERING_OFF_LS … … 2551 2721 2552 2722 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); 2554 2726 break; 2555 2727 … … 2558 2730 break; 2559 2731 2732 case VMSTATE_OFF_LS: 2733 AssertMsgReturn(enmStateNew == VMSTATE_OFF, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false); 2734 break; 2735 2560 2736 case VMSTATE_FATAL_ERROR: 2561 2737 AssertMsgReturn(enmStateNew == VMSTATE_POWERING_OFF, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false); … … 2563 2739 2564 2740 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); 2566 2744 break; 2567 2745 … … 2573 2751 2574 2752 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); 2576 2756 break; 2577 2757 … … 2595 2775 2596 2776 /** 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 */ 2786 static void vmR3DoAtState(PVM pVM, PUVM pUVM, VMSTATE enmStateNew, VMSTATE enmStateOld) 2787 { 2616 2788 LogRel(("Changing the VM state from '%s' to '%s'.\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew))); 2617 2789 2618 /*2619 * Call the at state change callbacks.2620 */2621 RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);2622 2790 for (PVMATSTATE pCur = pUVM->vm.s.pAtState; pCur; pCur = pCur->pNext) 2623 2791 { 2624 2792 pCur->pfnAtState(pVM, enmStateNew, enmStateOld, pCur->pvUser); 2625 if ( pVM->enmVMState != enmStateNew2793 if ( enmStateNew != VMSTATE_DESTROYING 2626 2794 && pVM->enmVMState == VMSTATE_DESTROYING) 2627 2795 break; … … 2632 2800 "difficult to follow.\n")); 2633 2801 } 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 */ 2813 static 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 */ 2832 static 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 } 2634 2850 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 */ 2865 static 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 */ 2900 static 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 */ 2923 static 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 */ 2964 void 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); 2635 2970 } 2636 2971 … … 2648 2983 * @thread Any. 2649 2984 */ 2650 VMMR3DECL(int) 2985 VMMR3DECL(int) VMR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser) 2651 2986 { 2652 2987 LogFlow(("VMR3AtStateRegister: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser)); … … 3139 3474 rc = vmR3SuspendCommon(pVM, true /*fFatal*/); 3140 3475 else if (fFlags & VMSETRTERR_FLAGS_SUSPEND) 3141 rc = VMR3Suspend(pVM);3476 rc = vmR3SuspendCommon(pVM, false /*fFatal*/); 3142 3477 3143 3478 /* -
trunk/src/VBox/VMM/VMEmt.cpp
r21144 r23009 224 224 && pUVM->pVM) 225 225 { 226 PVM pVM = pUVM->pVM;227 PVMCPU pVCpu = &pVM->aCpus[idCpu];226 PVM pVM = pUVM->pVM; 227 PVMCPU pVCpu = &pVM->aCpus[idCpu]; 228 228 if ( pVM->enmVMState == VMSTATE_RUNNING 229 229 && VMCPUSTATE_IS_STARTED(VMCPU_GET_STATE(pVCpu))) … … 231 231 rc = EMR3ExecuteVM(pVM, pVCpu); 232 232 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); 236 235 } 237 236 } … … 241 240 242 241 /* 243 * Exiting. 242 * Cleanup and exit. 243 * If EMT(0) called VMR3Destroy, EMT(0) will do all the terminating here. 244 244 */ 245 245 Log(("vmR3EmulationThread: Terminating emulation thread! Thread=%#x pUVM=%p rc=%Rrc enmBefore=%d enmVMState=%d\n", 246 246 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) 248 249 { 249 250 Log(("vmR3EmulationThread: executing delayed Destroy\n")); 250 251 Assert(pUVM->pVM); 251 252 vmR3Destroy(pUVM->pVM); 252 vmR3DestroyFinalBitFromEMT(pUVM); 253 vmR3DestroyFinalBitFromEMT(pUVM, idCpu); 254 /* The pUVM structure is now invliad. */ 255 pUVCpu = NULL; 256 pUVM = NULL; 253 257 } 254 258 else 255 259 { 256 vmR3DestroyFinalBitFromEMT(pUVM); 257 260 vmR3DestroyFinalBitFromEMT(pUVM, idCpu); 258 261 pUVCpu->vm.s.NativeThreadEMT = NIL_RTNATIVETHREAD; 259 262 } -
trunk/src/VBox/VMM/VMInternal.h
r22986 r23009 166 166 /** VM Runtime Error Message. */ 167 167 R3PTRTYPE(PVMRUNTIMEERROR) pRuntimeErrorR3; 168 /** Set by VMR3SuspendNoSave; cleared by VMR3Resume; signals the VM is in an169 * inconsistent state and saving is not allowed. */170 bool fPreventSaveState;171 168 } VMINT; 172 169 /** Pointer to the VM Internal Data (part of the VM structure). */ … … 207 204 /** Force EMT to terminate. */ 208 205 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. 210 207 * If clear the VMR3Destroy() caller does so. */ 211 208 bool fEMTDoesTheCleanup; 212 209 213 /** Critical section for pAtState . */210 /** Critical section for pAtState and enmPrevVMState. */ 214 211 RTCRITSECT AtStateCritSect; 215 212 /** List of registered state change callbacks. */ … … 217 214 /** List of registered state change callbacks. */ 218 215 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; 219 220 220 221 /** Critical section for pAtError and pAtRuntimeError. */ … … 416 417 DECLCALLBACK(int) vmR3SetRuntimeErrorV(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list *pVa); 417 418 void vmSetRuntimeErrorCopy(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va); 418 void vmR3DestroyFinalBitFromEMT(PUVM pUVM );419 void vmR3Set State(PVM pVM, VMSTATE enmStateNew);419 void vmR3DestroyFinalBitFromEMT(PUVM pUVM, VMCPUID idCpu); 420 void vmR3SetGuruMeditation(PVM pVM); 420 421 421 422 RT_C_DECLS_END
Note:
See TracChangeset
for help on using the changeset viewer.