Changeset 45102 in vbox for trunk/src/VBox
- Timestamp:
- Mar 20, 2013 10:46:51 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 84392
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
r45092 r45102 1743 1743 1744 1744 /** 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 */ 1755 VMMR0DECL(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 /** 1745 1816 * Loads the guest state. 1746 1817 * … … 2344 2415 #endif /* VBOX_WITH_AUTO_MSR_LOAD_RESTORE */ 2345 2416 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 else2364 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 else2381 {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 else2394 {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 #endif2401 2402 2417 /* Done with the major changes */ 2403 2418 pVCpu->hm.s.fContextUseFlags &= ~HM_CHANGED_ALL_GUEST; … … 2894 2909 RTGCUINTPTR errCode, instrInfo; 2895 2910 bool fSetupTPRCaching = false; 2911 bool fNeedTscSetup = true; 2896 2912 uint64_t u64OldLSTAR = 0; 2897 2913 uint8_t u8LastTPR = 0; … … 3253 3269 VMXR0LoadMinimalGuestState(pVM, pVCpu, pCtx); 3254 3270 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadMinimal); 3271 if (fNeedTscSetup) 3272 { 3273 VMXR0SetupTscOffsetAndPreemption(pVM, pVCpu); 3274 fNeedTscSetup = false; 3275 } 3255 3276 } 3256 3277 else … … 3263 3284 } 3264 3285 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 } 3322 3288 3323 3289 #ifndef VBOX_WITH_VMMR0_DISABLE_PREEMPTION … … 4346 4312 Assert(cbInstr == 2); 4347 4313 pCtx->rip += cbInstr; 4314 fNeedTscSetup = true; /* See @bugref{6634}. */ 4348 4315 goto ResumeExecution; 4349 4316 } … … 4362 4329 Assert(cbInstr == 3); 4363 4330 pCtx->rip += cbInstr; 4331 fNeedTscSetup = true; /* See @bugref{6634}. */ 4364 4332 goto ResumeExecution; 4365 4333 }
Note:
See TracChangeset
for help on using the changeset viewer.