VirtualBox

Changeset 1057 in vbox for trunk


Ignore:
Timestamp:
Feb 23, 2007 8:38:37 PM (18 years ago)
Author:
vboxsync
Message:

Trapping and virtualizing TSC (both disabled).

Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/tm.h

    r443 r1057  
    3434/** Enable a timer hack which improves the timer response/resolution a bit. */
    3535#define VBOX_HIGH_RES_TIMERS_HACK
    36 
    37 /** Use the real CPU TSC. */
    38 #define TM_REAL_CPU_TICK
    3936
    4037
  • trunk/src/VBox/VMM/EM.cpp

    r1055 r1057  
    32173217        rc = TMVirtualResume(pVM);
    32183218        Assert(rc == VINF_SUCCESS);
     3219        rc = TMCpuTickResume(pVM);
     3220        Assert(rc == VINF_SUCCESS);
    32193221
    32203222        /*
     
    33363338                    Log2(("EMR3ExecuteVM: returns VINF_EM_OFF (%d -> %d)\n", pVM->em.s.enmState, EMSTATE_TERMINATING));
    33373339                    TMVirtualPause(pVM);
     3340                    TMCpuTickPause(pVM);
    33383341                    VMMR3Unlock(pVM);
    33393342                    STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
     
    33473350                    Log(("EMR3ExecuteVM returns VINF_EM_TERMINATE (%d -> %d)\n", pVM->em.s.enmState, EMSTATE_TERMINATING));
    33483351                    TMVirtualPause(pVM);
     3352                    TMCpuTickPause(pVM);
    33493353                    STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
    33503354                    return rc;
     
    34553459                case EMSTATE_SUSPENDED:
    34563460                    TMVirtualPause(pVM);
     3461                    TMCpuTickPause(pVM);
    34573462                    VMMR3Unlock(pVM);
    34583463                    STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
     
    34653470                case EMSTATE_DEBUG_GUEST_RAW:
    34663471                    TMVirtualPause(pVM);
     3472                    TMCpuTickPause(pVM);
    34673473                    rc = emR3Debug(pVM, rc);
    34683474                    TMVirtualResume(pVM);
     3475                    TMCpuTickResume(pVM);
    34693476                    Log2(("EMR3ExecuteVM: enmr3Debug -> %Vrc (state %d)\n", rc, pVM->em.s.enmState));
    34703477                    break;
     
    34763483                {
    34773484                    TMVirtualPause(pVM);
     3485                    TMCpuTickPause(pVM);
    34783486                    STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
    34793487
     
    34903498                    STAM_PROFILE_ADV_START(&pVM->em.s.StatTotal, x);
    34913499                    TMVirtualResume(pVM);
     3500                    TMCpuTickResume(pVM);
    34923501                    break;
    34933502                }
     
    35003509                    /** @todo this ain't entirely safe. make a better return code check and specify this in DBGF/emR3Debug. */
    35013510                    TMVirtualPause(pVM);
     3511                    TMCpuTickPause(pVM);
    35023512                    VMMR3FatalDump(pVM, rc);
    35033513                    int rc2 = emR3Debug(pVM, rc);
     
    35103520                    }
    35113521                    TMVirtualResume(pVM);
     3522                    TMCpuTickResume(pVM);
    35123523                    rc = rc2;
    35133524                    /** @todo we're not doing the right thing in emR3Debug and will cause code to be executed on disconnect and stuff.. */
     
    35253536                    pVM->em.s.enmState = EMSTATE_GURU_MEDITATION;
    35263537                    TMVirtualPause(pVM);
     3538                    TMCpuTickPause(pVM);
    35273539                    VMMR3Unlock(pVM);
    35283540                    STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
     
    35383550        LogFlow(("EMR3ExecuteVM: returns %Vrc (longjmp / fatal error)\n", rc));
    35393551        TMVirtualPause(pVM);
     3552        TMCpuTickPause(pVM);
    35403553        VMMR3FatalDump(pVM, rc);
    35413554        emR3Debug(pVM, rc);
  • trunk/src/VBox/VMM/TM.cpp

    r1027 r1057  
    9797static DECLCALLBACK(void)   tmR3TimerInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    9898static DECLCALLBACK(void)   tmR3TimerInfoActive(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
     99static DECLCALLBACK(void)   tmR3InfoClocks(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    99100
    100101
     
    178179
    179180    /*
    180      * Calibrate the cpu timestamp counter.
    181      */
    182     pVM->tm.s.cTSCTicksPerSecond = tmR3Calibrate();
    183     Log(("TM: cTSCTicksPerSecond=%#RX64 (%RU64)\n", pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.cTSCTicksPerSecond));
     181     * Determin the TSC configuration and frequency.
     182     */
     183    /* mode */
     184    rc = CFGMR3QueryBool(CFGMR3GetRoot(pVM), "TSCVirtualized", &pVM->tm.s.fTSCVirtualized);
     185    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     186#if 0 /* seems to kind of work... */
     187        pVM->tm.s.fTSCVirtualized = true;
     188#else
     189        pVM->tm.s.fTSCVirtualized = false;
     190#endif
     191    else if (VBOX_FAILURE(rc))
     192        return VMSetError(pVM, rc, RT_SRC_POS,
     193                          N_("Configuration error: Failed to querying bool value \"UseRealTSC\". (%Vrc)"), rc);
     194
     195    /* source */
     196    rc = CFGMR3QueryBool(CFGMR3GetRoot(pVM), "UseRealTSC", &pVM->tm.s.fTSCTicking);
     197    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     198#if 1 /* doesn't seem to work reliably yet... xp takes several ~2 min to shutdown now. darn. */
     199        pVM->tm.s.fTSCUseRealTSC = false; /* virtualize it */
     200#else
     201        pVM->tm.s.fTSCUseRealTSC = true; /* don't virtualize it */
     202#endif
     203    else if (VBOX_FAILURE(rc))
     204        return VMSetError(pVM, rc, RT_SRC_POS,
     205                          N_("Configuration error: Failed to querying bool value \"UseRealTSC\". (%Vrc)"), rc);
     206    if (!pVM->tm.s.fTSCUseRealTSC)
     207        pVM->tm.s.fTSCVirtualized = true;
     208
     209    /* frequency */
     210    rc = CFGMR3QueryU64(CFGMR3GetRoot(pVM), "TSCTicksPerSecond", &pVM->tm.s.cTSCTicksPerSecond);
     211    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     212    {
     213#if 0  /* when tmCpuTickGetRawVirtual is done */
     214        pVM->tm.s.cTSCTicksPerSecond = tmR3Calibrate();
     215#else
     216        if (pVM->tm.s.fTSCUseRealTSC)
     217            pVM->tm.s.cTSCTicksPerSecond = tmR3Calibrate();
     218        else
     219            pVM->tm.s.cTSCTicksPerSecond = TMCLOCK_FREQ_VIRTUAL;/* same as the virtual clock. */
     220#endif
     221    }
     222    else if (VBOX_FAILURE(rc))
     223        return VMSetError(pVM, rc, RT_SRC_POS,
     224                          N_("Configuration error: Failed to querying uint64_t value \"TSCTicksPerSecond\". (%Vrc)"), rc);
     225#if 0 /* when tmCpuTickGetRawVirtual is done */
     226    else if (   pVM->tm.s.cTSCTicksPerSecond < _1M
     227             || pVM->tm.s.cTSCTicksPerSecond > _1E)
     228        return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
     229                          N_("Configuration error: \"TSCTicksPerSecond\" = %RI64 is not in the range 1MHz..1EHz!"),
     230                          pVM->tm.s.cTSCTicksPerSecond);
     231#else
     232    else if (pVM->tm.s.cTSCTicksPerSecond != TMCLOCK_FREQ_VIRTUAL)
     233        return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
     234                          N_("Configuration error: \"TSCTicksPerSecond\" = %RI64 is not 1GHz! (temporary restriction)"),
     235                          pVM->tm.s.cTSCTicksPerSecond);
     236#endif
     237    else
     238    {
     239        pVM->tm.s.fTSCUseRealTSC = false;
     240        pVM->tm.s.fTSCVirtualized = true;
     241    }
     242
     243    /* setup and report */
     244    if (pVM->tm.s.fTSCUseRealTSC)
     245        CPUMR3SetCR4Feature(pVM, 0, ~X86_CR4_TSD);
     246    else
     247        CPUMR3SetCR4Feature(pVM, X86_CR4_TSD, ~X86_CR4_TSD);
     248    LogRel(("TM: cTSCTicksPerSecond=%#RX64 (%RU64) fTSCVirtualized=%RTbool fTSCUseRealTSC=%RTbool\n",
     249            pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.fTSCVirtualized, pVM->tm.s.fTSCUseRealTSC));
    184250
    185251    /*
     
    272338    DBGFR3InfoRegisterInternal(pVM, "timers",       "Dumps all timers. No arguments.",          tmR3TimerInfo);
    273339    DBGFR3InfoRegisterInternal(pVM, "activetimers", "Dumps active all timers. No arguments.",   tmR3TimerInfoActive);
     340    DBGFR3InfoRegisterInternal(pVM, "clocks",       "Display the time of the various clocks.",  tmR3InfoClocks);
    274341
    275342    return VINF_SUCCESS;
     
    11921259}
    11931260
     1261
     1262/**
     1263 * Display all clocks.
     1264 *
     1265 * @param   pVM         VM Handle.
     1266 * @param   pHlp        The info helpers.
     1267 * @param   pszArgs     Arguments, ignored.
     1268 */
     1269static DECLCALLBACK(void) tmR3InfoClocks(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
     1270{
     1271    NOREF(pszArgs);
     1272
     1273    /* TSC */
     1274    uint64_t u64 = TMCpuTickGet(pVM);
     1275    pHlp->pfnPrintf(pHlp,
     1276                    "Cpu Tick: %#RX64 (%RU64) %RU64Hz %s%s",
     1277                    u64, u64, TMCpuTicksPerSecond(pVM),
     1278                    pVM->tm.s.fTSCTicking ? "ticking" : "paused",
     1279                    pVM->tm.s.fTSCVirtualized ? " - virtualized" : "");
     1280    if (pVM->tm.s.fTSCUseRealTSC)
     1281    {
     1282        pHlp->pfnPrintf(pHlp, "- real tsc");
     1283        if (pVM->tm.s.u64TSCOffset)
     1284            pHlp->pfnPrintf(pHlp, "\n          offset %#RX64", pVM->tm.s.u64TSCOffset);
     1285    }
     1286    else
     1287        pHlp->pfnPrintf(pHlp, "- virtual clock");
     1288    pHlp->pfnPrintf(pHlp, "\n");
     1289
     1290    /* virtual */
     1291    u64 = TMVirtualGet(pVM);
     1292    pHlp->pfnPrintf(pHlp,
     1293                    " Virtual: %#RX64 (%RU64) %RU64Hz %s",
     1294                    u64, u64, TMVirtualGetFreq(pVM),
     1295                    pVM->tm.s.fVirtualTicking ? "ticking" : "paused");
     1296    if (pVM->tm.s.fVirtualWarpDrive)
     1297        pHlp->pfnPrintf(pHlp, " WarpDrive %RU32 %%", pVM->tm.s.u32VirtualWarpDrivePercentage);
     1298    pHlp->pfnPrintf(pHlp, "\n");
     1299
     1300    /* virtual sync */
     1301    u64 = TMVirtualGetSync(pVM);
     1302    pHlp->pfnPrintf(pHlp,
     1303                    "VirtSync: %#RX64 (%RU64) %s%s",
     1304                    u64, u64,
     1305                    pVM->tm.s.fVirtualSyncTicking ? "ticking" : "paused",
     1306                    pVM->tm.s.fVirtualSyncCatchUp ? " - catchup" : "");
     1307    if (pVM->tm.s.u64VirtualSyncOffset)
     1308        pHlp->pfnPrintf(pHlp, "\n          offset %#RX64", pVM->tm.s.u64VirtualSyncOffset);
     1309    pHlp->pfnPrintf(pHlp, "\n");
     1310
     1311    /* real */
     1312    u64 = TMRealGet(pVM);
     1313    pHlp->pfnPrintf(pHlp,
     1314                    "    Real: %#RX64 (%RU64) %RU64Hz\n",
     1315                    u64, u64, TMRealGetFreq(pVM));
     1316}
  • trunk/src/VBox/VMM/TMInternal.h

    r443 r1057  
    288288    /** CPU timestamp ticking enabled indicator (bool). (RDTSC) */
    289289    bool                        fTSCTicking;
     290    /** Set if we fully virtualize the TSC, i.e. intercept all rdtsc instructions.
     291     * Config variable: TSCVirtualized (bool) */
     292    bool                        fTSCVirtualized;
     293    /** Set if we use the real TSC as time source or if we use the virtual clock.
     294     * If fTSCVirtualized is set we maintain a offset to the TSC and pausing/resuming the
     295     * ticking. fTSCVirtualized = false implies fTSCUseRealTSC = true.
     296     * Config variable: TSCUseRealTSC (bool) */
     297    bool                        fTSCUseRealTSC;
    290298    /** The offset between the host TSC and the Guest TSC.
    291      * Only valid if fTicking is set. */
     299     * Only valid if fTicking is set and and fTSCUseRealTSC is clear. */
    292300    uint64_t                    u64TSCOffset;
    293301    /** The guest TSC when fTicking is cleared. */
    294302    uint64_t                    u64TSC;
    295     /** The number of CPU clock ticks per second (TMCLOCK_TSC).
    296      * If GIP is available, g_pSUPGlobalInfoPage->u64CpuHz will be used instead. */
     303    /** The number of CPU clock ticks per second (TMCLOCK_TSC).
     304     * Config variable: TSCTicksPerSecond (64-bit unsigned int)
     305     * The config variable implies fTSCVirtualized = true and fTSCUseRealTSC = false. */
    297306    uint64_t                    cTSCTicksPerSecond;
    298307
  • trunk/src/VBox/VMM/VMEmt.cpp

    r866 r1057  
    305305     * and the yielder is suspended.
    306306     */
    307     TMCpuTickResume(pVM);
     307//    TMCpuTickResume(pVM);
    308308    VMMR3YieldSuspend(pVM);
    309309
     
    416416     * and resume the yielder.
    417417     */
    418     TMCpuTickPause(pVM);
     418//    TMCpuTickPause(pVM);
    419419    VMMR3YieldResume(pVM);
    420420
  • trunk/src/VBox/VMM/VMMAll/TMAll.cpp

    r1027 r1057  
    609609
    610610        case TMCLOCK_TSC:
    611         {
    612             PCSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
    613             if (pGip)
    614                 return SUPGetCpuHzFromGIP(pGip) ;
    615             return pTimer->CTXALLSUFF(pVM)->tm.s.cTSCTicksPerSecond;
    616         }
     611            return TMCpuTicksPerSecond(pTimer->CTXALLSUFF(pVM));
    617612
    618613        default:
  • trunk/src/VBox/VMM/VMMAll/TMAllCpu.cpp

    r23 r1057  
    2828#include "TMInternal.h"
    2929#include <VBox/vm.h>
     30#include <VBox/sup.h>
    3031
    3132#include <VBox/param.h>
     
    3334#include <iprt/assert.h>
    3435#include <iprt/asm.h>
     36
     37
     38/**
     39 * Gets the raw cpu tick from current virtual time.
     40 */
     41DECLINLINE(uint64_t) tmCpuTickGetRawVirtual(PVM pVM)
     42{
     43    uint64_t u64 = TMVirtualGet(pVM);
     44    /** @todo calc tsc from virtual time. */
     45    return u64;
     46}
    3547
    3648
     
    4658    {
    4759        pVM->tm.s.fTSCTicking = true;
    48 #ifndef TM_REAL_CPU_TICK
    49         pVM->tm.s.u64TSCOffset = ASMReadTSC() - pVM->tm.s.u64TSC;
    50 #endif
     60        if (pVM->tm.s.fTSCVirtualized)
     61        {
     62            if (pVM->tm.s.fTSCUseRealTSC)
     63                pVM->tm.s.u64TSCOffset = ASMReadTSC() - pVM->tm.s.u64TSC;
     64            else
     65                pVM->tm.s.u64TSCOffset = tmCpuTickGetRawVirtual(pVM) - pVM->tm.s.u64TSC;
     66        }
    5167        return VINF_SUCCESS;
    5268    }
     
    6682    if (pVM->tm.s.fTSCTicking)
    6783    {
    68 #ifndef TM_REAL_CPU_TICK
    69         pVM->tm.s.u64TSC = ASMReadTSC() - pVM->tm.s.u64TSCOffset;
    70 #endif
     84        if (!pVM->tm.s.fTSCVirtualized)
     85        {
     86            if (pVM->tm.s.fTSCUseRealTSC)
     87                pVM->tm.s.u64TSC = ASMReadTSC() - pVM->tm.s.u64TSCOffset;
     88            else
     89                pVM->tm.s.u64TSC = tmCpuTickGetRawVirtual(pVM) - pVM->tm.s.u64TSCOffset;
     90        }
    7191        pVM->tm.s.fTSCTicking = false;
    7292        return VINF_SUCCESS;
     
    86106TMDECL(uint64_t) TMCpuTickGet(PVM pVM)
    87107{
    88 #ifdef TM_REAL_CPU_TICK
    89     return ASMReadTSC();
    90 #else
    91     if (pVM->tm.s.fTSCTicking)
    92         return ASMReadTSC() - pVM->tm.s.u64TSCOffset;
    93     return pVM->tm.s.u64TSC;
    94 #endif
     108    uint64_t u64;
     109    if (pVM->tm.s.fTSCUseRealTSC)
     110        u64 = ASMReadTSC();
     111    else
     112    {
     113        if (pVM->tm.s.fTSCTicking)
     114        {
     115            if (pVM->tm.s.fTSCUseRealTSC)
     116                u64 = ASMReadTSC() - pVM->tm.s.u64TSCOffset;
     117            else
     118                u64 = tmCpuTickGetRawVirtual(pVM) - pVM->tm.s.u64TSCOffset;
     119        }
     120        else
     121            u64 = pVM->tm.s.u64TSC;
     122    }
     123    return u64;
    95124}
    96125
     
    119148TMDECL(uint64_t) TMCpuTicksPerSecond(PVM pVM)
    120149{
     150    if (pVM->tm.s.fTSCUseRealTSC)
     151    {
     152        uint64_t cTSCTicksPerSecond = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
     153        if (RT_LIKELY(cTSCTicksPerSecond != ~(uint64_t)0))
     154            return cTSCTicksPerSecond;
     155    }
    121156    return pVM->tm.s.cTSCTicksPerSecond;
    122157}
  • trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp

    r443 r1057  
    372372        int rc = TMVirtualPause(pVM);
    373373        AssertRCReturn(rc, rc);
     374        rc = TMCpuTickPause(pVM);
     375        AssertRCReturn(rc, rc);
    374376    }
    375377
     
    383385        int rc = TMVirtualResume(pVM);
    384386        AssertRCReturn(rc, rc);
     387        rc = TMCpuTickResume(pVM);
     388        AssertRCReturn(rc, rc);
    385389    }
    386390
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r1006 r1057  
    429429            STAM_COUNTER_INC(&pVM->vmm.s.StatRunGC);
    430430            register int rc;
    431             TMCpuTickResume(pVM);
    432431            pVM->vmm.s.iLastGCRc = rc = pVM->vmm.s.pfnR0HostToGuest(pVM);
    433             TMCpuTickPause(pVM);
    434432
    435433#ifdef VBOX_WITH_STATISTICS
     
    511509
    512510            STAM_COUNTER_INC(&pVM->vmm.s.StatRunGC);
    513             TMCpuTickResume(pVM);
    514511            rc = HWACCMR0Enable(pVM);
    515512            if (VBOX_SUCCESS(rc))
     
    525522                AssertRC(rc2);
    526523            }
    527             TMCpuTickPause(pVM);
    528524            pVM->vmm.s.iLastGCRc = rc;
    529525
  • trunk/src/recompiler/VBoxRecompiler.c

    r858 r1057  
    719719         */
    720720        pVM->rem.s.Env.interrupt_request = CPU_INTERRUPT_SINGLE_INSTR;
    721         TMCpuTickResume(pVM);
    722721        rc = cpu_exec(&pVM->rem.s.Env);
    723         TMCpuTickPause(pVM);
    724722        switch (rc)
    725723        {
     
    826824        do
    827825        {
    828             TMCpuTickResume(pVM);
    829826            rc = cpu_exec(&pVM->rem.s.Env);
    830             TMCpuTickPause(pVM);
    831 
    832827        } while (   eip == pVM->rem.s.Env.eip
    833828                 && (rc == EXCP_DEBUG || rc == EXCP_EXECUTE_RAW)
     
    949944
    950945
    951     TMCpuTickResume(pVM);
    952946    int rc = cpu_exec(&pVM->rem.s.Env);
    953     TMCpuTickPause(pVM);
    954947    switch (rc)
    955948    {
  • trunk/src/recompiler/new/VBoxRecompiler.c

    r1001 r1057  
    735735         */
    736736        pVM->rem.s.Env.interrupt_request = CPU_INTERRUPT_SINGLE_INSTR;
    737         TMCpuTickResume(pVM);
    738737        rc = cpu_exec(&pVM->rem.s.Env);
    739         TMCpuTickPause(pVM);
    740738        switch (rc)
    741739        {
     
    850848        do
    851849        {
    852             TMCpuTickResume(pVM);
    853850            rc = cpu_exec(&pVM->rem.s.Env);
    854             TMCpuTickPause(pVM);
    855851
    856852        } while (   eip == pVM->rem.s.Env.eip
     
    981977
    982978
    983     TMCpuTickResume(pVM);
    984979    int rc = cpu_exec(&pVM->rem.s.Env);
    985     TMCpuTickPause(pVM);
    986980    switch (rc)
    987981    {
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