Changeset 23148 in vbox
- Timestamp:
- Sep 18, 2009 9:53:15 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VM.cpp
r23146 r23148 1130 1130 1131 1131 /** 1132 * Power on the virtual machine. 1133 * 1134 * @returns 0 on success. 1135 * @returns VBox error code on failure. 1136 * @param pVM VM to power on. 1137 * @thread EMT 1138 */ 1139 static DECLCALLBACK(int) vmR3PowerOn(PVM pVM) 1140 { 1141 LogFlow(("vmR3PowerOn: pVM=%p\n", pVM)); 1142 1143 /* 1144 * EMT(0) does the actual power on work *before* the other EMTs 1145 * get here, they just need to set their state to STARTED so they 1146 * get out of the EMT loop and into EM. 1147 */ 1148 PVMCPU pVCpu = VMMGetCpu(pVM); 1132 * EMT rendezvous worker for VMR3PowerOn. 1133 * 1134 * @returns VERR_VM_INVALID_VM_STATE or VINF_SUCCESS. (This is a strict return 1135 * code, see FNVMMEMTRENDEZVOUS.) 1136 * 1137 * @param pVM The VM handle. 1138 * @param pVCpu The VMCPU handle of the EMT. 1139 * @param pvUser Ignored. 1140 */ 1141 static DECLCALLBACK(VBOXSTRICTRC) vmR3PowerOn(PVM pVM, PVMCPU pVCpu, void *pvUser) 1142 { 1143 LogFlow(("vmR3PowerOn: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu)); 1144 Assert(!pvUser); NOREF(pvUser); 1145 1146 /* 1147 * The first thread thru here tries to change the state. We shouldn't be 1148 * called again if this fails. 1149 */ 1150 if (pVCpu->idCpu == pVM->cCpus - 1) 1151 { 1152 int rc = vmR3TrySetState(pVM, "VMR3PowerOn", 1, VMSTATE_POWERING_ON, VMSTATE_CREATED); 1153 if (RT_FAILURE(rc)) 1154 return rc; 1155 } 1156 1157 VMSTATE enmVMState = VMR3GetState(pVM); 1158 AssertMsgReturn(enmVMState == VMSTATE_POWERING_ON, 1159 ("%s\n", VMR3GetStateName(enmVMState)), 1160 VERR_INTERNAL_ERROR_4); 1161 1162 /* 1163 * All EMTs changes their state to started. 1164 */ 1149 1165 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED); 1150 if (pVCpu->idCpu != 0) 1151 return VINF_SUCCESS; 1152 1153 /* 1154 * Try change the state. 1155 */ 1156 int rc = vmR3TrySetState(pVM, "VMR3PowerOff", 1, VMSTATE_POWERING_ON, VMSTATE_CREATED); 1157 if (RT_FAILURE(rc)) 1158 return rc; 1159 1160 /* 1161 * Change the state, notify the components and resume the execution. 1162 */ 1163 PDMR3PowerOn(pVM); 1164 vmR3SetState(pVM, VMSTATE_RUNNING, VMSTATE_POWERING_ON); 1166 1167 /* 1168 * EMT(0) is last thru here and it will make the notification calls 1169 * and advance the state. 1170 */ 1171 if (pVCpu->idCpu == 0) 1172 { 1173 PDMR3PowerOn(pVM); 1174 vmR3SetState(pVM, VMSTATE_RUNNING, VMSTATE_POWERING_ON); 1175 } 1165 1176 1166 1177 return VINF_SUCCESS; … … 1177 1188 * @thread Any thread. 1178 1189 * @vmstate Created 1179 * @vmstateto PoweringOn ,Running1190 * @vmstateto PoweringOn+Running 1180 1191 */ 1181 1192 VMMR3DECL(int) VMR3PowerOn(PVM pVM) … … 1185 1196 1186 1197 /* 1187 * Forward the request to the EMTs (EMT(0) first as it does all the 1188 * work upfront). 1189 */ 1190 int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL, (PFNRT)vmR3PowerOn, 1, pVM); 1191 LogFlow(("VMR3PowerOn: returns %Rrc\n", rc)); 1198 * Gather all the EMTs to reduce the init TSC drift and keep . 1199 * the state changing APIs a bit uniform. 1200 */ 1201 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR, 1202 vmR3PowerOn, NULL); 1203 LogFlow(("VMR3Suspend: returns %Rrc\n", rc)); 1192 1204 return rc; 1193 1205 } … … 1207 1219 1208 1220 /** 1209 * EMT worker for VMR3Suspend. 1210 * 1211 * @returns VBox strict status code. 1212 * @retval VINF_EM_SUSPEND. 1213 * @retval VERR_VM_INVALID_VM_STATE. 1214 * 1215 * @param pVM The VM to suspend. 1216 * @param pvUser Our fFatal flag. 1217 * 1218 * @thread EMT 1221 * EMT rendezvous worker for VMR3Suspend. 1222 * 1223 * @returns VERR_VM_INVALID_VM_STATE or VINF_EM_SUSPEND. (This is a strict 1224 * return code, see FNVMMEMTRENDEZVOUS.) 1225 * 1226 * @param pVM The VM handle. 1227 * @param pVCpu The VMCPU handle of the EMT. 1228 * @param pvUser Ignored. 1219 1229 */ 1220 1230 static DECLCALLBACK(VBOXSTRICTRC) vmR3Suspend(PVM pVM, PVMCPU pVCpu, void *pvUser) 1221 1231 { 1222 #if 01223 if (!pVCpu) pVCpu = VMMGetCpu(pVM);1224 #endif1225 1232 LogFlow(("vmR3Suspend: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu)); 1226 Assert(!pvUser); 1227 Assert(pVCpu); 1233 Assert(!pvUser); NOREF(pvUser); 1228 1234 1229 1235 /* … … 1283 1289 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1284 1290 1285 #if 0 /* if the code below screws up, this should still work */1286 /*1287 * Forward the operation to EMT in reverse order so EMT(0) can do the1288 * actual suspending after the other ones have stopped running guest code.1289 */1290 int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL_REVERSE,1291 (PFNRT)vmR3Suspend, 3, pVM, NULL, NULL);1292 #else1293 1291 /* 1294 1292 * Gather all the EMTs to make sure there are no races before … … 1297 1295 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR, 1298 1296 vmR3Suspend, NULL); 1299 #endif1300 1301 1297 LogFlow(("VMR3Suspend: returns %Rrc\n", rc)); 1302 1298 return rc; … … 1305 1301 1306 1302 /** 1307 * Resume VM execution. 1308 * 1309 * @returns 0 on success. 1310 * @returns VBox error code on failure. 1311 * @param pVM The VM to resume. 1312 * @thread EMT 1313 */ 1314 static DECLCALLBACK(int) vmR3Resume(PVM pVM) 1315 { 1316 LogFlow(("vmR3Resume: pVM=%p\n", pVM)); 1317 1318 /* 1319 * EMT(0) does all the work *before* the others wake up. 1320 */ 1321 PVMCPU pVCpu = VMMGetCpu(pVM); 1322 if (pVCpu->idCpu == 0) 1303 * EMT rendezvous worker for VMR3Resume. 1304 * 1305 * @returns VERR_VM_INVALID_VM_STATE or VINF_EM_RESUME. (This is a strict 1306 * return code, see FNVMMEMTRENDEZVOUS.) 1307 * 1308 * @param pVM The VM handle. 1309 * @param pVCpu The VMCPU handle of the EMT. 1310 * @param pvUser Ignored. 1311 */ 1312 static DECLCALLBACK(VBOXSTRICTRC) vmR3Resume(PVM pVM, PVMCPU pVCpu, void *pvUser) 1313 { 1314 LogFlow(("vmR3Resume: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu)); 1315 Assert(!pvUser); NOREF(pvUser); 1316 1317 /* 1318 * The first thread thru here tries to change the state. We shouldn't be 1319 * called again if this fails. 1320 */ 1321 if (pVCpu->idCpu == pVM->cCpus - 1) 1323 1322 { 1324 1323 int rc = vmR3TrySetState(pVM, "VMR3Resume", 1, VMSTATE_RESUMING, VMSTATE_SUSPENDED); 1325 1324 if (RT_FAILURE(rc)) 1326 1325 return rc; 1327 1328 /* Perform resume notifications. */ 1326 } 1327 1328 VMSTATE enmVMState = VMR3GetState(pVM); 1329 AssertMsgReturn(enmVMState == VMSTATE_RESUMING, 1330 ("%s\n", VMR3GetStateName(enmVMState)), 1331 VERR_INTERNAL_ERROR_4); 1332 1333 #if 0 1334 /* 1335 * All EMTs changes their state to started. 1336 */ 1337 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED); 1338 #endif 1339 1340 /* 1341 * EMT(0) is last thru here and it will make the notification calls 1342 * and advance the state. 1343 */ 1344 if (pVCpu->idCpu == 0) 1345 { 1329 1346 PDMR3Resume(pVM); 1330 1331 /* Advance to the final state. */1332 1347 vmR3SetState(pVM, VMSTATE_RUNNING, VMSTATE_RESUMING); 1333 1348 } 1334 1349 1335 /** @todo there is a race here: Someone could suspend, power off, raise a fatal1336 * error (both kinds), save the vm, or start a live save operation before1337 * we get here on all CPUs. Only safe way is a cross call, or to make1338 * the last thread flip the state from Resuming to Running. While the1339 * latter seems easy and perhaps more attractive, the former might be1340 * better wrt TSC/TM... */1341 AssertMsgReturn(VMR3GetState(pVM) == VMSTATE_RUNNING, ("%s\n", VMR3GetStateName(VMR3GetState(pVM))), VERR_VM_INVALID_VM_STATE);1342 1350 return VINF_EM_RESUME; 1343 1351 } 1344 1345 1346 1352 1347 1353 … … 1364 1370 1365 1371 /* 1366 * Forward the request to the EMTs (EMT(0) first as it does all the 1367 * work upfront). 1368 */ 1369 int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL, (PFNRT)vmR3Resume, 1, pVM); 1372 * Gather all the EMTs to make sure there are no races before 1373 * changing the VM state. 1374 */ 1375 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR, 1376 vmR3Resume, NULL); 1370 1377 LogFlow(("VMR3Resume: returns %Rrc\n", rc)); 1371 1378 return rc; … … 1692 1699 1693 1700 /* 1694 * Forward the request to EMT(0). 1701 * Forward the request to EMT(0). No need to setup a rendezvous here 1702 * since there is no execution taking place when this call is allowed. 1695 1703 */ 1696 1704 int rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/, … … 1702 1710 1703 1711 /** 1704 * Worker for VMR3PowerOff that does the actually powering off on EMT(0) after 1705 * cycling thru the other EMTs first. 1706 * 1707 * @returns VBox strict status code. 1708 * 1709 * @param pVM The VM handle. 1710 * @param pVCpu The VMCPU of the EMT. 1711 * @param pvUser Unused user argument. 1712 * 1713 * @thread EMT. 1712 * EMT rendezvous worker for VMR3PowerOff. 1713 * 1714 * @returns VERR_VM_INVALID_VM_STATE or VINF_EM_OFF. (This is a strict 1715 * return code, see FNVMMEMTRENDEZVOUS.) 1716 * 1717 * @param pVM The VM handle. 1718 * @param pVCpu The VMCPU handle of the EMT. 1719 * @param pvUser Ignored. 1714 1720 */ 1715 1721 static DECLCALLBACK(VBOXSTRICTRC) vmR3PowerOff(PVM pVM, PVMCPU pVCpu, void *pvUser) 1716 1722 { 1717 #if 01718 pVCpu = VMMGetCpu(pVM);1719 #endif1720 1723 LogFlow(("vmR3PowerOff: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu)); 1721 NOREF(pvUser);1724 Assert(!pvUser); NOREF(pvUser); 1722 1725 1723 1726 /* … … 1853 1856 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1854 1857 1855 #if 01856 /*1857 * Forward the request to the EMTs in reverse order, making all the other1858 * EMTs stop working before EMT(0) comes and does the actual powering off.1859 */1860 int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL_REVERSE, (PFNRT)vmR3PowerOff, 3, pVM, NULL, NULL);1861 #else1862 1858 /* 1863 1859 * Gather all the EMTs to make sure there are no races before … … 1866 1862 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR, 1867 1863 vmR3PowerOff, NULL); 1868 1869 #endif1870 1864 LogFlow(("VMR3PowerOff: returns %Rrc\n", rc)); 1871 1865 return rc; … … 2391 2385 2392 2386 /** 2393 * Reset request processor. 2394 * 2395 * This is called by the emulation threads as a response to the 2396 * reset request issued by VMR3Reset(). 2397 * 2398 * @returns VBox strict status code. 2399 * @param pVM The VM to reset. 2400 * @param pVCpu The VMCPU of the EMT. 2401 * @param pvUser Unused argument. 2387 * EMT rendezvous worker for VMR3Reset. 2388 * 2389 * This is called by the emulation threads as a response to the reset request 2390 * issued by VMR3Reset(). 2391 * 2392 * @returns VERR_VM_INVALID_VM_STATE, VINF_EM_RESET or VINF_EM_SUSPEND. (This 2393 * is a strict return code, see FNVMMEMTRENDEZVOUS.) 2394 * 2395 * @param pVM The VM handle. 2396 * @param pVCpu The VMCPU handle of the EMT. 2397 * @param pvUser Ignored. 2402 2398 */ 2403 2399 static DECLCALLBACK(VBOXSTRICTRC) vmR3Reset(PVM pVM, PVMCPU pVCpu, void *pvUser) 2404 2400 { 2405 #if 0 2406 pVCpu = VMMGetCpu(pVM); 2407 #endif 2408 Assert(!pvUser); 2409 NOREF(pvUser); 2401 Assert(!pvUser); NOREF(pvUser); 2410 2402 2411 2403 /* … … 2529 2521 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 2530 2522 2531 #if 02532 /*2533 * Forward the query to the EMTs in reverse order, so all the other EMT are2534 * dosile when EMT(0) does the actual resetting.2535 */2536 int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL_REVERSE, (PFNRT)vmR3Reset, 3, pVM, NULL, NULL);2537 #else2538 2523 /* 2539 2524 * Gather all the EMTs to make sure there are no races before … … 2542 2527 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR, 2543 2528 vmR3Reset, NULL); 2544 #endif2545 2529 LogFlow(("VMR3Reset: returns %Rrc\n", rc)); 2546 2530 return rc; … … 2642 2626 case VMSTATE_POWERING_ON: 2643 2627 AssertMsgReturn( enmStateNew == VMSTATE_RUNNING 2644 || enmStateNew == VMSTATE_FATAL_ERROR /*?*/2628 /*|| enmStateNew == VMSTATE_FATAL_ERROR ?*/ 2645 2629 , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false); 2646 2630 break; … … 2648 2632 case VMSTATE_RESUMING: 2649 2633 AssertMsgReturn( enmStateNew == VMSTATE_RUNNING 2650 || enmStateNew == VMSTATE_FATAL_ERROR /*?*/2634 /*|| enmStateNew == VMSTATE_FATAL_ERROR ?*/ 2651 2635 , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false); 2652 2636 break; … … 3471 3455 * code, see FNVMMEMTRENDEZVOUS.) 3472 3456 * 3473 * @param pVM 3474 * @param pVCpu 3475 * @param pvUser Unused user argument.3457 * @param pVM The VM handle. 3458 * @param pVCpu The VMCPU handle of the EMT. 3459 * @param pvUser Ignored. 3476 3460 */ 3477 3461 static DECLCALLBACK(VBOXSTRICTRC) vmR3SetRuntimeErrorChangeState(PVM pVM, PVMCPU pVCpu, void *pvUser) 3478 3462 { 3479 3463 NOREF(pVCpu); 3480 NOREF(pvUser); 3464 Assert(!pvUser); NOREF(pvUser); 3465 3481 3466 int rc = vmR3TrySetState(pVM, "VMSetRuntimeError", 2, 3482 3467 VMSTATE_FATAL_ERROR, VMSTATE_RUNNING,
Note:
See TracChangeset
for help on using the changeset viewer.