VirtualBox

Changeset 45102 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 20, 2013 10:46:51 AM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
84392
Message:

VMX: Redo TSC offsetting setup if unexpected RDTSC(P) occurred.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r45092 r45102  
    17431743
    17441744/**
     1745 * Sets up TSC offsetting and VMX preemption, if supported/configured/available.
     1746 *
     1747 * NOTE: This function reads the host TSC value. Therefore it must be executed very
     1748 * shortly before a VM entry and execution MUST NOT be rescheduled between a call to
     1749 * this function and a VM entry without calling this function again.
     1750 *
     1751 * @returns VBox status code.
     1752 * @param   pVM         Pointer to the VM.
     1753 * @param   pVCpu       Pointer to the VMCPU.
     1754 */
     1755VMMR0DECL(int) VMXR0SetupTscOffsetAndPreemption(PVM pVM, PVMCPU pVCpu)
     1756{
     1757    int     rc = VINF_SUCCESS;
     1758    bool    fOffsettedTsc;
     1759
     1760    if (pVM->hm.s.vmx.fUsePreemptTimer)
     1761    {
     1762        uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVCpu, &fOffsettedTsc, &pVCpu->hm.s.vmx.u64TSCOffset);
     1763
     1764        /* Make sure the returned values have sane upper and lower boundaries. */
     1765        uint64_t u64CpuHz = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
     1766
     1767        cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64);   /* 1/64 of a second */
     1768        cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
     1769
     1770        cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
     1771        uint32_t cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
     1772        rc = VMXWriteVmcs(VMX_VMCS32_GUEST_PREEMPTION_TIMER_VALUE, cPreemptionTickCount);
     1773        AssertRC(rc);
     1774    }
     1775    else
     1776        fOffsettedTsc = TMCpuTickCanUseRealTSC(pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset);
     1777
     1778    if (fOffsettedTsc)
     1779    {
     1780        uint64_t u64CurTSC = ASMReadTSC();
     1781        if (u64CurTSC + pVCpu->hm.s.vmx.u64TSCOffset > TMCpuTickGetLastSeen(pVCpu))
     1782        {
     1783            /* Note: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT takes precedence over TSC_OFFSET, applies to RDTSCP too. */
     1784            rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, pVCpu->hm.s.vmx.u64TSCOffset);
     1785            AssertRC(rc);
     1786
     1787            pVCpu->hm.s.vmx.u32ProcCtls &= ~VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
     1788            rc = VMXWriteVmcs(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
     1789            AssertRC(rc);
     1790            STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
     1791        }
     1792        else
     1793        {
     1794            /* Fall back to rdtsc, rdtscp emulation as we would otherwise pass decreasing tsc values to the guest. */
     1795            LogFlow(("TSC %RX64 offset %RX64 time=%RX64 last=%RX64 (diff=%RX64, virt_tsc=%RX64)\n", u64CurTSC,
     1796                     pVCpu->hm.s.vmx.u64TSCOffset, u64CurTSC + pVCpu->hm.s.vmx.u64TSCOffset,
     1797                     TMCpuTickGetLastSeen(pVCpu), TMCpuTickGetLastSeen(pVCpu) - u64CurTSC - pVCpu->hm.s.vmx.u64TSCOffset,
     1798                     TMCpuTickGet(pVCpu)));
     1799            pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
     1800            rc = VMXWriteVmcs(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
     1801            AssertRC(rc);
     1802            STAM_COUNTER_INC(&pVCpu->hm.s.StatTscInterceptOverFlow);
     1803        }
     1804    }
     1805    else
     1806    {
     1807        pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
     1808        rc = VMXWriteVmcs(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
     1809        AssertRC(rc);
     1810        STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
     1811    }
     1812    return rc;
     1813}
     1814
     1815/**
    17451816 * Loads the guest state.
    17461817 *
     
    23442415#endif /* VBOX_WITH_AUTO_MSR_LOAD_RESTORE */
    23452416
    2346 #if 0 /* Temp move for testing. */
    2347     bool fOffsettedTsc;
    2348     if (pVM->hm.s.vmx.fUsePreemptTimer)
    2349     {
    2350         uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVCpu, &fOffsettedTsc, &pVCpu->hm.s.vmx.u64TSCOffset);
    2351 
    2352         /* Make sure the returned values have sane upper and lower boundaries. */
    2353         uint64_t u64CpuHz = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
    2354 
    2355         cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64);   /* 1/64 of a second */
    2356         cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
    2357 
    2358         cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
    2359         uint32_t cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
    2360         rc = VMXWriteVmcs(VMX_VMCS32_GUEST_PREEMPTION_TIMER_VALUE, cPreemptionTickCount);
    2361         AssertRC(rc);
    2362     }
    2363     else
    2364         fOffsettedTsc = TMCpuTickCanUseRealTSC(pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset);
    2365 
    2366     if (fOffsettedTsc)
    2367     {
    2368         uint64_t u64CurTSC = ASMReadTSC();
    2369         if (u64CurTSC + pVCpu->hm.s.vmx.u64TSCOffset > TMCpuTickGetLastSeen(pVCpu))
    2370         {
    2371             /* Note: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT takes precedence over TSC_OFFSET, applies to RDTSCP too. */
    2372             rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, pVCpu->hm.s.vmx.u64TSCOffset);
    2373             AssertRC(rc);
    2374 
    2375             pVCpu->hm.s.vmx.u32ProcCtls &= ~VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
    2376             rc = VMXWriteVmcs(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
    2377             AssertRC(rc);
    2378             STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
    2379         }
    2380         else
    2381         {
    2382             /* Fall back to rdtsc, rdtscp emulation as we would otherwise pass decreasing tsc values to the guest. */
    2383             LogFlow(("TSC %RX64 offset %RX64 time=%RX64 last=%RX64 (diff=%RX64, virt_tsc=%RX64)\n", u64CurTSC,
    2384                      pVCpu->hm.s.vmx.u64TSCOffset, u64CurTSC + pVCpu->hm.s.vmx.u64TSCOffset,
    2385                      TMCpuTickGetLastSeen(pVCpu), TMCpuTickGetLastSeen(pVCpu) - u64CurTSC - pVCpu->hm.s.vmx.u64TSCOffset,
    2386                      TMCpuTickGet(pVCpu)));
    2387             pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
    2388             rc = VMXWriteVmcs(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
    2389             AssertRC(rc);
    2390             STAM_COUNTER_INC(&pVCpu->hm.s.StatTscInterceptOverFlow);
    2391         }
    2392     }
    2393     else
    2394     {
    2395         pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
    2396         rc = VMXWriteVmcs(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
    2397         AssertRC(rc);
    2398         STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
    2399     }
    2400 #endif
    2401 
    24022417    /* Done with the major changes */
    24032418    pVCpu->hm.s.fContextUseFlags &= ~HM_CHANGED_ALL_GUEST;
     
    28942909    RTGCUINTPTR errCode, instrInfo;
    28952910    bool        fSetupTPRCaching = false;
     2911    bool        fNeedTscSetup = true;
    28962912    uint64_t    u64OldLSTAR = 0;
    28972913    uint8_t     u8LastTPR = 0;
     
    32533269        VMXR0LoadMinimalGuestState(pVM, pVCpu, pCtx);
    32543270        STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadMinimal);
     3271        if (fNeedTscSetup)
     3272        {
     3273            VMXR0SetupTscOffsetAndPreemption(pVM, pVCpu);
     3274            fNeedTscSetup = false;
     3275        }
    32553276    }
    32563277    else
     
    32633284        }
    32643285        STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadFull);
    3265     }
    3266 
    3267 #if 1   /* Moved for testing. */
    3268     bool fOffsettedTsc;
    3269     if (pVM->hm.s.vmx.fUsePreemptTimer)
    3270     {
    3271         uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVCpu, &fOffsettedTsc, &pVCpu->hm.s.vmx.u64TSCOffset);
    3272 
    3273         /* Make sure the returned values have sane upper and lower boundaries. */
    3274         uint64_t u64CpuHz = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
    3275 
    3276         cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64);   /* 1/64 of a second */
    3277         cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
    3278 
    3279         cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
    3280         uint32_t cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
    3281         rc = VMXWriteVmcs(VMX_VMCS32_GUEST_PREEMPTION_TIMER_VALUE, cPreemptionTickCount);
    3282         AssertRC(VBOXSTRICTRC_VAL(rc));
    3283     }
    3284     else
    3285         fOffsettedTsc = TMCpuTickCanUseRealTSC(pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset);
    3286 
    3287     if (fOffsettedTsc)
    3288     {
    3289         uint64_t u64CurTSC = ASMReadTSC();
    3290         if (u64CurTSC + pVCpu->hm.s.vmx.u64TSCOffset > TMCpuTickGetLastSeen(pVCpu))
    3291         {
    3292             /* Note: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT takes precedence over TSC_OFFSET, applies to RDTSCP too. */
    3293             rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, pVCpu->hm.s.vmx.u64TSCOffset);
    3294             AssertRC(VBOXSTRICTRC_VAL(rc));
    3295 
    3296             pVCpu->hm.s.vmx.u32ProcCtls &= ~VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
    3297             rc = VMXWriteVmcs(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
    3298             AssertRC(VBOXSTRICTRC_VAL(rc));
    3299             STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
    3300         }
    3301         else
    3302         {
    3303             /* Fall back to rdtsc, rdtscp emulation as we would otherwise pass decreasing tsc values to the guest. */
    3304             LogFlow(("TSC %RX64 offset %RX64 time=%RX64 last=%RX64 (diff=%RX64, virt_tsc=%RX64)\n", u64CurTSC,
    3305                      pVCpu->hm.s.vmx.u64TSCOffset, u64CurTSC + pVCpu->hm.s.vmx.u64TSCOffset,
    3306                      TMCpuTickGetLastSeen(pVCpu), TMCpuTickGetLastSeen(pVCpu) - u64CurTSC - pVCpu->hm.s.vmx.u64TSCOffset,
    3307                      TMCpuTickGet(pVCpu)));
    3308             pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
    3309             rc = VMXWriteVmcs(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
    3310             AssertRC(VBOXSTRICTRC_VAL(rc));
    3311             STAM_COUNTER_INC(&pVCpu->hm.s.StatTscInterceptOverFlow);
    3312         }
    3313     }
    3314     else
    3315     {
    3316         pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
    3317         rc = VMXWriteVmcs(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
    3318         AssertRC(VBOXSTRICTRC_VAL(rc));
    3319         STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
    3320     }
    3321 #endif
     3286        VMXR0SetupTscOffsetAndPreemption(pVM, pVCpu);
     3287    }
    33223288
    33233289#ifndef VBOX_WITH_VMMR0_DISABLE_PREEMPTION
     
    43464312            Assert(cbInstr == 2);
    43474313            pCtx->rip += cbInstr;
     4314            fNeedTscSetup = true;   /* See @bugref{6634}. */
    43484315            goto ResumeExecution;
    43494316        }
     
    43624329            Assert(cbInstr == 3);
    43634330            pCtx->rip += cbInstr;
     4331            fNeedTscSetup = true;   /* See @bugref{6634}. */
    43644332            goto ResumeExecution;
    43654333        }
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette