VirtualBox

Changeset 19032 in vbox for trunk/src/VBox/VMM/TM.cpp


Ignore:
Timestamp:
Apr 20, 2009 3:03:08 PM (16 years ago)
Author:
vboxsync
Message:

Split TM for SMP guests.

File:
1 edited

Legend:

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

    r15844 r19032  
    9191 * Each clock has its own scheduling facility, or timer queue if you like.
    9292 * There are a few factors which makes it a bit complex.  First, there is the
    93  * usual R0 vs R3 vs. RC thing.  Then there is multiple threads, and then there
     93 * usual R0 vs R3 vs. RC thing.  Then there are multiple threads, and then there
    9494 * is the timer thread that periodically checks whether any timers has expired
    9595 * without EMT noticing.  On the API level, all but the create and save APIs
     
    9898 * The design is using a doubly linked list of active timers which is ordered
    9999 * by expire date.  This list is only modified by the EMT thread.  Updates to
    100  * the list are batched in a singly linked list, which is then process by the
     100 * the list are batched in a singly linked list, which is then processed by the
    101101 * EMT thread at the first opportunity (immediately, next time EMT modifies a
    102102 * timer on that clock, or next timer timeout).  Both lists are offset based and
     
    310310    {
    311311        if (!pVM->tm.s.fTSCUseRealTSC)
    312             pVM->tm.s.fMaybeUseOffsettedHostTSC = tmR3HasFixedTSC(pVM);
     312        {
     313            /* @todo simple case for guest SMP; always emulate RDTSC */
     314            if (pVM->cCPUs == 1)
     315                pVM->tm.s.fMaybeUseOffsettedHostTSC = tmR3HasFixedTSC(pVM);
     316        }
    313317        else
    314318            pVM->tm.s.fMaybeUseOffsettedHostTSC = true;
     
    346350    /** @cfgm{TM/TSCTiedToExecution, bool, false}
    347351     * Whether the TSC should be tied to execution. This will exclude most of the
    348      * virtualization overhead, but will by default include the time spend in the
     352     * virtualization overhead, but will by default include the time spent in the
    349353     * halt state (see TM/TSCNotTiedToHalt). This setting will override all other
    350354     * TSC settings except for TSCTicksPerSecond and TSCNotTiedToHalt, which should
     
    984988static DECLCALLBACK(int) tmR3Save(PVM pVM, PSSMHANDLE pSSM)
    985989{
     990    unsigned i;
     991
    986992    LogFlow(("tmR3Save:\n"));
    987     Assert(!pVM->tm.s.fTSCTicking);
     993#ifdef VBOX_STRICT
     994    for (i=0;i<pVM->cCPUs;i++)
     995    {
     996        PVMCPU pVCpu = &pVM->aCpus[i];
     997        Assert(!pVCpu->tm.s.fTSCTicking);
     998    }
    988999    Assert(!pVM->tm.s.fVirtualTicking);
    9891000    Assert(!pVM->tm.s.fVirtualSyncTicking);
     1001#endif
    9901002
    9911003    /*
     
    10061018    SSMR3PutU64(pSSM, TMCLOCK_FREQ_REAL);
    10071019
    1008     /* the cpu tick clock. */
    1009     SSMR3PutU64(pSSM, TMCpuTickGet(pVM));
     1020    for (i=0;i<pVM->cCPUs;i++)
     1021    {
     1022        PVMCPU pVCpu = &pVM->aCpus[i];
     1023
     1024        /* the cpu tick clock. */
     1025        SSMR3PutU64(pSSM, TMCpuTickGet(pVCpu));
     1026    }
    10101027    return SSMR3PutU64(pSSM, pVM->tm.s.cTSCTicksPerSecond);
    10111028}
     
    10221039static DECLCALLBACK(int) tmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
    10231040{
     1041    unsigned i;
    10241042    LogFlow(("tmR3Load:\n"));
    1025     Assert(!pVM->tm.s.fTSCTicking);
     1043
     1044#ifdef VBOX_STRICT
     1045    for (i=0;i<pVM->cCPUs;i++)
     1046    {
     1047        PVMCPU pVCpu = &pVM->aCpus[i];
     1048        Assert(!pVCpu->tm.s.fTSCTicking);
     1049    }
    10261050    Assert(!pVM->tm.s.fVirtualTicking);
    10271051    Assert(!pVM->tm.s.fVirtualSyncTicking);
     1052#endif
    10281053
    10291054    /*
     
    10811106
    10821107    /* the cpu tick clock. */
    1083     pVM->tm.s.fTSCTicking = false;
    1084     SSMR3GetU64(pSSM, &pVM->tm.s.u64TSC);
     1108    for (i=0;i<pVM->cCPUs;i++)
     1109    {
     1110        PVMCPU pVCpu = &pVM->aCpus[i];
     1111
     1112        pVCpu->tm.s.fTSCTicking = false;
     1113        SSMR3GetU64(pSSM, &pVCpu->tm.s.u64TSC);
     1114
     1115        if (pVM->tm.s.fTSCUseRealTSC)
     1116            pVCpu->tm.s.u64TSCOffset = 0; /** @todo TSC restore stuff and HWACC. */
     1117    }
     1118
    10851119    rc = SSMR3GetU64(pSSM, &u64Hz);
    10861120    if (RT_FAILURE(rc))
    10871121        return rc;
    1088     if (pVM->tm.s.fTSCUseRealTSC)
    1089         pVM->tm.s.u64TSCOffset = 0; /** @todo TSC restore stuff and HWACC. */
    1090     else
     1122    if (!pVM->tm.s.fTSCUseRealTSC)
    10911123        pVM->tm.s.cTSCTicksPerSecond = u64Hz;
     1124
    10921125    LogRel(("TM: cTSCTicksPerSecond=%#RX64 (%RU64) fTSCVirtualized=%RTbool fTSCUseRealTSC=%RTbool (state load)\n",
    10931126            pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.cTSCTicksPerSecond, pVM->tm.s.fTSCVirtualized, pVM->tm.s.fTSCUseRealTSC));
     
    13601393        case TMCLOCK_VIRTUAL_SYNC:  return TMVirtualSyncGet(pVM);
    13611394        case TMCLOCK_REAL:          return TMRealGet(pVM);
    1362         case TMCLOCK_TSC:           return TMCpuTickGet(pVM);
     1395        case TMCLOCK_TSC:           return TMCpuTickGet(&pVM->aCpus[0] /* just take VCPU 0 */);
    13631396        default:
    13641397            AssertMsgFailed(("enmClock=%d\n", enmClock));
     
    20832116     * Read the times first to avoid more than necessary time variation.
    20842117     */
    2085     const uint64_t u64TSC = TMCpuTickGet(pVM);
    20862118    const uint64_t u64Virtual = TMVirtualGet(pVM);
    20872119    const uint64_t u64VirtualSync = TMVirtualSyncGet(pVM);
    20882120    const uint64_t u64Real = TMRealGet(pVM);
    20892121
    2090     /*
    2091      * TSC
    2092      */
    2093     pHlp->pfnPrintf(pHlp,
    2094                     "Cpu Tick: %18RU64 (%#016RX64) %RU64Hz %s%s",
    2095                     u64TSC, u64TSC, TMCpuTicksPerSecond(pVM),
    2096                     pVM->tm.s.fTSCTicking ? "ticking" : "paused",
    2097                     pVM->tm.s.fTSCVirtualized ? " - virtualized" : "");
    2098     if (pVM->tm.s.fTSCUseRealTSC)
    2099     {
    2100         pHlp->pfnPrintf(pHlp, " - real tsc");
    2101         if (pVM->tm.s.u64TSCOffset)
    2102             pHlp->pfnPrintf(pHlp, "\n          offset %RU64", pVM->tm.s.u64TSCOffset);
    2103     }
    2104     else
    2105         pHlp->pfnPrintf(pHlp, " - virtual clock");
    2106     pHlp->pfnPrintf(pHlp, "\n");
     2122    for (unsigned i=0;i<pVM->cCPUs;i++)
     2123    {
     2124        PVMCPU pVCpu = &pVM->aCpus[i];
     2125
     2126        uint64_t u64TSC = TMCpuTickGet(pVCpu);
     2127        /*
     2128         * TSC
     2129         */
     2130        pHlp->pfnPrintf(pHlp,
     2131                        "Cpu Tick: %18RU64 (%#016RX64) %RU64Hz %s%s",
     2132                        u64TSC, u64TSC, TMCpuTicksPerSecond(pVM),
     2133                        pVCpu->tm.s.fTSCTicking ? "ticking" : "paused",
     2134                        pVM->tm.s.fTSCVirtualized ? " - virtualized" : "");
     2135        if (pVM->tm.s.fTSCUseRealTSC)
     2136        {
     2137            pHlp->pfnPrintf(pHlp, " - real tsc");
     2138            if (pVCpu->tm.s.u64TSCOffset)
     2139                pHlp->pfnPrintf(pHlp, "\n          offset %RU64", pVCpu->tm.s.u64TSCOffset);
     2140        }
     2141        else
     2142            pHlp->pfnPrintf(pHlp, " - virtual clock");
     2143        pHlp->pfnPrintf(pHlp, "\n");
     2144    }
    21072145
    21082146    /*
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