- Timestamp:
- Oct 17, 2014 2:18:50 PM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 96606
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r53035 r53087 1769 1769 /** Failed to measure the TSC delta between two CPUs. */ 1770 1770 #define VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED (-3743) 1771 /** Failed to calculate the TSC frequency. */ 1772 #define VERR_SUPDRV_TSC_FREQ_MEASUREMENT_FAILED (-3744) 1771 1773 /** @} */ 1772 1774 -
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r53085 r53087 5908 5908 5909 5909 /** 5910 * Measures the nominal TSC frequency. 5911 * 5912 * Uses a busy-wait method for the async. case as it is intended to help push 5913 * the CPU frequency up, while for the invariant cases using a sleeping method. 5914 * 5915 * @returns VBox status code. 5916 * @param pGip Pointer to the GIP. 5917 * 5918 * @remarks Must be called only after measuring the TSC deltas. 5919 */ 5920 static int supdrvGipMeasureNominalTscFreq(PSUPGLOBALINFOPAGE pGip) 5921 { 5922 int cTriesLeft = 4; 5923 AssertReturn(pGip, VERR_INVALID_PARAMETER); 5924 AssertReturn(pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC, VERR_WRONG_ORDER); 5925 5926 while (cTriesLeft-- > 0) 5927 { 5928 RTCCUINTREG uFlags; 5929 uint64_t u64NanoTS; 5930 uint64_t u64Before; 5931 uint64_t u64After; 5932 uint8_t idApicBefore; 5933 uint8_t idApicAfter; 5934 PSUPGIPCPU pGipCpuBefore; 5935 PSUPGIPCPU pGipCpuAfter; 5936 uint16_t iCpuBefore; 5937 uint16_t iCpuAfter; 5938 5939 uFlags = ASMIntDisableFlags(); 5940 idApicBefore = ASMGetApicId(); 5941 ASMSerializeInstruction(); 5942 u64Before = ASMReadTSC(); 5943 ASMSetFlags(uFlags); 5944 u64NanoTS = RTTimeSystemNanoTS(); 5945 5946 /** @todo change this to non-busy wait for invariant case. */ 5947 while (RTTimeSystemNanoTS() < RT_NS_10MS + u64NanoTS) 5948 ; 5949 5950 uFlags = ASMIntDisableFlags(); 5951 u64After = ASMReadTSC(); 5952 idApicAfter = ASMGetApicId(); 5953 ASMSetFlags(uFlags); 5954 5955 iCpuBefore = pGip->aiCpuFromApicId[idApicBefore]; 5956 iCpuAfter = pGip->aiCpuFromApicId[idApicAfter]; 5957 AssertMsg(iCpuBefore < pGip->cCpus, ("iCpuBefore=%u cCpus=%u\n", iCpuBefore, pGip->cCpus)); 5958 AssertMsg(iCpuAfter < pGip->cCpus, ("iCpuAfter=%u cCpus=%u\n", iCpuAfter, pGip->cCpus)); 5959 pGipCpuBefore = &pGip->aCPUs[iCpuBefore]; 5960 pGipCpuAfter = &pGip->aCPUs[iCpuAfter]; 5961 5962 /** @todo replace with enum check. */ 5963 if (supdrvIsInvariantTsc()) 5964 { 5965 if ( pGipCpuBefore->i64TSCDelta != INT64_MAX 5966 && pGipCpuAfter->i64TSCDelta != INT64_MAX) 5967 { 5968 u64Before += pGipCpuBefore->i64TSCDelta; 5969 u64After += pGipCpuAfter->i64TSCDelta; 5970 5971 SUPR0Printf("vboxdrv: TSC frequency is (%'RU64) Hz, kernel timer granularity is (%RU32) Ns\n", 5972 (u64After - u64Before) * 100, RTTimerGetSystemGranularity()); 5973 return VINF_SUCCESS; 5974 } 5975 else 5976 { 5977 SUPR0Printf("vboxdrv: supdrvGipMeasureNominalTscFreq: iCpuBefore=%u iCpuAfter=%u cTriesLeft=%u\n", iCpuBefore, 5978 iCpuAfter, cTriesLeft); 5979 } 5980 } 5981 else 5982 { 5983 SUPR0Printf("vboxdrv: TSC frequency is (%'RU64) Hz, kernel timer granularity is (%RU32) Ns\n", 5984 (u64After - u64Before) * 100, RTTimerGetSystemGranularity()); 5985 return VINF_SUCCESS; 5986 } 5987 } 5988 5989 return VERR_SUPDRV_TSC_FREQ_MEASUREMENT_FAILED; 5990 } 5991 5992 5993 /** 5910 5994 * Creates the GIP. 5911 5995 * … … 5995 6079 for (iCpu = 0; iCpu < pGip->cCpus; iCpu++) 5996 6080 Log(("supdrvTscDeltaInit: cpu[%u] delta %lld\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta)); 6081 #endif 6082 6083 #if 0 6084 /** @todo refactor later and use the nominal TSC rate for invariant case as 6085 * the real and constant TSC rate. */ 6086 supdrvGipMeasureNominalTscFreq(pGip); 5997 6087 #endif 5998 6088 … … 6130 6220 * affected a bit until we get proper TSC deltas than implementing options like 6131 6221 * rescheduling the tick to be delivered on the right CPU or missing the tick entirely. 6222 * 6223 * The likely hood of this happening is really low. On Windows, Linux timers 6224 * fire on the CPU they were registered/started on. Darwin, Solaris need verification. 6132 6225 */ 6133 6226 if (pGipCpu->i64TSCDelta != INT64_MAX) … … 6264 6357 * update the state and it'll get serviced when the thread's listening interval times out. 6265 6358 */ 6266 RTCpuSetAdd(&pDevExt->TscDeltaCpuSet, idCpu); 6267 RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock); 6268 if ( pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Listening 6269 || pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Measuring) 6270 { 6271 pDevExt->enmTscDeltaState = kSupDrvTscDeltaState_WaitAndMeasure; 6272 } 6273 RTSpinlockRelease(pDevExt->hTscDeltaSpinlock); 6359 if (supdrvIsInvariantTsc()) 6360 { 6361 RTCpuSetAdd(&pDevExt->TscDeltaCpuSet, idCpu); 6362 RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock); 6363 if ( pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Listening 6364 || pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Measuring) 6365 { 6366 pDevExt->enmTscDeltaState = kSupDrvTscDeltaState_WaitAndMeasure; 6367 } 6368 RTSpinlockRelease(pDevExt->hTscDeltaSpinlock); 6369 } 6274 6370 #endif 6275 6371 … … 7456 7552 #endif 7457 7553 7458 while ( !cTries--)7554 while (cTries--) 7459 7555 { 7460 7556 rc = supdrvMeasureTscDeltaOne(pDevExt, iCpu);
Note:
See TracChangeset
for help on using the changeset viewer.