- Timestamp:
- Oct 17, 2014 12:23:54 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r53064 r53085 162 162 static bool supdrvIsInvariantTsc(void); 163 163 static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, 164 uint64_t u64NanoTS, unsigned uUpdateHz, unsigned cCpus);164 uint64_t u64NanoTS, unsigned uUpdateHz, unsigned uUpdateIntervalNS, unsigned cCpus); 165 165 static DECLCALLBACK(void) supdrvGipInitOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2); 166 166 static void supdrvGipTerm(PSUPGLOBALINFOPAGE pGip); … … 5919 5919 uint32_t u32SystemResolution; 5920 5920 uint32_t u32Interval; 5921 uint32_t u32MinInterval; 5922 uint32_t uMod; 5921 5923 unsigned cCpus; 5922 5924 int rc; … … 5954 5956 /* 5955 5957 * Find a reasonable update interval and initialize the structure. 5956 */ 5957 u32Interval = u32SystemResolution = RTTimerGetSystemGranularity(); 5958 while (u32Interval < 10000000 /* 10 ms */) 5959 u32Interval += u32SystemResolution; 5960 5961 supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), 1000000000 / u32Interval /*=Hz*/, cCpus); 5958 * 5959 * If we have an invariant TSC, use a larger update interval as then 5960 * we get better accuracy along with lower host load. 5961 */ 5962 u32MinInterval = supdrvIsInvariantTsc() ? RT_NS_100MS : RT_NS_10MS; 5963 u32SystemResolution = RTTimerGetSystemGranularity(); 5964 u32Interval = u32MinInterval; 5965 uMod = u32MinInterval % u32SystemResolution; 5966 if (uMod) 5967 u32Interval += u32SystemResolution - uMod; 5968 5969 supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), RT_NS_1SEC / u32Interval /*=Hz*/, u32Interval, cCpus); 5962 5970 5963 5971 #ifdef SUPDRV_USE_TSC_DELTA_THREAD … … 6104 6112 { 6105 6113 RTCCUINTREG fOldFlags = ASMIntDisableFlags(); /* No interruptions please (real problem on S10). */ 6106 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser;6107 6114 uint64_t u64TSC = ASMReadTSC(); 6108 6115 uint64_t NanoTS = RTTimeSystemNanoTS(); 6116 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser; 6117 6118 if (supdrvIsInvariantTsc()) 6119 { 6120 PSUPGIPCPU pGipCpu; 6121 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 6122 unsigned iCpu = pGip->aiCpuFromApicId[ASMGetApicId()]; 6123 AssertReturnVoid(iCpu < pGip->cCpus); 6124 pGipCpu = &pGip->aCPUs[iCpu]; 6125 AssertReturnVoid(pGipCpu->idCpu == RTMpCpuId()); 6126 6127 /* 6128 * The calculations in supdrvGipUpdate() is very timing sensitive and doesn't handle 6129 * missed timer ticks. So for now it is better to use a delta of 0 and have the TSC rate 6130 * affected a bit until we get proper TSC deltas than implementing options like 6131 * rescheduling the tick to be delivered on the right CPU or missing the tick entirely. 6132 */ 6133 if (pGipCpu->i64TSCDelta != INT64_MAX) 6134 u64TSC += pGipCpu->i64TSCDelta; 6135 } 6109 6136 6110 6137 supdrvGipUpdate(pDevExt, NanoTS, u64TSC, NIL_RTCPUID, iTick); … … 6898 6925 static SUPGIPMODE supdrvGipDeterminTscMode(PSUPDRVDEVEXT pDevExt) 6899 6926 { 6927 if (supdrvIsInvariantTsc()) 6928 return SUPGIPMODE_SYNC_TSC; /** @todo Switch to SUPGIPMODE_INVARIANT_TSC later. */ 6929 6900 6930 /* 6901 6931 * On SMP we're faced with two problems: … … 6988 7018 * Initializes the GIP data. 6989 7019 * 6990 * @param pDevExt Pointer to the device instance data. 6991 * @param pGip Pointer to the read-write kernel mapping of the GIP. 6992 * @param HCPhys The physical address of the GIP. 6993 * @param u64NanoTS The current nanosecond timestamp. 6994 * @param uUpdateHz The update frequency. 6995 * @param cCpus The CPU count. 7020 * @param pDevExt Pointer to the device instance data. 7021 * @param pGip Pointer to the read-write kernel mapping of the GIP. 7022 * @param HCPhys The physical address of the GIP. 7023 * @param u64NanoTS The current nanosecond timestamp. 7024 * @param uUpdateHz The update frequency. 7025 * @param uUpdateIntervalNS The update interval in nanoseconds. 7026 * @param cCpus The CPU count. 6996 7027 */ 6997 7028 static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, 6998 uint64_t u64NanoTS, unsigned uUpdateHz, unsigned cCpus)7029 uint64_t u64NanoTS, unsigned uUpdateHz, unsigned uUpdateIntervalNS, unsigned cCpus) 6999 7030 { 7000 7031 size_t const cbGip = RT_ALIGN_Z(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]), PAGE_SIZE); … … 7016 7047 pGip->cPages = (uint16_t)(cbGip / PAGE_SIZE); 7017 7048 pGip->u32UpdateHz = uUpdateHz; 7018 pGip->u32UpdateIntervalNS = 1000000000 / uUpdateHz;7049 pGip->u32UpdateIntervalNS = uUpdateIntervalNS; 7019 7050 pGip->u64NanoTSLastUpdateHz = u64NanoTS; 7020 7051 RTCpuSetEmpty(&pGip->OnlineCpuSet); … … 7160 7191 7161 7192 /* 7193 * For invariant TSC support, we take only 1 interval as there is a problem on 7194 * Windows where we have an occasional (but reccurring) sour value that messes up 7195 * the history. Also, since the update interval is pretty long with the invariant 7196 * TSC case this works accurately enough. 7197 */ 7198 if (supdrvIsInvariantTsc()) 7199 { 7200 u32UpdateIntervalTSC = (uint32_t)u64TSCDelta; 7201 u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 6; 7202 } 7203 /* 7162 7204 * UpdateIntervalTSC = average of last 8,2,1 intervals depending on update HZ. 7163 7205 */ 7164 if (pGip->u32UpdateHz >= 1000)7206 else if (pGip->u32UpdateHz >= 1000) 7165 7207 { 7166 7208 uint32_t u32; … … 7202 7244 * CpuHz. 7203 7245 */ 7204 u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, pGip->u32UpdateHz); 7246 u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, RT_NS_1SEC_64); 7247 u64CpuHz /= pGip->u32UpdateIntervalNS; 7205 7248 ASMAtomicWriteU64(&pGipCpu->u64CpuHz, u64CpuHz); 7206 7249 } … … 7258 7301 #ifdef RT_ARCH_AMD64 /** @todo fix 64-bit div here to work on x86 linux. */ 7259 7302 uint64_t u64Delta = u64NanoTS - pGip->u64NanoTSLastUpdateHz; 7260 uint32_t u32UpdateHz = (uint32_t)(( UINT64_C(1000000000)* GIP_UPDATEHZ_RECALC_FREQ) / u64Delta);7303 uint32_t u32UpdateHz = (uint32_t)((RT_NS_1SEC_64 * GIP_UPDATEHZ_RECALC_FREQ) / u64Delta); 7261 7304 if (u32UpdateHz <= 2000 && u32UpdateHz >= 30) 7262 7305 { 7263 7306 ASMAtomicWriteU32(&pGip->u32UpdateHz, u32UpdateHz); 7264 ASMAtomicWriteU32(&pGip->u32UpdateIntervalNS, 1000000000/ u32UpdateHz);7307 ASMAtomicWriteU32(&pGip->u32UpdateIntervalNS, RT_NS_1SEC / u32UpdateHz); 7265 7308 } 7266 7309 #endif
Note:
See TracChangeset
for help on using the changeset viewer.