Changeset 23151 in vbox for trunk/src/VBox
- Timestamp:
- Sep 18, 2009 11:13:02 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VM.cpp
r23148 r23151 1381 1381 1382 1382 /** 1383 * EMT rendezvous worker for VMR3Save and VMR3Migrate that suspends the VM after 1384 * the live step has been completed. 1385 * 1386 * @returns VERR_VM_INVALID_VM_STATE or VINF_EM_RESUME. (This is a strict 1387 * return code, see FNVMMEMTRENDEZVOUS.) 1388 * 1389 * @param pVM The VM handle. 1390 * @param pVCpu The VMCPU handle of the EMT. 1391 * @param pvUser Ignored. 1392 */ 1393 static DECLCALLBACK(VBOXSTRICTRC) vmR3LiveDoSuspend(PVM pVM, PVMCPU pVCpu, void *pvUser) 1394 { 1395 LogFlow(("vmR3LiveDoSuspend: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu)); 1396 Assert(!pvUser); NOREF(pvUser); 1397 1398 /* 1399 * The first thread thru here tries to change the state. We shouldn't be 1400 * called again if this fails. 1401 */ 1402 if (pVCpu->idCpu == pVM->cCpus - 1U) 1403 { 1404 PUVM pUVM = pVM->pUVM; 1405 int rc; 1406 1407 RTCritSectEnter(&pUVM->vm.s.AtStateCritSect); 1408 VMSTATE enmVMState = pVM->enmVMState; 1409 switch (enmVMState) 1410 { 1411 case VMSTATE_RUNNING_LS: 1412 vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDING_LS, VMSTATE_RUNNING_LS); 1413 rc = VINF_SUCCESS; 1414 break; 1415 1416 case VMSTATE_SUSPENDED_EXT_LS: 1417 case VMSTATE_SUSPENDED_LS: /* (via reset) */ 1418 rc = VINF_SUCCESS; 1419 break; 1420 1421 case VMSTATE_DEBUGGING_LS: 1422 rc = VERR_TRY_AGAIN; 1423 break; 1424 1425 case VMSTATE_OFF_LS: 1426 vmR3SetStateLocked(pVM, pUVM, VMSTATE_OFF, VMSTATE_OFF_LS); 1427 rc = VERR_SSM_LIVE_POWERED_OFF; 1428 break; 1429 1430 case VMSTATE_FATAL_ERROR_LS: 1431 vmR3SetStateLocked(pVM, pUVM, VMSTATE_FATAL_ERROR, VMSTATE_FATAL_ERROR_LS); 1432 rc = VERR_SSM_LIVE_FATAL_ERROR; 1433 break; 1434 1435 case VMSTATE_GURU_MEDITATION_LS: 1436 vmR3SetStateLocked(pVM, pUVM, VMSTATE_GURU_MEDITATION, VMSTATE_GURU_MEDITATION_LS); 1437 rc = VERR_SSM_LIVE_GURU_MEDITATION; 1438 break; 1439 1440 case VMSTATE_POWERING_OFF_LS: 1441 case VMSTATE_SUSPENDING_EXT_LS: 1442 case VMSTATE_RESETTING_LS: 1443 default: 1444 AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState))); 1445 rc = VERR_INTERNAL_ERROR_3; 1446 break; 1447 } 1448 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect); 1449 if (RT_FAILURE(rc)) 1450 { 1451 LogFlow(("vmR3LiveDoSuspend: returns %Rrc (state was %s)\n", rc, VMR3GetStateName(enmVMState))); 1452 return rc; 1453 } 1454 } 1455 1456 VMSTATE enmVMState = VMR3GetState(pVM); 1457 AssertMsgReturn(enmVMState == VMSTATE_SUSPENDING_LS, 1458 ("%s\n", VMR3GetStateName(enmVMState)), 1459 VERR_INTERNAL_ERROR_4); 1460 1461 /* 1462 * Only EMT(0) have work to do since it's last thru here. 1463 */ 1464 if (pVCpu->idCpu == 0) 1465 { 1466 vmR3SuspendDoWork(pVM); 1467 int rc = vmR3TrySetState(pVM, "VMR3Suspend", 2, 1468 VMSTATE_SUSPENDED_LS, VMSTATE_SUSPENDING_LS); 1469 if (RT_FAILURE(rc)) 1470 return VERR_INTERNAL_ERROR_3; 1471 } 1472 1473 return VINF_EM_SUSPEND; 1474 } 1475 1476 1477 /** 1478 * EMT rendezvous worker that VMR3Save and VMR3Migrate uses to clean up a 1479 * SSMR3LiveDoStep1 failure. 1480 * 1481 * Doing this as a rendezvous operation avoids all annoying transition 1482 * states. 1483 * 1484 * @returns VERR_VM_INVALID_VM_STATE, VINF_SUCCESS or some specific VERR_SSM_* 1485 * status code. (This is a strict return code, see FNVMMEMTRENDEZVOUS.) 1486 * 1487 * @param pVM The VM handle. 1488 * @param pVCpu The VMCPU handle of the EMT. 1489 * @param pvUser Ignored. 1490 */ 1491 static DECLCALLBACK(VBOXSTRICTRC) vmR3LiveDoStep1Cleanup(PVM pVM, PVMCPU pVCpu, void *pvUser) 1492 { 1493 LogFlow(("vmR3LiveDoStep1Cleanup: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu)); 1494 NOREF(pvUser); NOREF(pVCpu); 1495 1496 int rc = vmR3TrySetState(pVM, "vmR3LiveDoStep1Cleanup", 8, 1497 VMSTATE_OFF, VMSTATE_OFF_LS, 1498 VMSTATE_FATAL_ERROR, VMSTATE_FATAL_ERROR_LS, 1499 VMSTATE_GURU_MEDITATION, VMSTATE_GURU_MEDITATION_LS, 1500 VMSTATE_RUNNING, VMSTATE_RUNNING_LS, 1501 VMSTATE_SUSPENDED, VMSTATE_SUSPENDED_EXT_LS, 1502 VMSTATE_DEBUGGING, VMSTATE_DEBUGGING_LS); 1503 if (rc == 1) 1504 rc = VERR_SSM_LIVE_POWERED_OFF; 1505 else if (rc == 2) 1506 rc = VERR_SSM_LIVE_FATAL_ERROR; 1507 else if (rc == 3) 1508 rc = VERR_SSM_LIVE_GURU_MEDITATION; 1509 else if (rc > 0) 1510 rc = VINF_SUCCESS; 1511 return rc; 1512 } 1513 1514 1515 /** 1516 * EMT(0) worker for VMR3Save and VMR3Migrate that completes the live save. 1517 * 1518 * @returns VBox status code. 1519 * @retval VINF_SSM_LIVE_SUSPENDED if VMR3Suspend was called. 1520 * 1521 * @param pVM The VM handle. 1522 * @param pSSM The handle of saved state operation. 1523 * 1524 * @thread EMT(0) 1525 */ 1526 static DECLCALLBACK(int) vmR3LiveDoStep2(PVM pVM, PSSMHANDLE pSSM) 1527 { 1528 LogFlow(("vmR3LiveDoStep2: pVM=%p pSSM=%p\n", pVM, pSSM)); 1529 VM_ASSERT_EMT0(pVM); 1530 1531 /* 1532 * Advance the state and mark if VMR3Suspend was called. 1533 */ 1534 int rc = VINF_SUCCESS; 1535 if (VMR3GetState(pVM) == VMSTATE_SUSPENDED_LS) 1536 vmR3SetState(pVM, VMSTATE_SAVING, VMSTATE_SUSPENDED_LS); 1537 else 1538 { 1539 vmR3SetState(pVM, VMSTATE_SAVING, VMSTATE_SUSPENDED_EXT_LS); 1540 rc = VINF_SSM_LIVE_SUSPENDED; 1541 } 1542 1543 /* 1544 * Finish up and release the handle. Careful with the status codes. 1545 */ 1546 int rc2 = SSMR3LiveDoStep2(pSSM); 1547 if (rc == VINF_SUCCESS || (RT_FAILURE(rc2) && RT_SUCCESS(rc))) 1548 rc = rc2; 1549 1550 rc2 = SSMR3LiveDone(pSSM); 1551 if (rc == VINF_SUCCESS || (RT_FAILURE(rc2) && RT_SUCCESS(rc))) 1552 rc = rc2; 1553 1554 /* 1555 * Advance to the final state and return. 1556 */ 1557 vmR3SetState(pVM, VMSTATE_SUSPENDED, VMSTATE_SAVING); 1558 Assert(rc > VINF_EM_LAST || rc < VINF_EM_FIRST); 1559 return rc; 1560 } 1561 1562 1563 /** 1383 1564 * Worker for VMR3Save that validates the state and calls SSMR3Save. 1384 1565 * … … 1430 1611 1431 1612 /** 1432 * Worker for VMR3Save to clean up a SSMR3LiveDoStep1 failure.1433 *1434 * We failed after hitting the RunningLS state, but before trying to suspend the1435 * VM before vmR3SaveLiveStep2. There are a number of state transisions in this1436 * state, some, like ResetLS, that requires some special handling. (ResetLS is1437 * the excuse for doing this all on EMT(0).1438 *1439 * @returns VBox status code.1440 *1441 * @param pVM The VM handle.1442 * @param pSSM The handle of saved state operation. This will be1443 * closed.1444 * @thread EMT(0)1445 */1446 static DECLCALLBACK(int) vmR3SaveLiveStep1Cleanup(PVM pVM, PSSMHANDLE pSSM)1447 {1448 LogFlow(("vmR3SaveLiveStep2: pVM=%p pSSM=%p\n", pVM, pSSM));1449 VM_ASSERT_EMT0(pVM);1450 1451 /*1452 * Finish the SSM state first (or move the ssmR3SetCancellable call),1453 * then change the state out of the *LS variants.1454 */1455 int rc = SSMR3LiveDone(pSSM);1456 int rc2 = vmR3TrySetState(pVM, "vmR3SaveLiveStep1Cleanup", 8,1457 VMSTATE_RUNNING, VMSTATE_RUNNING_LS,1458 // VMSTATE_RUNNING, VMSTATE_RESET_LS,1459 VMSTATE_SUSPENDING, VMSTATE_SUSPENDING_LS, /* external*/1460 VMSTATE_GURU_MEDITATION, VMSTATE_GURU_MEDITATION_LS,1461 VMSTATE_FATAL_ERROR, VMSTATE_FATAL_ERROR_LS,1462 VMSTATE_POWERING_OFF, VMSTATE_POWERING_OFF_LS,1463 VMSTATE_OFF, VMSTATE_OFF_LS,1464 VMSTATE_DEBUGGING, VMSTATE_DEBUGGING_LS);1465 if (RT_SUCCESS(rc))1466 {1467 if (RT_SUCCESS(rc2))1468 rc = rc2 == 2 /* ResetLS -> Running */ ? VINF_EM_RESUME : VINF_SUCCESS;1469 else1470 rc = rc2;1471 }1472 return rc;1473 }1474 1475 1476 /**1477 * Worker for VMR3Save continues a live save on EMT(0).1478 *1479 * @returns VBox status code.1480 *1481 * @param pVM The VM handle.1482 * @param pSSM The handle of saved state operation.1483 * @thread EMT(0)1484 */1485 static DECLCALLBACK(int) vmR3SaveLiveStep2(PVM pVM, PSSMHANDLE pSSM)1486 {1487 LogFlow(("vmR3SaveLiveStep2: pVM=%p pSSM=%p\n", pVM, pSSM));1488 VM_ASSERT_EMT0(pVM);1489 1490 vmR3SetState(pVM, VMSTATE_SAVING, VMSTATE_SUSPENDED_LS);1491 1492 int rc = SSMR3LiveDoStep2(pSSM);1493 int rc2 = SSMR3LiveDone(pSSM);1494 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))1495 rc = rc2;1496 1497 vmR3SetState(pVM, VMSTATE_SUSPENDED, VMSTATE_SAVING);1498 1499 return rc;1500 }1501 1502 1503 1504 /**1505 1613 * Save current VM state. 1506 1614 * … … 1555 1663 * 1556 1664 * The state handling here is kind of tricky, doing it on EMT(0) helps 1557 * a bit. See the VMSTATE diagram for details. The EMT(0) calls 1558 * consumes the pSSM handle and calls SSMR3LiveDone. 1665 * a bit. See the VMSTATE diagram for details. 1559 1666 */ 1560 1667 rc = SSMR3LiveDoStep1(pSSM); 1561 1668 if (RT_SUCCESS(rc)) 1562 1669 { 1563 #if 01564 /** @todo LS/SMP: Changes out of Running and RunningLS should be done using1565 * VMMR3EmtRendezvous to avoid races and odd states while we're1566 * still executing. */1567 1670 for (;;) 1568 1671 { 1569 /* quietly try switch to SuspendingLS and suspend the VM. */ 1570 PUVM pUVM = pVM->pUVM; 1571 RTCritSectEnter(&pUVM->vm.s.AtStateCritSect); 1572 VMSTATE enmVMState = pVM->enmVMState; 1573 if (enmVMState == VMSTATE_RUNNING_LS) 1574 { 1575 vmR3SetStateLocked(pVM, pUVM, VMSTATE_SUSPENDING_LS, VMSTATE_RUNNING_LS); 1576 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect); 1577 // rc = vmR3SuspendCommon(pVM, false /*fFatal*/, true /*fSuspendingAlready*/); 1672 /* Try suspend the VM. */ 1673 rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR, 1674 vmR3LiveDoSuspend, pSSM); 1675 if (rc != VERR_TRY_AGAIN) 1578 1676 break; 1579 } 1580 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect); 1581 if (enmVMState != VMSTATE_SUSPENDED_LS) 1582 { 1583 rc = VINF_SUCCESS; 1584 break; 1585 } 1586 if ( enmVMState != VMSTATE_SUSPENDING_LS 1587 && enmVMState != VMSTATE_DEBUGGING_LS) 1588 { 1589 switch (enmVMState) 1590 { 1591 case VMSTATE_SUSPENDED 1592 } 1593 rc = VERR_SSM_LIVE_CANCELLED; 1594 break; 1595 } 1596 1597 /* 1598 * Wait for the state to change. 1599 */ 1600 /** @todo LS: fix this mess by some smart use of multiple release event 1601 * semaphores.. */ 1602 RTThreadSleep(250); 1677 1678 /* Wait for the state to change. */ 1679 RTThreadSleep(250); /** @todo LS: fix this polling wait by some smart use of multiple release event semaphores.. */ 1603 1680 } 1604 #endif 1681 if (RT_SUCCESS(rc)) 1682 rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/, (PFNRT)vmR3LiveDoStep2, 2, pVM, pSSM); 1683 else 1684 SSMR3LiveDone(pSSM); 1605 1685 } 1606 if (RT_SUCCESS(rc))1607 rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/, (PFNRT)vmR3SaveLiveStep2, 2, pVM, pSSM);1608 1686 else 1609 1687 { 1610 int rc2 = VMR3ReqCallWait(pVM, 0 /*idDstCpu*/, (PFNRT)vmR3SaveLiveStep1Cleanup, 2, pVM, pSSM); 1611 AssertLogRelRC(rc2); 1688 int rc2 = SSMR3LiveDone(pSSM); 1689 AssertMsg(rc2 == rc, ("%Rrc != %Rrc\n", rc2, rc)); 1690 1691 rc2 = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, vmR3LiveDoStep1Cleanup, NULL); 1692 if (RT_FAILURE(rc2) && rc == VERR_SSM_CANCELLED) 1693 rc = rc2; 1612 1694 } 1613 1695 } … … 1742 1824 if (RT_FAILURE(rc)) 1743 1825 return rc; 1826 if (rc >= 7) 1827 SSMR3Cancel(pVM); 1744 1828 } 1745 1829
Note:
See TracChangeset
for help on using the changeset viewer.