VirtualBox

Changeset 443 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jan 30, 2007 9:53:52 PM (18 years ago)
Author:
vboxsync
Message:

Implemented Warp drive. This can be configured using the WarpDrivePercentage (2..20000) or the TMVirtualSetWarpDrive API.

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

Legend:

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

    r23 r443  
    193193
    194194    /*
    195      * Start the timer.
     195     * Setup the warp drive.
     196     */
     197    rc = CFGMR3QueryU32(CFGMR3GetRoot(pVM), "WarpDrivePercentage", &pVM->tm.s.u32VirtualWarpDrivePercentage);
     198    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     199        pVM->tm.s.u32VirtualWarpDrivePercentage = 100;
     200    else if (VBOX_FAILURE(rc))
     201        return VMSetError(pVM, rc, RT_SRC_POS,
     202                          N_("Configuration error: Failed to querying uint32_t value \"WarpDrivePercent\". (%Vrc)"), rc);
     203    else if (   pVM->tm.s.u32VirtualWarpDrivePercentage < 2
     204             || pVM->tm.s.u32VirtualWarpDrivePercentage > 20000)
     205        return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
     206                          N_("Configuration error: \"WarpDrivePercent\" = %RI32 is not in the range 2..20000!"),
     207                          pVM->tm.s.u32VirtualWarpDrivePercentage);
     208    pVM->tm.s.fVirtualWarpDrive = pVM->tm.s.u32VirtualWarpDrivePercentage != 100;
     209    if (pVM->tm.s.fVirtualWarpDrive)
     210        LogRel(("TM: u32VirtualWarpDrivePercentage=%RI32\n", pVM->tm.s.u32VirtualWarpDrivePercentage));
     211
     212    /*
     213     * Start the timer (guard against REM not yielding).
    196214     */
    197215    uint32_t u32Millies;
     
    200218        u32Millies = 10;
    201219    else if (VBOX_FAILURE(rc))
    202     {
    203         AssertMsgFailed(("Configuration error: Failed to query uint32_t value \"TimerMillies\", rc=%Vrc.\n", rc));
    204         return rc;
    205     }
     220        return VMSetError(pVM, rc, RT_SRC_POS,
     221                          N_("Configuration error: Failed to query uint32_t value \"TimerMillies\", rc=%Vrc.\n"), rc);
    206222    rc = RTTimerCreate(&pVM->tm.s.pTimer, u32Millies, tmR3TimerCallback, pVM);
    207223    if (VBOX_FAILURE(rc))
  • trunk/src/VBox/VMM/TMInternal.h

    r161 r443  
    297297    uint64_t                    cTSCTicksPerSecond;
    298298
    299     /** Padding to ensure that 64-bit values are equaly aligned everywhere. */
    300     uint32_t                    uReserved;
    301299    /** Virtual time ticking enabled indicator (bool). (TMCLOCK_VIRTUAL) */
    302300    bool                        fVirtualTicking;
     301    /** Virtual time is not running at 100%. */
     302    bool                        fVirtualWarpDrive;
    303303    /** Virtual timer synchronous time ticking enabled indicator (bool). (TMCLOCK_VIRTUAL_SYNC) */
    304304    bool                        fVirtualSyncTicking;
    305305    /** Virtual timer synchronous time catch-up active. */
    306306    bool volatile               fVirtualSyncCatchUp;
     307    /** WarpDrive percentage.
     308     * 100% is normal (fVirtualSyncNormal == true). When other than 100% we apply
     309     * this percentage to the raw time source for the period it's been valid in,
     310     * i.e. since u64VirtualWarpDriveStart. */
     311    uint32_t                    u32VirtualWarpDrivePercentage;
    307312
    308313    /** The offset of the virtual clock relative to it's timesource.
     
    311316    /** The guest virtual time when fVirtualTicking is cleared. */
    312317    uint64_t                    u64Virtual;
     318    /** When the Warp drive was started or last adjusted.
     319     * Only valid when fVirtualWarpDrive is set. */
     320    uint64_t                    u64VirtualWarpDriveStart;
    313321
    314322    /** The offset of the virtual timer synchronous clock (TMCLOCK_VIRTUAL_SYNC) relative
     
    319327    /** The guest virtual timer synchronous time when fVirtualSyncTicking is cleared. */
    320328    uint64_t                    u64VirtualSync;
    321     /** How many precent faster the clock should advance when catch-up is active. */
    322     uint32_t                    u32VirtualSyncCatchupPrecentage;
     329    /** How many percent faster the clock should advance when catch-up is active. */
     330    uint32_t                    u32VirtualSyncCatchupPercentage;
    323331    /** When to stop catch-up. */
    324332    uint32_t                    u32VirtualSyncCatchupStopThreashold;
  • trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp

    r23 r443  
    4040
    4141
     42/*******************************************************************************
     43*   Internal Functions                                                         *
     44*******************************************************************************/
     45static DECLCALLBACK(int) tmVirtualSetWarpDrive(PVM pVM, uint32_t u32Percent);
     46
     47
     48
     49/**
     50 * Get the time when we're not running at 100%
     51 *
     52 * @returns The timestamp.
     53 * @param   pVM     The VM handle.
     54 */
     55uint64_t tmVirtualGetRawNonNormal(PVM pVM)
     56{
     57    /*
     58     * Recalculate the RTTimeNanoTS() value for the period where
     59     * warp drive has been enabled.
     60     */
     61    uint64_t u64 = RTTimeNanoTS();
     62    u64 -= pVM->tm.s.u64VirtualWarpDriveStart;
     63    u64 *= pVM->tm.s.u32VirtualWarpDrivePercentage;
     64    u64 /= 100;
     65    u64 += pVM->tm.s.u64VirtualWarpDriveStart;
     66
     67    /*
     68     * Now we apply the virtual time offset.
     69     * (Which is the negate RTTimeNanoTS() value for when the virtual machine
     70     * started if it had been running continuously without any suspends.)
     71     */
     72    u64 -= pVM->tm.s.u64VirtualOffset;
     73    return u64;
     74}
     75
     76
     77/**
     78 * Get the raw virtual time.
     79 *
     80 * @returns The current time stamp.
     81 * @param   pVM     The VM handle.
     82 */
     83DECLINLINE(uint64_t) tmVirtualGetRaw(PVM pVM)
     84{
     85    if (RT_LIKELY(!pVM->tm.s.fVirtualWarpDrive))
     86        return RTTimeNanoTS() - pVM->tm.s.u64VirtualOffset;
     87    return tmVirtualGetRawNonNormal(pVM);
     88}
    4289
    4390
     
    59106    {
    60107        STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGet);
    61         u64 = RTTimeNanoTS() - pVM->tm.s.u64VirtualOffset;
     108        u64 = tmVirtualGetRaw(pVM);
    62109
    63110        /*
     
    102149         */
    103150        Assert(pVM->tm.s.fVirtualTicking);
    104         u64 = RTTimeNanoTS() - pVM->tm.s.u64VirtualOffset;
     151        u64 = tmVirtualGetRaw(pVM);
    105152        if (    !VM_FF_ISSET(pVM, VM_FF_TIMER)
    106153            &&  pVM->tm.s.CTXALLSUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire <= u64)
     
    145192            if (!(u64Delta >> 32))
    146193            {
    147                 uint32_t u32Sub = ASMDivU64ByU32RetU32(ASMMult2xU32RetU64((uint32_t)u64Delta, pVM->tm.s.u32VirtualSyncCatchupPrecentage),
     194                uint32_t u32Sub = ASMDivU64ByU32RetU32(ASMMult2xU32RetU64((uint32_t)u64Delta, pVM->tm.s.u32VirtualSyncCatchupPercentage),
    148195                                                       100);
    149196                if (u32Sub < (uint32_t)u64Delta)
     
    223270    {
    224271        STAM_COUNTER_INC(&pVM->tm.s.StatVirtualResume);
    225         pVM->tm.s.u64VirtualOffset = RTTimeNanoTS() - pVM->tm.s.u64Virtual;
     272        pVM->tm.s.u64VirtualWarpDriveStart = RTTimeNanoTS();
     273        pVM->tm.s.u64VirtualOffset = pVM->tm.s.u64VirtualWarpDriveStart - pVM->tm.s.u64Virtual;
    226274        pVM->tm.s.fVirtualTicking = true;
    227275        pVM->tm.s.fVirtualSyncTicking = true;
     
    251299#ifndef TM_CONTINUOUS_TIME
    252300        STAM_COUNTER_INC(&pVM->tm.s.StatVirtualPause);
    253         pVM->tm.s.u64Virtual = RTTimeNanoTS() - pVM->tm.s.u64VirtualOffset;
     301        pVM->tm.s.u64Virtual = tmVirtualGetRaw(pVM);
    254302        pVM->tm.s.fVirtualSyncTicking = false;
    255303        pVM->tm.s.fVirtualTicking = false;
     
    260308    AssertFailed();
    261309    return VERR_INTERNAL_ERROR;
     310}
     311
     312
     313/**
     314 * Gets the current warp drive percent.
     315 *
     316 * @returns The warp drive percent.
     317 * @param   pVM         The VM handle.
     318 */
     319TMDECL(uint32_t) TMVirtualGetWarpDrive(PVM pVM)
     320{
     321    return pVM->tm.s.u32VirtualWarpDrivePercentage;
     322}
     323
     324
     325/**
     326 * Sets the warp drive percent of the virtual time.
     327 *
     328 * @returns VBox status code.
     329 * @param   pVM         The VM handle.
     330 * @param   u32Percent  The new percentage. 100 means normal operation.
     331 */
     332TMDECL(int) TMVirtualSetWarpDrive(PVM pVM, uint32_t u32Percent)
     333{
     334#ifdef IN_RING3
     335    PVMREQ pReq;
     336    int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)tmVirtualSetWarpDrive, 2, pVM, u32Percent);
     337    if (VBOX_SUCCESS(rc))
     338        rc = pReq->iStatus;
     339    VMR3ReqFree(pReq);
     340    return rc;
     341#else
     342
     343    return tmVirtualSetWarpDrive(pVM, u32Percent);
     344#endif
     345}
     346
     347
     348/**
     349 * EMT worker for tmVirtualSetWarpDrive.
     350 *
     351 * @returns VBox status code.
     352 * @param   pVM         The VM handle.
     353 * @param   u32Percent  See TMVirtualSetWarpDrive().
     354 * @internal
     355 */
     356static DECLCALLBACK(int) tmVirtualSetWarpDrive(PVM pVM, uint32_t u32Percent)
     357{
     358    /*
     359     * Validate it.
     360     */
     361    AssertMsgReturn(u32Percent >= 2 && u32Percent <= 20000,
     362                    ("%RX32 is not between 2 and 20000 (inclusive).\n", u32Percent),
     363                    VERR_INVALID_PARAMETER);
     364
     365    /*
     366     * If the time is running we'll have to pause it before we can change
     367     * the warp drive settings.
     368     */
     369    bool fPaused = pVM->tm.s.fVirtualTicking;
     370    if (fPaused)
     371    {
     372        int rc = TMVirtualPause(pVM);
     373        AssertRCReturn(rc, rc);
     374    }
     375
     376    pVM->tm.s.u32VirtualWarpDrivePercentage = u32Percent;
     377    pVM->tm.s.fVirtualWarpDrive = u32Percent != 100;
     378    LogRel(("TM: u32VirtualWarpDrivePercentage=%RI32 fVirtualWarpDrive=%RTbool\n",
     379            pVM->tm.s.u32VirtualWarpDrivePercentage, pVM->tm.s.fVirtualWarpDrive));
     380
     381    if (fPaused)
     382    {
     383        int rc = TMVirtualResume(pVM);
     384        AssertRCReturn(rc, rc);
     385    }
     386
     387    return VINF_SUCCESS;
    262388}
    263389
  • trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp

    r161 r443  
    408408    GEN_CHECK_OFF(TM, u64TSC);
    409409    GEN_CHECK_OFF(TM, cTSCTicksPerSecond);
    410     GEN_CHECK_OFF(TM, uReserved);
    411410    GEN_CHECK_OFF(TM, fVirtualTicking);
     411    GEN_CHECK_OFF(TM, fVirtualWarpDrive);
     412    GEN_CHECK_OFF(TM, u32VirtualWarpDrivePercentage);
    412413    GEN_CHECK_OFF(TM, u64VirtualOffset);
    413414    GEN_CHECK_OFF(TM, u64Virtual);
     415    GEN_CHECK_OFF(TM, u64VirtualWarpDriveStart);
    414416    GEN_CHECK_OFF(TM, u64VirtualSync);
    415     GEN_CHECK_OFF(TM, u32VirtualSyncCatchupPrecentage);
     417    GEN_CHECK_OFF(TM, u32VirtualSyncCatchupPercentage);
    416418    GEN_CHECK_OFF(TM, u32VirtualSyncCatchupStopThreashold);
    417419    GEN_CHECK_OFF(TM, u64VirtualSyncCatchupStartTreashold);
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