VirtualBox

Changeset 24874 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Nov 23, 2009 3:37:58 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
55135
Message:

Main,VMM,VBoxManage: Added a parameter to IConsole::Teleport for specifying a max downtime and made PGM compare this against a rough estimate of the time it would take to deal with the rest of the pages.

Location:
trunk/src/VBox/VMM
Files:
5 edited

Legend:

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

    r24797 r24874  
    15811581    STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cDirtyPagesLong,      STAMTYPE_U32,     "/PGM/LiveSave/cDirtyPagesLong",      STAMUNIT_COUNT,     "Longer term dirty page average.");
    15821582    STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cDirtyPagesShort,     STAMTYPE_U32,     "/PGM/LiveSave/cDirtyPagesShort",     STAMUNIT_COUNT,     "Short term dirty page average.");
     1583    STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cPagesPerSecond,      STAMTYPE_U32,     "/PGM/LiveSave/cPagesPerSecond",      STAMUNIT_COUNT,     "Pages per second.");
     1584    STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cSavedPages,          STAMTYPE_U64,     "/PGM/LiveSave/cSavedPages",          STAMUNIT_COUNT,     "The total number of saved pages.");
    15831585    STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cReadyPages,      STAMTYPE_U32,     "/PGM/LiveSave/Ram/cReadPages",       STAMUNIT_COUNT,     "RAM: Ready pages.");
    15841586    STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cDirtyPages,      STAMTYPE_U32,     "/PGM/LiveSave/Ram/cDirtyPages",      STAMUNIT_COUNT,     "RAM: Dirty pages.");
  • trunk/src/VBox/VMM/PGMInternal.h

    r24807 r24874  
    27542754        /** Long term dirty page average. */
    27552755        uint32_t                    cDirtyPagesLong;
     2756        /** The number of saved pages.  This is used to get some kind of estimate of the
     2757         * link speed so we can decide when we're done.  It is reset after the first
     2758         * 7 passes so the speed estimate doesn't get inflated by the initial set of
     2759         * zero pages.   */
     2760        uint64_t                    cSavedPages;
     2761        /** The nanosecond timestamp when cSavedPages was 0. */
     2762        uint64_t                    uSaveStartNS;
     2763        /** Pages per second (for statistics). */
     2764        uint32_t                    cPagesPerSecond;
     2765        uint32_t                    cAlignment;
    27562766    } LiveSave;
    27572767
  • trunk/src/VBox/VMM/PGMSavedState.cpp

    r24808 r24874  
    437437                pVM->pgm.s.LiveSave.Rom.cDirtyPages--;
    438438                pVM->pgm.s.LiveSave.Rom.cReadyPages++;
     439                pVM->pgm.s.LiveSave.cSavedPages++;
    439440            }
    440441        }
     
    502503                        pVM->pgm.s.LiveSave.Rom.cReadyPages++;
    503504                        pVM->pgm.s.LiveSave.Rom.cDirtyPages--;
     505                        pVM->pgm.s.LiveSave.cSavedPages++;
    504506                    }
    505507                    pgmUnlock(pVM);
     
    880882                    }
    881883                    u8Type = paLSPages[iPage].fZero ? PGM_STATE_REC_MMIO2_ZERO : PGM_STATE_REC_MMIO2_RAW;
     884                    pVM->pgm.s.LiveSave.cSavedPages++;
    882885                }
    883886
     
    957960                if (u8Type == PGM_STATE_REC_MMIO2_ZERO)
    958961                    pVM->pgm.s.LiveSave.Mmio2.cZeroPages++;
     962                pVM->pgm.s.LiveSave.cSavedPages++;
    959963                iPageLast = iPage;
    960964            }
     
    16081612                            pVM->pgm.s.LiveSave.Ram.cZeroPages++;
    16091613                        pVM->pgm.s.LiveSave.Ram.cDirtyPages--;
     1614                        pVM->pgm.s.LiveSave.cSavedPages++;
    16101615                    }
    16111616                    if (idRamRangesGen != pVM->pgm.s.idRamRangesGen)
     
    17231728            return rc;
    17241729    }
     1730    /*
     1731     * Reset the page-per-second estimate to avoid inflation by the initial
     1732     * load of zero pages.  pgmR3LiveVote ASSUMES this is done at pass 7.
     1733     */
     1734    else if (uPass == 7)
     1735    {
     1736        pVM->pgm.s.LiveSave.cSavedPages  = 0;
     1737        pVM->pgm.s.LiveSave.uSaveStartNS = RTTimeNanoTS();
     1738    }
    17251739
    17261740    /*
     
    17681782
    17691783    /* update history. */
     1784    pgmLock(pVM);
     1785    uint32_t const cWrittenToPages = pVM->pgm.s.cWrittenToPages;
     1786    pgmUnlock(pVM);
    17701787    uint32_t i = pVM->pgm.s.LiveSave.iDirtyPagesHistory;
    17711788    pVM->pgm.s.LiveSave.acDirtyPagesHistory[i] = pVM->pgm.s.LiveSave.Rom.cDirtyPages
    17721789                                               + pVM->pgm.s.LiveSave.Mmio2.cDirtyPages
    1773                                                + pVM->pgm.s.LiveSave.Ram.cDirtyPages;
     1790                                               + pVM->pgm.s.LiveSave.Ram.cDirtyPages
     1791                                               + cWrittenToPages;
    17741792    pVM->pgm.s.LiveSave.iDirtyPagesHistory = (i + 1) % cHistoryEntries;
    17751793
     
    17941812    pVM->pgm.s.LiveSave.cDirtyPagesLong = cDirtyPagesLong;
    17951813
     1814    /* estimate the speed */
     1815    uint64_t cNsElapsed = RTTimeNanoTS() - pVM->pgm.s.LiveSave.uSaveStartNS;
     1816    uint32_t cPagesPerSecond = (uint32_t)(   pVM->pgm.s.LiveSave.cSavedPages
     1817                                          / ((long double)cNsElapsed / 1000000000.0) );
     1818    pVM->pgm.s.LiveSave.cPagesPerSecond = cPagesPerSecond;
     1819
    17961820    /*
    17971821     * Try make a decision.
    17981822     */
    1799     /** @todo take the count dirtied write-monitored page into account here. */
    18001823    if (cDirtyPagesShort <= cDirtyPagesLong)
    18011824    {
    1802         if (    cDirtyPagesShort <= 128
    1803             &&  cDirtyPagesLong  <= 1024)
    1804             return VINF_SUCCESS;
    1805         if (cDirtyPagesLong  <= 256)
    1806             return VINF_SUCCESS;
    1807         /* !! hack !! */
    1808         if (    cDirtyPagesShort <= 512
    1809             &&  cDirtyPagesLong  <= 640
    1810             &&  uPass >= 1024)
    1811             return VINF_SUCCESS;
    1812         if (    cDirtyPagesShort <= 896
    1813             &&  cDirtyPagesLong  <= 1024
    1814             &&  uPass >= 2048)
    1815             return VINF_SUCCESS;
    1816         if (    cDirtyPagesShort <= 1512
    1817             &&  cDirtyPagesLong  <= 1536
    1818             &&  uPass >= 4096)
    1819             return VINF_SUCCESS;
    1820         if (    cDirtyPagesLong  <= 4096
    1821             &&  uPass >= 8192)
    1822             return VINF_SUCCESS;
     1825        if (uPass > 10)
     1826        {
     1827            uint32_t cMsLeftShort   = (uint32_t)(cDirtyPagesShort / (long double)cPagesPerSecond * 1000.0);
     1828            uint32_t cMsLeftLong    = (uint32_t)(cDirtyPagesLong  / (long double)cPagesPerSecond * 1000.0);
     1829            uint32_t cMsMaxDowntime = SSMR3HandleMaxDowntime(pSSM);
     1830            if (cMsMaxDowntime < 32)
     1831                cMsMaxDowntime = 32;
     1832            if (   (   cMsLeftLong  <= cMsMaxDowntime
     1833                    && cMsLeftShort <  cMsMaxDowntime)
     1834                || cMsLeftShort < cMsMaxDowntime / 2
     1835               )
     1836            {
     1837                Log(("pgmR3LiveVote: VINF_SUCCESS - pass=%d cDirtyPagesShort=%u|%ums cDirtyPagesLong=%u|%ums cMsMaxDowntime=%u\n",
     1838                     uPass, cDirtyPagesShort, cMsLeftShort, cDirtyPagesLong, cMsLeftLong, cMsMaxDowntime));
     1839                return VINF_SUCCESS;
     1840            }
     1841        }
     1842        else
     1843        {
     1844            if (   (   cDirtyPagesShort <= 128
     1845                    && cDirtyPagesLong  <= 1024)
     1846                || cDirtyPagesLong <= 256
     1847               )
     1848            {
     1849                Log(("pgmR3LiveVote: VINF_SUCCESS - pass=%d cDirtyPagesShort=%u cDirtyPagesLong=%u\n", uPass, cDirtyPagesShort, cDirtyPagesLong));
     1850                return VINF_SUCCESS;
     1851            }
     1852        }
    18231853    }
    18241854    return VINF_SSM_VOTE_FOR_ANOTHER_PASS;
     
    18671897        pVM->pgm.s.LiveSave.acDirtyPagesHistory[i] = UINT32_MAX / 2;
    18681898    pVM->pgm.s.LiveSave.iDirtyPagesHistory = 0;
     1899    pVM->pgm.s.LiveSave.cSavedPages       = 0;
     1900    pVM->pgm.s.LiveSave.uSaveStartNS      = RTTimeNanoTS();
     1901    pVM->pgm.s.LiveSave.cPagesPerSecond   = 8192;
    18691902
    18701903    /*
     
    29803013    return SSMR3RegisterInternal(pVM, "pgm", 1, PGM_SAVED_STATE_VERSION, (size_t)cbRam + sizeof(PGM),
    29813014                                 pgmR3LivePrep, pgmR3LiveExec, pgmR3LiveVote,
    2982                                  NULL, pgmR3SaveExec, pgmR3SaveDone,
    2983                                  pgmR3LoadPrep, pgmR3Load, NULL);
    2984 }
    2985 
     3015                                 NULL,          pgmR3SaveExec, pgmR3SaveDone,
     3016                                 pgmR3LoadPrep, pgmR3Load,     NULL);
     3017}
     3018
  • trunk/src/VBox/VMM/SSM.cpp

    r24846 r24874  
    504504            /** Data buffer. */
    505505            uint8_t         abDataBuffer[4096];
     506            /** The maximum downtime given as milliseconds. */
     507            uint32_t        cMsMaxDowntime;
    506508        } Write;
    507509
     
    46044606        return VERR_NO_MEMORY;
    46054607
    4606     pSSM->pVM                   = pVM;
    4607     pSSM->enmOp                 = SSMSTATE_INVALID;
    4608     pSSM->enmAfter              = enmAfter;
    4609     pSSM->fCancelled            = SSMHANDLE_OK;
    4610     pSSM->rc                    = VINF_SUCCESS;
    4611     pSSM->cbUnitLeftV1          = 0;
    4612     pSSM->offUnit               = UINT64_MAX;
    4613     pSSM->fLiveSave             = false;
    4614     pSSM->pfnProgress           = pfnProgress;
    4615     pSSM->pvUser                = pvProgressUser;
    4616     pSSM->uPercent              = 0;
    4617     pSSM->offEstProgress        = 0;
    4618     pSSM->cbEstTotal            = 0;
    4619     pSSM->offEst                = 0;
    4620     pSSM->offEstUnitEnd         = 0;
    4621     pSSM->uPercentPrepare       = 0;
    4622     pSSM->uPercentDone          = 0;
    4623     pSSM->pszFilename           = pszFilename;
    4624     pSSM->u.Write.offDataBuffer = 0;
     4608    pSSM->pVM                       = pVM;
     4609    pSSM->enmOp                     = SSMSTATE_INVALID;
     4610    pSSM->enmAfter                  = enmAfter;
     4611    pSSM->fCancelled                = SSMHANDLE_OK;
     4612    pSSM->rc                        = VINF_SUCCESS;
     4613    pSSM->cbUnitLeftV1              = 0;
     4614    pSSM->offUnit                   = UINT64_MAX;
     4615    pSSM->fLiveSave                 = false;
     4616    pSSM->pfnProgress               = pfnProgress;
     4617    pSSM->pvUser                    = pvProgressUser;
     4618    pSSM->uPercent                  = 0;
     4619    pSSM->offEstProgress            = 0;
     4620    pSSM->cbEstTotal                = 0;
     4621    pSSM->offEst                    = 0;
     4622    pSSM->offEstUnitEnd             = 0;
     4623    pSSM->uPercentPrepare           = 0;
     4624    pSSM->uPercentDone              = 0;
     4625    pSSM->pszFilename               = pszFilename;
     4626    pSSM->u.Write.offDataBuffer     = 0;
     4627    pSSM->u.Write.cMsMaxDowntime    = UINT32_MAX;
    46254628
    46264629    int rc;
     
    50975100 *
    50985101 * @param   pVM             The VM handle.
     5102 * @param   cMsMaxDowntime  The maximum downtime given as milliseconds.
    50995103 * @param   pszFilename     Name of the file to save the state in. This string
    51005104 *                          must remain valid until SSMR3LiveDone is called.
     
    51095113 * @thread  EMT0
    51105114 */
    5111 VMMR3_INT_DECL(int) SSMR3LiveSave(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
    5112                                   SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, PSSMHANDLE *ppSSM)
    5113 {
    5114     LogFlow(("SSMR3LiveSave: pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p\n",
    5115              pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser));
     5115VMMR3_INT_DECL(int) SSMR3LiveSave(PVM pVM, uint32_t cMsMaxDowntime,
     5116                                  const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
     5117                                  SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser,
     5118                                  PSSMHANDLE *ppSSM)
     5119{
     5120    LogFlow(("SSMR3LiveSave: cMsMaxDowntime=%u pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p\n",
     5121             cMsMaxDowntime, pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser));
    51165122    VM_ASSERT_EMT0(pVM);
    51175123
     
    51485154    if (RT_FAILURE(rc))
    51495155        return rc;
    5150     pSSM->uPercentPrepare = 20; /** @todo fix these. */
    5151     pSSM->uPercentDone    = 2;
    5152     pSSM->fLiveSave       = true;
     5156    pSSM->uPercentPrepare        = 20; /** @todo fix these. */
     5157    pSSM->uPercentDone           = 2;
     5158    pSSM->fLiveSave              = true;
     5159    pSSM->u.Write.cMsMaxDowntime = cMsMaxDowntime;
    51535160
    51545161    /*
     
    86458652
    86468653/**
     8654 * Gets the maximum downtime for a live operation.
     8655 *
     8656 * @returns The max downtime in milliseconds.  Can be anything from 0 thru
     8657 *          UINT32_MAX.
     8658 *
     8659 * @param   pSSM            The saved state handle.
     8660 */
     8661VMMR3DECL(uint32_t) SSMR3HandleMaxDowntime(PSSMHANDLE pSSM)
     8662{
     8663    SSM_ASSERT_VALID_HANDLE(pSSM);
     8664    if (pSSM->enmOp <= SSMSTATE_SAVE_DONE)
     8665        return pSSM->u.Write.cMsMaxDowntime;
     8666    return UINT32_MAX;
     8667}
     8668
     8669
     8670/**
    86478671 * Gets the host bit count of a saved state.
    86488672 *
  • trunk/src/VBox/VMM/VM.cpp

    r24785 r24874  
    15851585 *
    15861586 * @param   pVM             The VM handle.
     1587 * @param   cMsMaxDowntime  The maximum downtime given as milliseconds.
    15871588 * @param   pszFilename     The name of the file.  NULL if pStreamOps is used.
    15881589 * @param   pStreamOps      The stream methods.  NULL if pszFilename is used.
     
    15951596 * @thread  EMT
    15961597 */
    1597 static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
     1598static DECLCALLBACK(int) vmR3Save(PVM pVM, uint32_t cMsMaxDowntime, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
    15981599                                  SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, PSSMHANDLE *ppSSM)
    15991600{
    1600     LogFlow(("vmR3Save: pVM=%p pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p ppSSM=%p\n",
    1601              pVM, pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser, ppSSM));
     1601    LogFlow(("vmR3Save: pVM=%p cMsMaxDowntime=%u pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p ppSSM=%p\n",
     1602             pVM, cMsMaxDowntime, pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser, ppSSM));
    16021603
    16031604    /*
     
    16291630        if (enmAfter == SSMAFTER_TELEPORT)
    16301631            pVM->vm.s.fTeleportedAndNotFullyResumedYet = true;
    1631         rc = SSMR3LiveSave(pVM, pszFilename, pStreamOps, pvStreamOpsUser,
     1632        rc = SSMR3LiveSave(pVM, cMsMaxDowntime, pszFilename, pStreamOps, pvStreamOpsUser,
    16321633                           enmAfter, pfnProgress, pvProgressUser, ppSSM);
    16331634        /* (We're not subject to cancellation just yet.) */
     
    16451646 *
    16461647 * @param   pVM             The VM handle.
     1648 * @param   cMsMaxDowntime      The maximum downtime given as milliseconds.
    16471649 * @param   pszFilename     The name of the file.  NULL if pStreamOps is used.
    16481650 * @param   pStreamOps      The stream methods.  NULL if pszFilename is used.
     
    16551657 * @thread  Non-EMT
    16561658 */
    1657 static int vmR3SaveTeleport(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
     1659static int vmR3SaveTeleport(PVM pVM, uint32_t cMsMaxDowntime,
     1660                            const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
    16581661                            SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended)
    16591662{
     
    16631666    PSSMHANDLE pSSM;
    16641667    int rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/,
    1665                               (PFNRT)vmR3Save, 8, pVM, pszFilename, pStreamOps, pvStreamOpsUser,
     1668                              (PFNRT)vmR3Save, 9, pVM, cMsMaxDowntime, pszFilename, pStreamOps, pvStreamOpsUser,
    16661669                              enmAfter, pfnProgress, pvProgressUser, &pSSM);
    16671670    if (    RT_SUCCESS(rc)
     
    17561759    bool fSuspended = false; /** @todo need this for live snapshots. */
    17571760    SSMAFTER enmAfter = fContinueAfterwards ? SSMAFTER_CONTINUE : SSMAFTER_DESTROY;
    1758     int rc = vmR3SaveTeleport(pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOpsUser*/,
     1761    int rc = vmR3SaveTeleport(pVM, 250 /*cMsMaxDowntime*/,
     1762                              pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOpsUser*/,
    17591763                              enmAfter, pfnProgress, pvUser, &fSuspended);
    17601764    LogFlow(("VMR3Save: returns %Rrc\n", rc));
     
    17691773 *
    17701774 * @param   pVM                 The VM which state should be saved.
     1775 * @param   cMsMaxDowntime      The maximum downtime given as milliseconds.
    17711776 * @param   pStreamOps          The stream methods.
    17721777 * @param   pvStreamOpsUser     The user argument to the stream methods.
     
    17801785 *              RunningLS+SuspeningLS+SuspendedLS+Saving+Suspended.
    17811786 */
    1782 VMMR3DECL(int) VMR3Teleport(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
     1787VMMR3DECL(int) VMR3Teleport(PVM pVM, uint32_t cMsMaxDowntime, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
    17831788                            PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended)
    17841789{
    1785     LogFlow(("VMR3Teleport: pVM=%p pStreamOps=%p pvStreamOps=%p pfnProgress=%p pvProgressUser=%p\n",
    1786              pVM, pStreamOps, pvStreamOpsUser, pfnProgress, pvProgressUser));
     1790    LogFlow(("VMR3Teleport: pVM=%p cMsMaxDowntime=%u pStreamOps=%p pvStreamOps=%p pfnProgress=%p pvProgressUser=%p\n",
     1791             pVM, cMsMaxDowntime, pStreamOps, pvStreamOpsUser, pfnProgress, pvProgressUser));
    17871792
    17881793    /*
     
    17991804     * Join paths with VMR3Save.
    18001805     */
    1801     int rc = vmR3SaveTeleport(pVM, NULL /*pszFilename*/, pStreamOps, pvStreamOpsUser,
     1806    int rc = vmR3SaveTeleport(pVM, cMsMaxDowntime,
     1807                              NULL /*pszFilename*/, pStreamOps, pvStreamOpsUser,
    18021808                              SSMAFTER_TELEPORT, pfnProgress, pvProgressUser, pfSuspended);
    18031809    LogFlow(("VMR3Teleport: returns %Rrc (*pfSuspended=%RTbool)\n", rc, *pfSuspended));
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