VirtualBox

Changeset 22242 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Aug 13, 2009 3:38:35 PM (15 years ago)
Author:
vboxsync
Message:

Made TSC underflow checking more generic.

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

Legend:

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

    r22241 r22242  
    508508        HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatTSCIntercept,           "/HWACCM/CPU%d/TSC/Intercept");
    509509        HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatTSCInterceptOverFlow,   "/HWACCM/CPU%d/TSC/InterceptOverflow");
    510         HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatTSCOverFlow,            "/HWACCM/CPU%d/TSC/Overflow");
    511510       
    512511        HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatDRxArmed,               "/HWACCM/CPU%d/Debug/Armed");
  • trunk/src/VBox/VMM/HWACCMInternal.h

    r22241 r22242  
    557557    RTUINT                      uCurrentASID;
    558558
    559     /* Last seen TSC by the guest when in offsetted mode. */
    560     uint64_t                    u64LastTSC;
    561559    /* Last use TSC offset value. (cached) */
    562560    uint64_t                    u64TSCOffset;
     
    819817    STAMCOUNTER             StatTSCOffset;
    820818    STAMCOUNTER             StatTSCIntercept;
    821     STAMCOUNTER             StatTSCOverFlow;
    822819    STAMCOUNTER             StatTSCInterceptOverFlow;
    823820
  • trunk/src/VBox/VMM/TM.cpp

    r21606 r22242  
    623623    STAM_REG(pVM, &pVM->tm.s.StatTSCWarp,                             STAMTYPE_COUNTER, "/TM/TSC/Intercept/Warp",              STAMUNIT_OCCURENCES, "Warpdrive is active.");
    624624    STAM_REG(pVM, &pVM->tm.s.StatTSCSet,                              STAMTYPE_COUNTER, "/TM/TSC/Sets",                        STAMUNIT_OCCURENCES, "Calls to TMCpuTickSet.");
     625    STAM_REG(pVM, &pVM->tm.s.StatTSCUnderflow,                        STAMTYPE_COUNTER, "/TM/TSC/Underflow",                   STAMUNIT_OCCURENCES, "TSC underflow; corrected with last seen value .");
    625626#endif /* VBOX_WITH_STATISTICS */
    626627
  • trunk/src/VBox/VMM/TMInternal.h

    r20784 r22242  
    546546    STAMCOUNTER                 StatTSCCatchupOther;
    547547    STAMCOUNTER                 StatTSCWarp;
     548    STAMCOUNTER                 StatTSCUnderflow;
    548549    STAMCOUNTER                 StatTSCSyncNotTicking;
    549550    /** @} */
     
    573574    uint64_t                    u64TSC;
    574575
     576    /** The last seen TSC by the guest. */
     577    uint64_t                    u64TSCLastSeen;
    575578} TMCPU;
    576579/** Pointer to TM VMCPU instance data. */
  • trunk/src/VBox/VMM/VMMAll/TMAllCpu.cpp

    r20689 r22242  
    210210        else
    211211            u64 = ASMReadTSC();
     212
     213        /* Never return a value lower than what the guest has already seen. */
     214        if (u64 < pVCpu->tm.s.u64TSCLastSeen)
     215        {
     216            STAM_COUNTER_INC(&pVM->tm.s.StatTSCUnderflow);
     217            pVCpu->tm.s.u64TSCLastSeen += 64;   /* @todo choose a good increment here */
     218            u64 = pVCpu->tm.s.u64TSCLastSeen;
     219        }
    212220    }
    213221    else
     
    271279}
    272280
     281/**
     282 * Sets the last seen CPU timestamp counter.
     283 *
     284 * @returns VBox status code.
     285 * @param   pVCpu               The virtual CPU to operate on.
     286 * @param   u64LastSeenTick     The last seen timestamp value.
     287 *
     288 * @thread  EMT which TSC is to be set.
     289 */
     290VMMDECL(int) TMCpuTickSetLastSeen(PVMCPU pVCpu, uint64_t u64LastSeenTick)
     291{
     292    VMCPU_ASSERT_EMT(pVCpu);
     293
     294    Assert(pVCpu->tm.s.u64TSCLastSeen < u64LastSeenTick);
     295    pVCpu->tm.s.u64TSCLastSeen = u64LastSeenTick;
     296    return VINF_SUCCESS;
     297}
     298
     299/**
     300 * Gets the last seen CPU timestamp counter.
     301 *
     302 * @returns last seen TSC
     303 * @param   pVCpu               The virtual CPU to operate on.
     304 *
     305 * @thread  EMT which TSC is to be set.
     306 */
     307VMMDECL(uint64_t) TMCpuTickGetLastSeen(PVMCPU pVCpu)
     308{
     309    VMCPU_ASSERT_EMT(pVCpu);
     310
     311    return pVCpu->tm.s.u64TSCLastSeen;
     312}
     313
    273314
    274315/**
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r22241 r22242  
    18031803    AssertRC(rc);
    18041804
    1805     /* TSC offset. */
    1806     uint64_t u64TSCOffset;
    1807 
    1808     if (TMCpuTickCanUseRealTSC(pVCpu, &u64TSCOffset))
     1805    if (TMCpuTickCanUseRealTSC(pVCpu, &pVCpu->hwaccm.s.u64TSCOffset))
    18091806    {
    18101807        uint64_t u64CurTSC = ASMReadTSC();
    1811         pVCpu->hwaccm.s.u64TSCOffset = u64TSCOffset;
    1812         if (u64CurTSC + u64TSCOffset >= pVCpu->hwaccm.s.u64LastTSC)
     1808        if (u64CurTSC + pVCpu->hwaccm.s.u64TSCOffset >= TMCpuTickGetLastSeen(pVCpu))
    18131809        {
    18141810            /* Note: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT takes precedence over TSC_OFFSET */
    1815             rc = VMXWriteVMCS64(VMX_VMCS_CTRL_TSC_OFFSET_FULL, u64TSCOffset);
     1811            rc = VMXWriteVMCS64(VMX_VMCS_CTRL_TSC_OFFSET_FULL, pVCpu->hwaccm.s.u64TSCOffset);
    18161812            AssertRC(rc);
    18171813
     
    18241820        {
    18251821            /* Fall back to rdtsc emulation as we would otherwise pass decreasing tsc values to the guest. */
    1826             Log(("TSC %RX64 offset %RX64 time=%RX64 last=%RX64 (diff=%RX64, virt_tsc=%RX64)\n", u64CurTSC, u64TSCOffset, u64CurTSC + u64TSCOffset, pVCpu->hwaccm.s.u64LastTSC, pVCpu->hwaccm.s.u64LastTSC - u64CurTSC - u64TSCOffset, TMCpuTickGet(pVCpu)));
     1822            Log(("TSC %RX64 offset %RX64 time=%RX64 last=%RX64 (diff=%RX64, virt_tsc=%RX64)\n", u64CurTSC, pVCpu->hwaccm.s.u64TSCOffset, u64CurTSC + pVCpu->hwaccm.s.u64TSCOffset, TMCpuTickGetLastSeen(pVCpu), TMCpuTickGetLastSeen(pVCpu) - u64CurTSC - pVCpu->hwaccm.s.u64TSCOffset, TMCpuTickGet(pVCpu)));
    18271823            pVCpu->hwaccm.s.vmx.proc_ctls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
    18281824            rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVCpu->hwaccm.s.vmx.proc_ctls);
     
    25962592    /* Possibly the last TSC value seen by the guest (too high) (only when we're in tsc offset mode). */
    25972593    if (!(pVCpu->hwaccm.s.vmx.proc_ctls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT))
    2598         pVCpu->hwaccm.s.u64LastTSC = ASMReadTSC() + pVCpu->hwaccm.s.u64TSCOffset - 0x1000 /* guestimate of world switch overhead */;
     2594        TMCpuTickSetLastSeen(pVCpu, ASMReadTSC() + pVCpu->hwaccm.s.u64TSCOffset - 0x1000 /* guestimate of world switch overhead in clock ticks */);
    25992595
    26002596    TMNotifyEndOfExecution(pVCpu);
     
    33993395        if (rc == VINF_SUCCESS)
    34003396        {
    3401             uint64_t u64CurrentTSC = (uint64_t)pCtx->edx << 32ULL;
    3402             u64CurrentTSC += pCtx->eax;
    3403 
    3404             if (u64CurrentTSC < pVCpu->hwaccm.s.u64LastTSC)
    3405             {
    3406                 STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatTSCOverFlow);
    3407                 Log(("invalid tsc %RX64 vs %RX64 (diff %RX64)\n", u64CurrentTSC, pVCpu->hwaccm.s.u64LastTSC, pVCpu->hwaccm.s.u64LastTSC - u64CurrentTSC));
    3408                 pVCpu->hwaccm.s.u64LastTSC += 64;
    3409                 pCtx->edx = (pVCpu->hwaccm.s.u64LastTSC >> 32ULL);
    3410                 pCtx->eax = (pVCpu->hwaccm.s.u64LastTSC & 0xffffffff);
    3411             }
    3412 
    34133397            /* Update EIP and continue execution. */
    34143398            Assert(cbInstr == 2);
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