VirtualBox

Changeset 23151 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 18, 2009 11:13:02 PM (15 years ago)
Author:
vboxsync
Message:

VBox/err.h,VMM: VMR3Save should be mostly done now.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VM.cpp

    r23148 r23151  
    13811381
    13821382/**
     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 */
     1393static 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 */
     1491static 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 */
     1526static 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/**
    13831564 * Worker for VMR3Save that validates the state and calls SSMR3Save.
    13841565 *
     
    14301611
    14311612/**
    1432  * Worker for VMR3Save to clean up a SSMR3LiveDoStep1 failure.
    1433  *
    1434  * We failed after hitting the RunningLS state, but before trying to suspend the
    1435  * VM before vmR3SaveLiveStep2.  There are a number of state transisions in this
    1436  * state, some, like ResetLS, that requires some special handling.  (ResetLS is
    1437  * 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 be
    1443  *                          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         else
    1470             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 /**
    15051613 * Save current VM state.
    15061614 *
     
    15551663         *
    15561664         * 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.
    15591666         */
    15601667        rc = SSMR3LiveDoStep1(pSSM);
    15611668        if (RT_SUCCESS(rc))
    15621669        {
    1563 #if 0
    1564             /** @todo LS/SMP: Changes out of Running and RunningLS should be done using
    1565              *        VMMR3EmtRendezvous to avoid races and odd states while we're
    1566              *        still executing. */
    15671670            for (;;)
    15681671            {
    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)
    15781676                    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.. */
    16031680            }
    1604 #endif
     1681            if (RT_SUCCESS(rc))
     1682                rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/, (PFNRT)vmR3LiveDoStep2, 2, pVM, pSSM);
     1683            else
     1684                SSMR3LiveDone(pSSM);
    16051685        }
    1606         if (RT_SUCCESS(rc))
    1607             rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/, (PFNRT)vmR3SaveLiveStep2, 2, pVM, pSSM);
    16081686        else
    16091687        {
    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;
    16121694        }
    16131695    }
     
    17421824        if (RT_FAILURE(rc))
    17431825            return rc;
     1826        if (rc >= 7)
     1827            SSMR3Cancel(pVM);
    17441828    }
    17451829
Note: See TracChangeset for help on using the changeset viewer.

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