Changeset 2611 in vbox
- Timestamp:
- May 14, 2007 4:58:51 AM (18 years ago)
- svn:sync-xref-src-repo-rev:
- 21124
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/TM.cpp
r2584 r2611 26 26 * device and drivers. 27 27 * 28 * 28 * 29 29 * @section sec_tm_clocks Clocks 30 * 30 * 31 31 * There are currently 4 clocks: 32 32 * - Virtual (guest). 33 33 * - Synchronous virtual (guest). 34 * - CPU Tick (TSC) (guest). Only current use is rdtsc emulation. Usually a 34 * - CPU Tick (TSC) (guest). Only current use is rdtsc emulation. Usually a 35 35 * function of the virtual clock. 36 * - Real (host). The only current use is display updates for not real 36 * - Real (host). The only current use is display updates for not real 37 37 * good reason... 38 * 39 * The interesting clocks are two first ones, the virtual and synchronous virtual 40 * clock. The synchronous virtual clock is tied to the virtual clock except that 38 * 39 * The interesting clocks are two first ones, the virtual and synchronous virtual 40 * clock. The synchronous virtual clock is tied to the virtual clock except that 41 41 * it will take into account timer delivery lag caused by host scheduling. It will 42 42 * normally never advance beyond the header timer, and when lagging too far behind 43 43 * it will gradually speed up to catch up with the virtual clock. 44 44 * 45 * The CPU tick (TSC) is normally virtualized as a function of the virtual time, 45 * The CPU tick (TSC) is normally virtualized as a function of the virtual time, 46 46 * where the frequency defaults to the host cpu frequency (as we measure it). It 47 47 * can also use the host TSC as source and either present it with an offset or 48 * unmodified. It is of course possible to configure the TSC frequency and mode 48 * unmodified. It is of course possible to configure the TSC frequency and mode 49 49 * of operation. 50 * 50 * 51 51 * @subsection subsec_tm_timesync Guest Time Sync / UTC time 52 * 52 * 53 53 * Guest time syncing is primarily taken care of by the VMM device. The principle 54 * is very simple, the guest additions periodically asks the VMM device what the 55 * current UTC time is and makes adjustments accordingly. Now, because the 54 * is very simple, the guest additions periodically asks the VMM device what the 55 * current UTC time is and makes adjustments accordingly. Now, because the 56 56 * synchronous virtual clock might be doing catchups and we would therefore 57 57 * deliver more than the normal rate for a little while, some adjusting of the 58 * UTC time is required before passing it on to the guest. This is why TM provides 58 * UTC time is required before passing it on to the guest. This is why TM provides 59 59 * an API for query the current UTC time. 60 60 * 61 * 61 * 62 62 * @section sec_tm_timers Timers 63 63 * 64 64 * The timers can use any of the TM clocks described in the previous section. Each 65 65 * clock has its own scheduling facility, or timer queue if you like. There are 66 * a few factors which makes it a bit complex. First there is the usual R0 vs R3 66 * a few factors which makes it a bit complex. First there is the usual R0 vs R3 67 67 * vs. GC thing. Then there is multiple threads, and then there is the timer thread 68 * that periodically checks whether any timers has expired without EMT noticing. On 68 * that periodically checks whether any timers has expired without EMT noticing. On 69 69 * the API level, all but the create and save APIs must be mulithreaded. EMT will 70 70 * always run the timers. 71 71 * 72 72 * The design is using a doubly linked list of active timers which is ordered 73 * by expire date. This list is only modified by the EMT thread. Updates to the 74 * list are are batched in a singly linked list, which is then process by the EMT 75 * thread at the first opportunity (immediately, next time EMT modifies a timer 73 * by expire date. This list is only modified by the EMT thread. Updates to the 74 * list are are batched in a singly linked list, which is then process by the EMT 75 * thread at the first opportunity (immediately, next time EMT modifies a timer 76 76 * on that clock, or next timer timeout). Both lists are offset based and all 77 77 * the elements therefore allocated from the hyper heap. … … 83 83 * - Poll the virtual clocks and calculate first timeout from the halt loop. 84 84 * - Employ a thread which periodically (100Hz) polls all the timer queues. 85 * 86 * 85 * 86 * 87 87 * @section sec_tm_timer Logging 88 * 88 * 89 89 * Level 2: Logs a most of the timer state transitions and queue servicing. 90 90 * Level 3: Logs a few oddments. 91 91 * Level 4: Logs TMCLOCK_VIRTUAL_SYNC catch-up events. 92 * 92 * 93 93 */ 94 94 … … 241 241 pVM->tm.s.fTSCVirtualized = true; /* trap rdtsc */ 242 242 else if (VBOX_FAILURE(rc)) 243 return VMSetError(pVM, rc, RT_SRC_POS, 244 N_("Configuration error: Failed to querying bool value \"UseRealTSC\". (%Vrc)"), rc); 243 return VMSetError(pVM, rc, RT_SRC_POS, 244 N_("Configuration error: Failed to querying bool value \"UseRealTSC\". (%Vrc)"), rc); 245 245 246 246 /* source */ … … 249 249 pVM->tm.s.fTSCUseRealTSC = false; /* use virtual time */ 250 250 else if (VBOX_FAILURE(rc)) 251 return VMSetError(pVM, rc, RT_SRC_POS, 252 N_("Configuration error: Failed to querying bool value \"UseRealTSC\". (%Vrc)"), rc); 251 return VMSetError(pVM, rc, RT_SRC_POS, 252 N_("Configuration error: Failed to querying bool value \"UseRealTSC\". (%Vrc)"), rc); 253 253 if (!pVM->tm.s.fTSCUseRealTSC) 254 254 pVM->tm.s.fTSCVirtualized = true; … … 277 277 } 278 278 else if (VBOX_FAILURE(rc)) 279 return VMSetError(pVM, rc, RT_SRC_POS, 280 N_("Configuration error: Failed to querying uint64_t value \"TSCTicksPerSecond\". (%Vrc)"), rc); 279 return VMSetError(pVM, rc, RT_SRC_POS, 280 N_("Configuration error: Failed to querying uint64_t value \"TSCTicksPerSecond\". (%Vrc)"), rc); 281 281 else if ( pVM->tm.s.cTSCTicksPerSecond < _1M 282 282 || pVM->tm.s.cTSCTicksPerSecond >= _4G) 283 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 283 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 284 284 N_("Configuration error: \"TSCTicksPerSecond\" = %RI64 is not in the range 1MHz..4GHz-1!"), 285 285 pVM->tm.s.cTSCTicksPerSecond); … … 295 295 else 296 296 CPUMR3SetCR4Feature(pVM, 0, ~X86_CR4_TSD); 297 LogRel(("TM: cTSCTicksPerSecond=%#RX64 (%RU64) fTSCVirtualized=%RTbool fTSCUseRealTSC=%RTbool fMaybeUseOffsettedHostTSC=%RTbool\n", 298 pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.fTSCVirtualized, 297 LogRel(("TM: cTSCTicksPerSecond=%#RX64 (%RU64) fTSCVirtualized=%RTbool fTSCUseRealTSC=%RTbool fMaybeUseOffsettedHostTSC=%RTbool\n", 298 pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.fTSCVirtualized, 299 299 pVM->tm.s.fTSCUseRealTSC, pVM->tm.s.fMaybeUseOffsettedHostTSC)); 300 300 … … 306 306 pVM->tm.s.u32VirtualSyncScheduleSlack = 100000; /* 0.100ms (ASSUMES virtual time is nanoseconds) */ 307 307 else if (VBOX_FAILURE(rc)) 308 return VMSetError(pVM, rc, RT_SRC_POS, 309 N_("Configuration error: Failed to querying 32-bit integer value \"ScheduleSlack\". (%Vrc)"), rc); 308 return VMSetError(pVM, rc, RT_SRC_POS, 309 N_("Configuration error: Failed to querying 32-bit integer value \"ScheduleSlack\". (%Vrc)"), rc); 310 310 311 311 rc = CFGMR3QueryU64(pCfgHandle, "CatchUpStopThreshold", &pVM->tm.s.u64VirtualSyncCatchUpStopThreshold); … … 313 313 pVM->tm.s.u64VirtualSyncCatchUpStopThreshold = 500000; /* 0.5ms */ 314 314 else if (VBOX_FAILURE(rc)) 315 return VMSetError(pVM, rc, RT_SRC_POS, 316 N_("Configuration error: Failed to querying 64-bit integer value \"CatchUpStopThreshold\". (%Vrc)"), rc); 315 return VMSetError(pVM, rc, RT_SRC_POS, 316 N_("Configuration error: Failed to querying 64-bit integer value \"CatchUpStopThreshold\". (%Vrc)"), rc); 317 317 318 318 rc = CFGMR3QueryU64(pCfgHandle, "CatchUpGiveUpThreshold", &pVM->tm.s.u64VirtualSyncCatchUpGiveUpThreshold); … … 320 320 pVM->tm.s.u64VirtualSyncCatchUpGiveUpThreshold = UINT64_C(60000000000); /* 60 sec */ 321 321 else if (VBOX_FAILURE(rc)) 322 return VMSetError(pVM, rc, RT_SRC_POS, 323 N_("Configuration error: Failed to querying 64-bit integer value \"CatchUpGiveUpThreshold\". (%Vrc)"), rc); 322 return VMSetError(pVM, rc, RT_SRC_POS, 323 N_("Configuration error: Failed to querying 64-bit integer value \"CatchUpGiveUpThreshold\". (%Vrc)"), rc); 324 324 325 325 … … 358 358 359 359 /* 360 * Configure real world time (UCT). 361 */ 362 rc = CFGMR3QueryS64(pCfgHandle, "UCTOffset", &pVM->tm.s.offUCT); 363 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 364 pVM->tm.s.offUCT = 0; /* ns */ 365 else if (VBOX_FAILURE(rc)) 366 return VMSetError(pVM, rc, RT_SRC_POS, 367 N_("Configuration error: Failed to querying 64-bit integer value \"UCTOffset\". (%Vrc)"), rc); 368 369 /* 360 370 * Setup the warp drive. 361 371 */ … … 366 376 pVM->tm.s.u32VirtualWarpDrivePercentage = 100; 367 377 else if (VBOX_FAILURE(rc)) 368 return VMSetError(pVM, rc, RT_SRC_POS, 369 N_("Configuration error: Failed to querying uint32_t value \"WarpDrivePercent\". (%Vrc)"), rc); 370 else if ( pVM->tm.s.u32VirtualWarpDrivePercentage < 2 378 return VMSetError(pVM, rc, RT_SRC_POS, 379 N_("Configuration error: Failed to querying uint32_t value \"WarpDrivePercent\". (%Vrc)"), rc); 380 else if ( pVM->tm.s.u32VirtualWarpDrivePercentage < 2 371 381 || pVM->tm.s.u32VirtualWarpDrivePercentage > 20000) 372 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 382 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 373 383 N_("Configuration error: \"WarpDrivePercent\" = %RI32 is not in the range 2..20000!"), 374 384 pVM->tm.s.u32VirtualWarpDrivePercentage); … … 385 395 u32Millies = 10; 386 396 else if (VBOX_FAILURE(rc)) 387 return VMSetError(pVM, rc, RT_SRC_POS, 397 return VMSetError(pVM, rc, RT_SRC_POS, 388 398 N_("Configuration error: Failed to query uint32_t value \"TimerMillies\", rc=%Vrc.\n"), rc); 389 399 rc = RTTimerCreate(&pVM->tm.s.pTimer, u32Millies, tmR3TimerCallback, pVM); … … 480 490 /** 481 491 * Checks if the host CPU has a fixed TSC frequency. 482 * 492 * 483 493 * @returns true if it has, false if it hasn't. 484 * 485 * @remark This test doesn't bother with very old CPUs that doesn't do power 494 * 495 * @remark This test doesn't bother with very old CPUs that doesn't do power 486 496 * management or any other stuff that might influence the TSC rate. 487 497 * This isn't currently relevant. … … 494 504 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX); 495 505 if ( uEAX >= 1 496 && uEBX == 0x68747541 497 && uECX == 0x444d4163 506 && uEBX == 0x68747541 507 && uECX == 0x444d4163 498 508 && uEDX == 0x69746e65) 499 509 { 500 /* 510 /* 501 511 * AuthenticAMD - Check for APM support and that TscInvariant is set. 502 512 * 503 * This test isn't correct with respect to fixed/non-fixed TSC and 513 * This test isn't correct with respect to fixed/non-fixed TSC and 504 514 * older models, but this isn't relevant since the result is currently 505 515 * only used for making a descision on AMD-V models. … … 518 528 && uEDX == 0x49656e69) 519 529 { 520 /* 530 /* 521 531 * GenuineIntel - Check the model number. 522 * 532 * 523 533 * This test is lacking in the same way and for the same reasons 524 534 * as the AMD test above. … … 552 562 uint64_t u64Hz; 553 563 PCSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage; 554 if ( pGip 564 if ( pGip 555 565 && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC) 556 566 { … … 564 574 if ( pGip 565 575 && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC 566 && (u64Hz = pGip->aCPUs[iCpu].u64CpuHz) 576 && (u64Hz = pGip->aCPUs[iCpu].u64CpuHz) 567 577 && u64Hz != ~(uint64_t)0) 568 578 return u64Hz; … … 838 848 else 839 849 pVM->tm.s.cTSCTicksPerSecond = u64Hz; 840 LogRel(("TM: cTSCTicksPerSecond=%#RX64 (%RU64) fTSCVirtualized=%RTbool fTSCUseRealTSC=%RTbool (state load)\n", 850 LogRel(("TM: cTSCTicksPerSecond=%#RX64 (%RU64) fTSCVirtualized=%RTbool fTSCUseRealTSC=%RTbool (state load)\n", 841 851 pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.fTSCVirtualized, pVM->tm.s.fTSCUseRealTSC)); 842 852 … … 852 862 /** 853 863 * Internal TMR3TimerCreate worker. 854 * 864 * 855 865 * @returns VBox status code. 856 866 * @param pVM The VM handle. … … 1117 1127 DECLINLINE(bool) tmR3AnyExpiredTimers(PVM pVM) 1118 1128 { 1119 /* 1129 /* 1120 1130 * Combine the time calculation for the first two since we're not on EMT 1121 1131 * TMVirtualSyncGet only permits EMT. … … 1124 1134 if (pVM->tm.s.CTXALLSUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire <= u64Now) 1125 1135 return true; 1126 u64Now = pVM->tm.s.fVirtualSyncTicking 1127 ? u64Now - pVM->tm.s.offVirtualSync 1136 u64Now = pVM->tm.s.fVirtualSyncTicking 1137 ? u64Now - pVM->tm.s.offVirtualSync 1128 1138 : pVM->tm.s.u64VirtualSync; 1129 1139 if (pVM->tm.s.CTXALLSUFF(paTimerQueues)[TMCLOCK_VIRTUAL_SYNC].u64Expire <= u64Now) … … 1147 1157 * @param pvUser VM handle. 1148 1158 * @thread Timer thread. 1149 * 1159 * 1150 1160 * @remark We cannot do the scheduling and queues running from a timer handler 1151 1161 * since it's not executing in EMT, and even if it was it would be async … … 1220 1230 tmR3TimerQueueRun(pVM, &pVM->tm.s.paTimerQueuesR3[TMCLOCK_TSC]); 1221 1231 STAM_PROFILE_ADV_SUSPEND(&pVM->tm.s.StatDoQueuesRun, r3); 1222 #endif 1232 #endif 1223 1233 1224 1234 /* TMCLOCK_REAL */ … … 1319 1329 1320 1330 /** 1321 * Schedules and runs any pending times in the timer queue for the 1331 * Schedules and runs any pending times in the timer queue for the 1322 1332 * synchronous virtual clock. 1323 * 1333 * 1324 1334 * This scheduling is a bit different from the other queues as it need 1325 * to implement the special requirements of the timer synchronous virtual 1335 * to implement the special requirements of the timer synchronous virtual 1326 1336 * clock, thus this 2nd queue run funcion. 1327 1337 * … … 1353 1363 * this will be implemented at a later point if neccessary. 1354 1364 * 1355 * Without this frame we would 1) having to run timers much more frequently 1365 * Without this frame we would 1) having to run timers much more frequently 1356 1366 * and 2) lag behind at a steady rate. 1357 1367 */ … … 1417 1427 || !(u64Max <= u64VirtualNow - pVM->tm.s.offVirtualSyncGivenUp) 1418 1428 || !(u64Now <= u64Max))) 1419 { 1429 { 1420 1430 AssertMsg2("Add the following to defect #1414:\n" 1421 1431 " u64Now=%016RX64\n" … … 1433 1443 " fVirtualSyncCatchUp=%RTbool (prev=%RTbool)\n", 1434 1444 u64Now, 1435 u64Max, 1445 u64Max, 1436 1446 pNext->u64Expire, 1437 1447 u64VirtualNow, … … 1443 1453 pVM->tm.s.u64VirtualSyncCatchUpPrev, 1444 1454 pVM->tm.s.u32VirtualSyncCatchUpPercentage, 1445 pVM->tm.s.fVirtualSyncTicking, 1455 pVM->tm.s.fVirtualSyncTicking, 1446 1456 pVM->tm.s.fVirtualSyncCatchUp, fWasInCatchup); 1447 1457 Assert(u64Now <= u64VirtualNow - pVM->tm.s.offVirtualSyncGivenUp); … … 1508 1518 1509 1519 /* 1510 * Restart the clock if it was stopped to serve any timers, 1520 * Restart the clock if it was stopped to serve any timers, 1511 1521 * and start/adjust catch-up if necessary. 1512 1522 */ … … 1552 1562 Assert(!(offLag & RT_BIT_64(63))); 1553 1563 1554 /* 1555 * Deal with starting, adjusting and stopping catchup. 1564 /* 1565 * Deal with starting, adjusting and stopping catchup. 1556 1566 */ 1557 1567 if (pVM->tm.s.fVirtualSyncCatchUp) … … 1615 1625 } 1616 1626 1617 /* 1618 * Update the offset and restart the clock. 1627 /* 1628 * Update the offset and restart the clock. 1619 1629 */ 1620 1630 ASMAtomicXchgU64(&pVM->tm.s.offVirtualSync, offNew); … … 1739 1749 RTTimeNow(pTime); 1740 1750 RTTimeSpecSubNano(pTime, pVM->tm.s.offVirtualSync - pVM->tm.s.offVirtualSyncGivenUp); 1751 RTTimeSpecAddNano(pTime, pVM->tm.s.offUCT); 1741 1752 return pTime; 1742 1753 } … … 1814 1825 pTimer->offPrev, 1815 1826 pTimer->offScheduleNext, 1816 pTimer->enmClock == TMCLOCK_REAL 1817 ? "Real " 1818 : pTimer->enmClock == TMCLOCK_VIRTUAL 1827 pTimer->enmClock == TMCLOCK_REAL 1828 ? "Real " 1829 : pTimer->enmClock == TMCLOCK_VIRTUAL 1819 1830 ? "Virt " 1820 1831 : pTimer->enmClock == TMCLOCK_VIRTUAL_SYNC … … 1849 1860 const uint64_t u64Real = TMRealGet(pVM); 1850 1861 1851 /* 1852 * TSC 1862 /* 1863 * TSC 1853 1864 */ 1854 1865 pHlp->pfnPrintf(pHlp, 1855 "Cpu Tick: %18RU64 (%#016RX64) %RU64Hz %s%s", 1866 "Cpu Tick: %18RU64 (%#016RX64) %RU64Hz %s%s", 1856 1867 u64TSC, u64TSC, TMCpuTicksPerSecond(pVM), 1857 1868 pVM->tm.s.fTSCTicking ? "ticking" : "paused", … … 1867 1878 pHlp->pfnPrintf(pHlp, "\n"); 1868 1879 1869 /* 1870 * virtual 1880 /* 1881 * virtual 1871 1882 */ 1872 1883 pHlp->pfnPrintf(pHlp, … … 1878 1889 pHlp->pfnPrintf(pHlp, "\n"); 1879 1890 1880 /* 1881 * virtual sync 1891 /* 1892 * virtual sync 1882 1893 */ 1883 1894 pHlp->pfnPrintf(pHlp, 1884 1895 "VirtSync: %18RU64 (%#016RX64) %s%s", 1885 u64VirtualSync, u64VirtualSync, 1896 u64VirtualSync, u64VirtualSync, 1886 1897 pVM->tm.s.fVirtualSyncTicking ? "ticking" : "paused", 1887 1898 pVM->tm.s.fVirtualSyncCatchUp ? " - catchup" : ""); … … 1894 1905 pHlp->pfnPrintf(pHlp, "\n"); 1895 1906 1896 /* 1897 * real 1907 /* 1908 * real 1898 1909 */ 1899 1910 pHlp->pfnPrintf(pHlp, -
trunk/src/VBox/VMM/TMInternal.h
r2581 r2611 291 291 /** CPU timestamp ticking enabled indicator (bool). (RDTSC) */ 292 292 bool fTSCTicking; 293 /** Set if we fully virtualize the TSC, i.e. intercept all rdtsc instructions. 293 /** Set if we fully virtualize the TSC, i.e. intercept all rdtsc instructions. 294 294 * Config variable: TSCVirtualized (bool) */ 295 295 bool fTSCVirtualized; 296 296 /** Set if we use the real TSC as time source or if we use the virtual clock. 297 * If fTSCVirtualized is set we maintain a offset to the TSC and pausing/resuming the 298 * ticking. fTSCVirtualized = false implies fTSCUseRealTSC = true. 297 * If fTSCVirtualized is set we maintain a offset to the TSC and pausing/resuming the 298 * ticking. fTSCVirtualized = false implies fTSCUseRealTSC = true. 299 299 * Config variable: TSCUseRealTSC (bool) */ 300 300 bool fTSCUseRealTSC; … … 304 304 /** The guest TSC when fTicking is cleared. */ 305 305 uint64_t u64TSC; 306 /** The number of CPU clock ticks per second (TMCLOCK_TSC). 306 /** The number of CPU clock ticks per second (TMCLOCK_TSC). 307 307 * Config variable: TSCTicksPerSecond (64-bit unsigned int) 308 308 * The config variable implies fTSCVirtualized = true and fTSCUseRealTSC = false. */ … … 317 317 /** Virtual timer synchronous time catch-up active. */ 318 318 bool volatile fVirtualSyncCatchUp; 319 /** WarpDrive percentage. 320 * 100% is normal (fVirtualSyncNormal == true). When other than 100% we apply 321 * this percentage to the raw time source for the period it's been valid in, 319 /** WarpDrive percentage. 320 * 100% is normal (fVirtualSyncNormal == true). When other than 100% we apply 321 * this percentage to the raw time source for the period it's been valid in, 322 322 * i.e. since u64VirtualWarpDriveStart. */ 323 323 uint32_t u32VirtualWarpDrivePercentage; … … 335 335 uint64_t volatile u64VirtualSync; 336 336 /** The offset of the timer synchronous virtual clock (TMCLOCK_VIRTUAL_SYNC) relative 337 * to the virtual clock (TMCLOCK_VIRTUAL). 337 * to the virtual clock (TMCLOCK_VIRTUAL). 338 338 * (This is accessed by the timer thread and must be updated atomically.) */ 339 339 uint64_t volatile offVirtualSync; 340 /** The offset into offVirtualSync that's been irrevocably given up by failed catch-up attempts. 340 /** The offset into offVirtualSync that's been irrevocably given up by failed catch-up attempts. 341 341 * Thus the current lag is offVirtualSync - offVirtualSyncGivenUp. */ 342 342 uint64_t offVirtualSyncGivenUp; … … 351 351 /** When to give up catch-up. */ 352 352 uint64_t u64VirtualSyncCatchUpGiveUpThreshold; 353 /** @def TM_MAX_CATCHUP_PERIODS 353 /** @def TM_MAX_CATCHUP_PERIODS 354 354 * The number of catchup rates. */ 355 355 #define TM_MAX_CATCHUP_PERIODS 10 356 /** The agressivness of the catch-up relative to how far we've lagged behind. 356 /** The agressivness of the catch-up relative to how far we've lagged behind. 357 357 * The idea is to have increasing catch-up percentage as the lag increases. */ 358 358 struct TMCATCHUPPERIOD … … 363 363 } aVirtualSyncCatchUpPeriods[TM_MAX_CATCHUP_PERIODS]; 364 364 365 /** The UCT offset in ns. 366 * This is *NOT* for converting UTC to local time. It is for converting real 367 * world UCT time to VM UCT time. This feature is indented for doing date 368 * testing of software and similar. 369 * @todo Implement warpdrive on UCT. */ 370 int64_t offUCT; 371 365 372 /** Timer queues for the different clock types - R3 Ptr */ 366 373 R3PTRTYPE(PTMTIMERQUEUE) paTimerQueuesR3; … … 412 419 STAMCOUNTER StatPostponedGC; 413 420 /** @} */ 414 /** Read the time 421 /** Read the time 415 422 * @{ */ 416 423 STAMCOUNTER StatVirtualGet; -
trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp
r2551 r2611 50 50 /** 51 51 * Get the time when we're not running at 100% 52 * 52 * 53 53 * @returns The timestamp. 54 54 * @param pVM The VM handle. … … 56 56 static uint64_t tmVirtualGetRawNonNormal(PVM pVM) 57 57 { 58 /* 59 * Recalculate the RTTimeNanoTS() value for the period where 58 /* 59 * Recalculate the RTTimeNanoTS() value for the period where 60 60 * warp drive has been enabled. 61 61 */ … … 66 66 u64 += pVM->tm.s.u64VirtualWarpDriveStart; 67 67 68 /* 69 * Now we apply the virtual time offset. 70 * (Which is the negate RTTimeNanoTS() value for when the virtual machine 68 /* 69 * Now we apply the virtual time offset. 70 * (Which is the negate RTTimeNanoTS() value for when the virtual machine 71 71 * started if it had been running continuously without any suspends.) 72 72 */ … … 78 78 /** 79 79 * Get the raw virtual time. 80 * 81 * @returns The current time stamp. 80 * 81 * @returns The current time stamp. 82 82 * @param pVM The VM handle. 83 83 */ … … 300 300 /** 301 301 * Gets the current lag of the synchronous virtual clock (relative to the virtual clock). 302 * 302 * 303 303 * @return The current lag. 304 304 * @param pVM VM handle. … … 312 312 /** 313 313 * Get the current catch-up percent. 314 * 314 * 315 315 * @return The current catch0up percent. 0 means running at the same speed as the virtual clock. 316 316 * @param pVM VM handle. … … 385 385 /** 386 386 * Gets the current warp drive percent. 387 * 387 * 388 388 * @returns The warp drive percent. 389 389 * @param pVM The VM handle. … … 397 397 /** 398 398 * Sets the warp drive percent of the virtual time. 399 * 399 * 400 400 * @returns VBox status code. 401 401 * @param pVM The VM handle. … … 404 404 TMDECL(int) TMVirtualSetWarpDrive(PVM pVM, uint32_t u32Percent) 405 405 { 406 /** @todo This isn't a feature specific to virtual time, move to TM level. (It 407 * should affect the TMR3UCTNow as well! */ 406 408 #ifdef IN_RING3 407 409 PVMREQ pReq; … … 414 416 415 417 return tmVirtualSetWarpDrive(pVM, u32Percent); 416 #endif 418 #endif 417 419 } 418 420 … … 420 422 /** 421 423 * EMT worker for tmVirtualSetWarpDrive. 422 * 424 * 423 425 * @returns VBox status code. 424 426 * @param pVM The VM handle. … … 431 433 * Validate it. 432 434 */ 433 AssertMsgReturn(u32Percent >= 2 && u32Percent <= 20000, 434 ("%RX32 is not between 2 and 20000 (inclusive).\n", u32Percent), 435 AssertMsgReturn(u32Percent >= 2 && u32Percent <= 20000, 436 ("%RX32 is not between 2 and 20000 (inclusive).\n", u32Percent), 435 437 VERR_INVALID_PARAMETER); 436 438 437 /* 439 /* 438 440 * If the time is running we'll have to pause it before we can change 439 441 * the warp drive settings. … … 450 452 pVM->tm.s.u32VirtualWarpDrivePercentage = u32Percent; 451 453 pVM->tm.s.fVirtualWarpDrive = u32Percent != 100; 452 LogRel(("TM: u32VirtualWarpDrivePercentage=%RI32 fVirtualWarpDrive=%RTbool\n", 454 LogRel(("TM: u32VirtualWarpDrivePercentage=%RI32 fVirtualWarpDrive=%RTbool\n", 453 455 pVM->tm.s.u32VirtualWarpDrivePercentage, pVM->tm.s.fVirtualWarpDrive)); 454 456
Note:
See TracChangeset
for help on using the changeset viewer.