Changeset 24874 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Nov 23, 2009 3:37:58 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 55135
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PGM.cpp
r24797 r24874 1581 1581 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cDirtyPagesLong, STAMTYPE_U32, "/PGM/LiveSave/cDirtyPagesLong", STAMUNIT_COUNT, "Longer term dirty page average."); 1582 1582 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."); 1583 1585 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cReadyPages, STAMTYPE_U32, "/PGM/LiveSave/Ram/cReadPages", STAMUNIT_COUNT, "RAM: Ready pages."); 1584 1586 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 2754 2754 /** Long term dirty page average. */ 2755 2755 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; 2756 2766 } LiveSave; 2757 2767 -
trunk/src/VBox/VMM/PGMSavedState.cpp
r24808 r24874 437 437 pVM->pgm.s.LiveSave.Rom.cDirtyPages--; 438 438 pVM->pgm.s.LiveSave.Rom.cReadyPages++; 439 pVM->pgm.s.LiveSave.cSavedPages++; 439 440 } 440 441 } … … 502 503 pVM->pgm.s.LiveSave.Rom.cReadyPages++; 503 504 pVM->pgm.s.LiveSave.Rom.cDirtyPages--; 505 pVM->pgm.s.LiveSave.cSavedPages++; 504 506 } 505 507 pgmUnlock(pVM); … … 880 882 } 881 883 u8Type = paLSPages[iPage].fZero ? PGM_STATE_REC_MMIO2_ZERO : PGM_STATE_REC_MMIO2_RAW; 884 pVM->pgm.s.LiveSave.cSavedPages++; 882 885 } 883 886 … … 957 960 if (u8Type == PGM_STATE_REC_MMIO2_ZERO) 958 961 pVM->pgm.s.LiveSave.Mmio2.cZeroPages++; 962 pVM->pgm.s.LiveSave.cSavedPages++; 959 963 iPageLast = iPage; 960 964 } … … 1608 1612 pVM->pgm.s.LiveSave.Ram.cZeroPages++; 1609 1613 pVM->pgm.s.LiveSave.Ram.cDirtyPages--; 1614 pVM->pgm.s.LiveSave.cSavedPages++; 1610 1615 } 1611 1616 if (idRamRangesGen != pVM->pgm.s.idRamRangesGen) … … 1723 1728 return rc; 1724 1729 } 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 } 1725 1739 1726 1740 /* … … 1768 1782 1769 1783 /* update history. */ 1784 pgmLock(pVM); 1785 uint32_t const cWrittenToPages = pVM->pgm.s.cWrittenToPages; 1786 pgmUnlock(pVM); 1770 1787 uint32_t i = pVM->pgm.s.LiveSave.iDirtyPagesHistory; 1771 1788 pVM->pgm.s.LiveSave.acDirtyPagesHistory[i] = pVM->pgm.s.LiveSave.Rom.cDirtyPages 1772 1789 + pVM->pgm.s.LiveSave.Mmio2.cDirtyPages 1773 + pVM->pgm.s.LiveSave.Ram.cDirtyPages; 1790 + pVM->pgm.s.LiveSave.Ram.cDirtyPages 1791 + cWrittenToPages; 1774 1792 pVM->pgm.s.LiveSave.iDirtyPagesHistory = (i + 1) % cHistoryEntries; 1775 1793 … … 1794 1812 pVM->pgm.s.LiveSave.cDirtyPagesLong = cDirtyPagesLong; 1795 1813 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 1796 1820 /* 1797 1821 * Try make a decision. 1798 1822 */ 1799 /** @todo take the count dirtied write-monitored page into account here. */1800 1823 if (cDirtyPagesShort <= cDirtyPagesLong) 1801 1824 { 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 } 1823 1853 } 1824 1854 return VINF_SSM_VOTE_FOR_ANOTHER_PASS; … … 1867 1897 pVM->pgm.s.LiveSave.acDirtyPagesHistory[i] = UINT32_MAX / 2; 1868 1898 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; 1869 1902 1870 1903 /* … … 2980 3013 return SSMR3RegisterInternal(pVM, "pgm", 1, PGM_SAVED_STATE_VERSION, (size_t)cbRam + sizeof(PGM), 2981 3014 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 504 504 /** Data buffer. */ 505 505 uint8_t abDataBuffer[4096]; 506 /** The maximum downtime given as milliseconds. */ 507 uint32_t cMsMaxDowntime; 506 508 } Write; 507 509 … … 4604 4606 return VERR_NO_MEMORY; 4605 4607 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; 4625 4628 4626 4629 int rc; … … 5097 5100 * 5098 5101 * @param pVM The VM handle. 5102 * @param cMsMaxDowntime The maximum downtime given as milliseconds. 5099 5103 * @param pszFilename Name of the file to save the state in. This string 5100 5104 * must remain valid until SSMR3LiveDone is called. … … 5109 5113 * @thread EMT0 5110 5114 */ 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)); 5115 VMMR3_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)); 5116 5122 VM_ASSERT_EMT0(pVM); 5117 5123 … … 5148 5154 if (RT_FAILURE(rc)) 5149 5155 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; 5153 5160 5154 5161 /* … … 8645 8652 8646 8653 /** 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 */ 8661 VMMR3DECL(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 /** 8647 8671 * Gets the host bit count of a saved state. 8648 8672 * -
trunk/src/VBox/VMM/VM.cpp
r24785 r24874 1585 1585 * 1586 1586 * @param pVM The VM handle. 1587 * @param cMsMaxDowntime The maximum downtime given as milliseconds. 1587 1588 * @param pszFilename The name of the file. NULL if pStreamOps is used. 1588 1589 * @param pStreamOps The stream methods. NULL if pszFilename is used. … … 1595 1596 * @thread EMT 1596 1597 */ 1597 static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,1598 static DECLCALLBACK(int) vmR3Save(PVM pVM, uint32_t cMsMaxDowntime, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, 1598 1599 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, PSSMHANDLE *ppSSM) 1599 1600 { 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)); 1602 1603 1603 1604 /* … … 1629 1630 if (enmAfter == SSMAFTER_TELEPORT) 1630 1631 pVM->vm.s.fTeleportedAndNotFullyResumedYet = true; 1631 rc = SSMR3LiveSave(pVM, pszFilename, pStreamOps, pvStreamOpsUser,1632 rc = SSMR3LiveSave(pVM, cMsMaxDowntime, pszFilename, pStreamOps, pvStreamOpsUser, 1632 1633 enmAfter, pfnProgress, pvProgressUser, ppSSM); 1633 1634 /* (We're not subject to cancellation just yet.) */ … … 1645 1646 * 1646 1647 * @param pVM The VM handle. 1648 * @param cMsMaxDowntime The maximum downtime given as milliseconds. 1647 1649 * @param pszFilename The name of the file. NULL if pStreamOps is used. 1648 1650 * @param pStreamOps The stream methods. NULL if pszFilename is used. … … 1655 1657 * @thread Non-EMT 1656 1658 */ 1657 static int vmR3SaveTeleport(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, 1659 static int vmR3SaveTeleport(PVM pVM, uint32_t cMsMaxDowntime, 1660 const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, 1658 1661 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended) 1659 1662 { … … 1663 1666 PSSMHANDLE pSSM; 1664 1667 int rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/, 1665 (PFNRT)vmR3Save, 8, pVM, pszFilename, pStreamOps, pvStreamOpsUser,1668 (PFNRT)vmR3Save, 9, pVM, cMsMaxDowntime, pszFilename, pStreamOps, pvStreamOpsUser, 1666 1669 enmAfter, pfnProgress, pvProgressUser, &pSSM); 1667 1670 if ( RT_SUCCESS(rc) … … 1756 1759 bool fSuspended = false; /** @todo need this for live snapshots. */ 1757 1760 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*/, 1759 1763 enmAfter, pfnProgress, pvUser, &fSuspended); 1760 1764 LogFlow(("VMR3Save: returns %Rrc\n", rc)); … … 1769 1773 * 1770 1774 * @param pVM The VM which state should be saved. 1775 * @param cMsMaxDowntime The maximum downtime given as milliseconds. 1771 1776 * @param pStreamOps The stream methods. 1772 1777 * @param pvStreamOpsUser The user argument to the stream methods. … … 1780 1785 * RunningLS+SuspeningLS+SuspendedLS+Saving+Suspended. 1781 1786 */ 1782 VMMR3DECL(int) VMR3Teleport(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,1787 VMMR3DECL(int) VMR3Teleport(PVM pVM, uint32_t cMsMaxDowntime, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, 1783 1788 PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended) 1784 1789 { 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)); 1787 1792 1788 1793 /* … … 1799 1804 * Join paths with VMR3Save. 1800 1805 */ 1801 int rc = vmR3SaveTeleport(pVM, NULL /*pszFilename*/, pStreamOps, pvStreamOpsUser, 1806 int rc = vmR3SaveTeleport(pVM, cMsMaxDowntime, 1807 NULL /*pszFilename*/, pStreamOps, pvStreamOpsUser, 1802 1808 SSMAFTER_TELEPORT, pfnProgress, pvProgressUser, pfSuspended); 1803 1809 LogFlow(("VMR3Teleport: returns %Rrc (*pfSuspended=%RTbool)\n", rc, *pfSuspended));
Note:
See TracChangeset
for help on using the changeset viewer.