- Timestamp:
- Dec 5, 2014 2:52:21 PM (10 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r53459 r53464 138 138 139 139 /** Whether the application of TSC-deltas is required. */ 140 #define GIP_ARE_TSC_DELTAS_APPLICABLE(a_p Gip) ((a_pGip)->u32Mode == SUPGIPMODE_INVARIANT_TSC && !g_fOsTscDeltasInSync)140 #define GIP_ARE_TSC_DELTAS_APPLICABLE(a_pDevExt) ((a_pDevExt)->pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC && !((a_pDevExt)->fOsTscDeltasInSync)) 141 141 142 142 … … 176 176 static void supdrvGipUpdatePerCpu(PSUPDRVDEVEXT pDevExt, uint64_t u64NanoTS, uint64_t u64TSC, 177 177 RTCPUID idCpu, uint8_t idApic, uint64_t iTick); 178 static void supdrvGipInitCpu(PSUP GLOBALINFOPAGE pGip, PSUPGIPCPU pCpu, uint64_t u64NanoTS);178 static void supdrvGipInitCpu(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pCpu, uint64_t u64NanoTS); 179 179 static int supdrvMeasureTscDeltas(PSUPDRVDEVEXT pDevExt, uint32_t *pidxMaster); 180 180 static int supdrvMeasureTscDeltaOne(PSUPDRVDEVEXT pDevExt, uint32_t idxWorker); … … 187 187 DECLEXPORT(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage = NULL; 188 188 189 /** @name r=bird: Stuff that should be SUPDRVDEVEXT members.190 * @todo Move this ASAP. */191 /**192 * The TSC delta synchronization struct. rounded to cache line size.193 */194 typedef union SUPTSCDELTASYNC195 {196 /** The synchronization variable, holds values GIP_TSC_DELTA_SYNC_*. */197 volatile uint32_t u;198 /** Padding to cache line size. */199 uint8_t u8Padding[64];200 } SUPTSCDELTASYNC;201 AssertCompileSize(SUPTSCDELTASYNC, 64);202 typedef SUPTSCDELTASYNC *PSUPTSCDELTASYNC;203 204 /** Pointer to the TSC delta sync. struct. */205 static void *g_pvTscDeltaSync;206 /** Aligned pointer to the TSC delta sync. struct. */207 static PSUPTSCDELTASYNC g_pTscDeltaSync;208 /** The TSC delta measurement initiator Cpu Id. */209 static volatile RTCPUID g_idTscDeltaInitiator = NIL_RTCPUID;210 /** Number of online/offline events, incremented each time a CPU goes online211 * or offline. */212 static volatile uint32_t g_cMpOnOffEvents;213 /** TSC reading during start of TSC frequency refinement phase. */214 static uint64_t g_u64TscAnchor;215 /** Timestamp (in nanosec) during start of TSC frequency refinement phase. */216 static uint64_t g_u64NanoTSAnchor;217 /** Pointer to the timer used to refine the TSC frequency. */218 static PRTTIMER g_pTscRefineTimer;219 /** Whether the host OS has already normalized the hardware TSC deltas across220 * CPUs. */221 static bool g_fOsTscDeltasInSync;222 /** @} */223 189 224 190 /** … … 543 509 pDevExt->hGipSpinlock = NIL_RTSPINLOCK; 544 510 pDevExt->hSessionHashTabSpinlock = NIL_RTSPINLOCK; 511 pDevExt->idTscDeltaInitiator = NIL_RTCPUID; 545 512 rc = RTSpinlockCreate(&pDevExt->Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "SUPDrvDevExt"); 546 513 if (RT_SUCCESS(rc)) … … 5924 5891 static int supdrvTscDeltaThreadInit(PSUPDRVDEVEXT pDevExt) 5925 5892 { 5926 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt ->pGip));5893 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)); 5927 5894 5928 5895 int rc = RTSpinlockCreate(&pDevExt->hTscDeltaSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "VBoxTscSpnLck"); … … 6106 6073 ASMSetFlags(uFlags); 6107 6074 6108 if (GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip))6075 if (GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)) 6109 6076 { 6110 6077 int rc; … … 6155 6122 * 6156 6123 * @param pTimer The timer. 6157 * @param pvUser Opaque pointer to the GIP.6124 * @param pvUser Opaque pointer to the device instance data. 6158 6125 * @param iTick The timer tick. 6159 6126 */ 6160 6127 static DECLCALLBACK(void) supdrvRefineTscTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick) 6161 6128 { 6129 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser; 6130 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 6131 bool fDeltaApplied = false; 6162 6132 uint8_t idApic; 6163 6133 uint64_t u64DeltaNanoTS; … … 6166 6136 uint64_t u64Tsc; 6167 6137 RTCCUINTREG uFlags; 6168 bool fDeltaApplied = false;6169 PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)pvUser;6170 6138 6171 6139 /* Paranoia. */ … … 6184 6152 ASMSetFlags(uFlags); 6185 6153 SUPTscDeltaApply(pGip, &u64Tsc, idApic, &fDeltaApplied); 6186 u64DeltaNanoTS = u64NanoTS - g_u64NanoTSAnchor;6187 u64DeltaTsc = u64Tsc - g_u64TscAnchor;6154 u64DeltaNanoTS = u64NanoTS - pDevExt->u64NanoTSAnchor; 6155 u64DeltaTsc = u64Tsc - pDevExt->u64TscAnchor; 6188 6156 6189 6157 if ( pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC … … 6243 6211 while (RTTimeSystemNanoTS() == u64NanoTS) 6244 6212 ASMNopPause(); 6245 uFlags = ASMIntDisableFlags();6246 idApic = ASMGetApicId();6247 g_u64TscAnchor = ASMReadTSC();6248 g_u64NanoTSAnchor = RTTimeSystemNanoTS();6213 uFlags = ASMIntDisableFlags(); 6214 idApic = ASMGetApicId(); 6215 pDevExt->u64TscAnchor = ASMReadTSC(); 6216 pDevExt->u64NanoTSAnchor = RTTimeSystemNanoTS(); 6249 6217 ASMSetFlags(uFlags); 6250 SUPTscDeltaApply(pGip, & g_u64TscAnchor, idApic, &fDeltaApplied);6218 SUPTscDeltaApply(pGip, &pDevExt->u64TscAnchor, idApic, &fDeltaApplied); 6251 6219 6252 6220 #ifdef SUPDRV_USE_TSC_DELTA_THREAD … … 6263 6231 #endif 6264 6232 6265 rc = RTTimerCreateEx(& g_pTscRefineTimer, 0 /* one-shot */, RTTIMER_FLAGS_CPU_ANY, supdrvRefineTscTimer, pGip);6233 rc = RTTimerCreateEx(&pDevExt->pTscRefineTimer, 0 /* one-shot */, RTTIMER_FLAGS_CPU_ANY, supdrvRefineTscTimer, pDevExt); 6266 6234 if (RT_SUCCESS(rc)) 6267 6235 { … … 6274 6242 * same TSC frequency whenever possible so we need to keep the interval short. 6275 6243 */ 6276 rc = RTTimerStart( g_pTscRefineTimer, GIP_TSC_REFINE_INTERVAL * RT_NS_1SEC_64);6244 rc = RTTimerStart(pDevExt->pTscRefineTimer, GIP_TSC_REFINE_INTERVAL * RT_NS_1SEC_64); 6277 6245 AssertRC(rc); 6278 6246 } … … 6328 6296 pGip = (PSUPGLOBALINFOPAGE)RTR0MemObjAddress(pDevExt->GipMemObj); AssertPtr(pGip); 6329 6297 HCPhysGip = RTR0MemObjGetPagePhysAddr(pDevExt->GipMemObj, 0); Assert(HCPhysGip != NIL_RTHCPHYS); 6298 6299 /* 6300 * Allocate the TSC-delta sync struct on a separate cache line. 6301 */ 6302 pDevExt->pvTscDeltaSync = RTMemAllocZ(sizeof(SUPTSCDELTASYNC) + 63); 6303 pDevExt->pTscDeltaSync = RT_ALIGN_PT(pDevExt->pvTscDeltaSync, 64, PSUPTSCDELTASYNC); 6304 Assert(RT_ALIGN_PT(pDevExt->pTscDeltaSync, 64, PSUPTSCDELTASYNC) == pDevExt->pTscDeltaSync); 6330 6305 6331 6306 /* … … 6344 6319 supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), RT_NS_1SEC / u32Interval /*=Hz*/, u32Interval, cCpus); 6345 6320 6346 if (RT_UNLIKELY( g_fOsTscDeltasInSync6321 if (RT_UNLIKELY( pDevExt->fOsTscDeltasInSync 6347 6322 && pGip->u32Mode == SUPGIPMODE_ASYNC_TSC 6348 6323 && !supdrvOSGetForcedAsyncTscMode(pDevExt))) 6349 6324 { 6350 /* Basically invariant Windows boxes, should never be detected as async. */6325 /* Basically, invariant Windows boxes, should never be detected as async (i.e. TSC-deltas should be 0). */ 6351 6326 OSDBGPRINT(("supdrvGipCreate: The TSC-deltas should be normalized by the host OS, but verifying shows it's not!\n")); 6352 6327 return VERR_INTERNAL_ERROR_2; … … 6354 6329 6355 6330 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 6356 if (GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip))6331 if (GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)) 6357 6332 { 6358 6333 /* Initialize TSC-delta measurement thread before executing any Mp event callbacks. */ … … 6370 6345 uint16_t iCpu; 6371 6346 #ifndef SUPDRV_USE_TSC_DELTA_THREAD 6372 if (GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip))6347 if (GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)) 6373 6348 { 6374 6349 /* … … 6480 6455 * Destroy the TSC-refinement one-shot timer. 6481 6456 */ 6482 if (g_pTscRefineTimer) 6483 { 6484 RTTimerDestroy(g_pTscRefineTimer); 6485 g_pTscRefineTimer = NULL; 6457 if (pDevExt->pTscRefineTimer) 6458 { 6459 RTTimerDestroy(pDevExt->pTscRefineTimer); 6460 pDevExt->pTscRefineTimer = NULL; 6461 } 6462 6463 if (pDevExt->pvTscDeltaSync) 6464 { 6465 RTMemFree(pDevExt->pvTscDeltaSync); 6466 pDevExt->pTscDeltaSync = NULL; 6467 pDevExt->pvTscDeltaSync = NULL; 6486 6468 } 6487 6469 … … 6537 6519 u64NanoTS = RTTimeSystemNanoTS(); 6538 6520 6539 if (GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip))6521 if (GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)) 6540 6522 { 6541 6523 /* … … 6660 6642 u64NanoTS = RTTimeSystemNanoTS() - pGip->u32UpdateIntervalNS; 6661 6643 i = supdrvGipCpuIndexFromCpuId(pGip, idCpu); 6662 supdrvGipInitCpu(p Gip, &pGip->aCPUs[i], u64NanoTS);6644 supdrvGipInitCpu(pDevExt, pGip, &pGip->aCPUs[i], u64NanoTS); 6663 6645 idApic = ASMGetApicId(); 6664 6646 ASMAtomicWriteU16(&pGip->aCPUs[i].idApic, idApic); … … 6673 6655 6674 6656 /* Update the Mp online/offline counter. */ 6675 ASMAtomicIncU32(& g_cMpOnOffEvents);6657 ASMAtomicIncU32(&pDevExt->cMpOnOffEvents); 6676 6658 6677 6659 #ifdef SUPDRV_USE_TSC_DELTA_THREAD … … 6682 6664 * update the state and it'll get serviced when the thread's listening interval times out. 6683 6665 */ 6684 if (GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip))6666 if (GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)) 6685 6667 { 6686 6668 RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock); … … 6731 6713 6732 6714 /* Update the Mp online/offline counter. */ 6733 ASMAtomicIncU32(& g_cMpOnOffEvents);6715 ASMAtomicIncU32(&pDevExt->cMpOnOffEvents); 6734 6716 6735 6717 /* If we are the initiator going offline while measuring the TSC delta, unspin other waiting CPUs! */ 6736 if (ASMAtomicReadU32(& g_idTscDeltaInitiator) == idCpu)6737 { 6738 ASMAtomicWriteU32(& g_pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_START);6718 if (ASMAtomicReadU32(&pDevExt->idTscDeltaInitiator) == idCpu) 6719 { 6720 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_START); 6739 6721 ASMAtomicWriteU64(&pGip->aCPUs[i].u64TSCSample, ~GIP_TSC_DELTA_RSVD); 6740 6722 } 6741 6723 6742 6724 /* Reset the TSC delta, we will recalculate it lazily. */ 6743 if (GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip))6725 if (GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)) 6744 6726 ASMAtomicWriteS64(&pGip->aCPUs[i].i64TSCDelta, INT64_MAX); 6745 6727 … … 6857 6839 * 6858 6840 * @param idCpu The CPU we are current scheduled on. 6859 * @param pvUser1 Opaque pointer to the GIP.6841 * @param pvUser1 Opaque pointer to the device instance data. 6860 6842 * @param pvUser2 Opaque pointer to the worker Cpu Id. 6861 6843 * … … 6887 6869 static DECLCALLBACK(void) supdrvMeasureTscDeltaCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2) 6888 6870 { 6889 PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)pvUser1; 6871 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser1; 6872 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 6890 6873 uint32_t *pidWorker = (uint32_t *)pvUser2; 6891 RTCPUID idMaster = ASMAtomicUoReadU32(& g_idTscDeltaInitiator);6874 RTCPUID idMaster = ASMAtomicUoReadU32(&pDevExt->idTscDeltaInitiator); 6892 6875 unsigned idxMaster = supdrvGipCpuIndexFromCpuId(pGip, idMaster); 6893 6876 unsigned idxWorker = supdrvGipCpuIndexFromCpuId(pGip, *pidWorker); … … 6915 6898 if (idCpu == idMaster) 6916 6899 { 6917 ASMAtomicWriteU32(& g_pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_PRESTART_MASTER);6918 while (ASMAtomicReadU32(& g_pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_PRESTART_WORKER)6900 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_PRESTART_MASTER); 6901 while (ASMAtomicReadU32(&pDevExt->pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_PRESTART_WORKER) 6919 6902 { 6920 6903 ASMSerializeInstruction(); … … 6932 6915 else 6933 6916 { 6934 while (ASMAtomicReadU32(& g_pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_PRESTART_MASTER)6917 while (ASMAtomicReadU32(&pDevExt->pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_PRESTART_MASTER) 6935 6918 { 6936 6919 ASMSerializeInstruction(); … … 6944 6927 ASMNopPause(); 6945 6928 } 6946 ASMAtomicWriteU32(& g_pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_PRESTART_WORKER);6929 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_PRESTART_WORKER); 6947 6930 } 6948 6931 } … … 6962 6945 RTCCUINTREG uFlags; 6963 6946 Assert(pGipCpuMaster->u64TSCSample == GIP_TSC_DELTA_RSVD); 6964 ASMAtomicWriteU32(& g_pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_START);6947 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_START); 6965 6948 6966 6949 /* Disable interrupts only in the master for as short a period … … 6968 6951 uFlags = ASMIntDisableFlags(); 6969 6952 6970 while (ASMAtomicReadU32(& g_pTscDeltaSync->u) == GIP_TSC_DELTA_SYNC_START)6953 while (ASMAtomicReadU32(&pDevExt->pTscDeltaSync->u) == GIP_TSC_DELTA_SYNC_START) 6971 6954 ; 6972 6955 … … 6979 6962 ASMSetFlags(uFlags); 6980 6963 6981 while (ASMAtomicReadU32(& g_pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_WORKER_DONE)6964 while (ASMAtomicReadU32(&pDevExt->pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_WORKER_DONE) 6982 6965 ; 6983 6966 … … 6993 6976 6994 6977 ASMAtomicWriteU64(&pGipCpuMaster->u64TSCSample, GIP_TSC_DELTA_RSVD); 6995 ASMAtomicWriteU32(& g_pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_STOP);6978 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_STOP); 6996 6979 } 6997 6980 else … … 7005 6988 7006 6989 ASMAtomicReadU64(&pGipCpuMaster->u64TSCSample); /* Warm the cache line. */ 7007 while (ASMAtomicReadU32(& g_pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_START)6990 while (ASMAtomicReadU32(&pDevExt->pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_START) 7008 6991 ; 7009 6992 Assert(pGipCpuMaster->u64TSCSample == GIP_TSC_DELTA_RSVD); 7010 ASMAtomicWriteU32(& g_pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_WORKER_READY);6993 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_WORKER_READY); 7011 6994 7012 6995 /* … … 7043 7026 } 7044 7027 7045 ASMAtomicWriteU32(& g_pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_WORKER_DONE);7046 while (ASMAtomicReadU32(& g_pTscDeltaSync->u) == GIP_TSC_DELTA_SYNC_WORKER_DONE)7028 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_WORKER_DONE); 7029 while (ASMAtomicReadU32(&pDevExt->pTscDeltaSync->u) == GIP_TSC_DELTA_SYNC_WORKER_DONE) 7047 7030 ASMNopPause(); 7048 7031 } … … 7060 7043 * GIP struct. as well. 7061 7044 * 7062 * @param p Gip Pointer to the GIP.7045 * @param pDevExt Pointer to the device instance data. 7063 7046 * @param fClearDeltas Whether the deltas are also to be cleared. 7064 7047 */ 7065 DECLINLINE(void) supdrvClearTscSamples(PSUP GLOBALINFOPAGE pGip, bool fClearDeltas)7048 DECLINLINE(void) supdrvClearTscSamples(PSUPDRVDEVEXT pDevExt, bool fClearDeltas) 7066 7049 { 7067 7050 unsigned iCpu; 7051 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 7068 7052 for (iCpu = 0; iCpu < pGip->cCpus; iCpu++) 7069 7053 { … … 7073 7057 ASMAtomicWriteS64(&pGipCpu->i64TSCDelta, INT64_MAX); 7074 7058 } 7075 ASMAtomicWriteU32(& g_pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_STOP);7059 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_STOP); 7076 7060 } 7077 7061 … … 7102 7086 pGipCpuWorker = &pGip->aCPUs[idxWorker]; 7103 7087 7104 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip));7088 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)); 7105 7089 7106 7090 if (pGipCpuWorker->idCpu == idMaster) … … 7111 7095 7112 7096 /* Set the master TSC as the initiator. */ 7113 while (ASMAtomicCmpXchgU32(& g_idTscDeltaInitiator, idMaster, NIL_RTCPUID) == false)7097 while (ASMAtomicCmpXchgU32(&pDevExt->idTscDeltaInitiator, idMaster, NIL_RTCPUID) == false) 7114 7098 { 7115 7099 /* … … 7124 7108 /* Fire TSC-read workers on all CPUs but only synchronize between master and one worker to ease memory contention. */ 7125 7109 ASMAtomicWriteS64(&pGipCpuWorker->i64TSCDelta, INT64_MAX); 7126 ASMAtomicWriteU32(& g_pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_STOP);7127 rc = RTMpOnAll(supdrvMeasureTscDeltaCallback, p Gip, &pGipCpuWorker->idCpu);7110 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_STOP); 7111 rc = RTMpOnAll(supdrvMeasureTscDeltaCallback, pDevExt, &pGipCpuWorker->idCpu); 7128 7112 if (RT_SUCCESS(rc)) 7129 7113 { … … 7135 7119 rc = VERR_CPU_OFFLINE; 7136 7120 7137 ASMAtomicWriteU32(& g_idTscDeltaInitiator, NIL_RTCPUID);7121 ASMAtomicWriteU32(&pDevExt->idTscDeltaInitiator, NIL_RTCPUID); 7138 7122 return rc; 7139 7123 } … … 7160 7144 uint32_t idxMaster = UINT32_MAX; 7161 7145 int rc = VINF_SUCCESS; 7162 uint32_t cMpOnOffEvents = ASMAtomicReadU32(& g_cMpOnOffEvents);7146 uint32_t cMpOnOffEvents = ASMAtomicReadU32(&pDevExt->cMpOnOffEvents); 7163 7147 uint32_t cOnlineCpus = pGip->cOnlineCpus; 7164 7148 7165 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip));7149 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)); 7166 7150 7167 7151 /* … … 7173 7157 * master as this point since the sync/async timer isn't created yet. 7174 7158 */ 7175 supdrvClearTscSamples(p Gip, true /* fClearDeltas */);7159 supdrvClearTscSamples(pDevExt, true /* fClearDeltas */); 7176 7160 for (iCpu = 0; iCpu < RT_ELEMENTS(pGip->aiCpuFromApicId); iCpu++) 7177 7161 { … … 7214 7198 } 7215 7199 7216 if (ASMAtomicReadU32(& g_cMpOnOffEvents) != cMpOnOffEvents)7200 if (ASMAtomicReadU32(&pDevExt->cMpOnOffEvents) != cMpOnOffEvents) 7217 7201 { 7218 7202 SUPR0Printf("One or more CPUs transitioned between online & offline states. I'm confused, retrying...\n"); … … 7391 7375 * Initializes per-CPU GIP information. 7392 7376 * 7393 * @param pGip Pointer to the read-write kernel mapping of the GIP. 7377 * @param pDevExt Pointer to the device instance data. 7378 * @param pGip Pointer to the GIP. 7394 7379 * @param pCpu Pointer to which GIP CPU to initalize. 7395 7380 * @param u64NanoTS The current nanosecond timestamp. 7396 7381 */ 7397 static void supdrvGipInitCpu(PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pCpu, uint64_t u64NanoTS) 7398 { 7382 static void supdrvGipInitCpu(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pCpu, uint64_t u64NanoTS) 7383 { 7384 /* !!! Warning !!! The GIP may not be linked to the device instance data at this point! 7385 which is why we have 2 separate parameters. Don't dereference pDevExt->pGip here. */ 7399 7386 pCpu->u32TransactionId = 2; 7400 7387 pCpu->u64NanoTS = u64NanoTS; 7401 7388 pCpu->u64TSC = ASMReadTSC(); 7402 7389 pCpu->u64TSCSample = GIP_TSC_DELTA_RSVD; 7403 pCpu->i64TSCDelta = g_fOsTscDeltasInSync ? 0 : INT64_MAX;7390 pCpu->i64TSCDelta = pDevExt->fOsTscDeltasInSync ? 0 : INT64_MAX; 7404 7391 7405 7392 ASMAtomicWriteSize(&pCpu->enmState, SUPGIPCPUSTATE_INVALID); … … 7453 7440 * We only bother with TSC-deltas only on invariant CPUs for now. 7454 7441 */ 7455 g_fOsTscDeltasInSync = supdrvIsInvariantTsc() && supdrvOSAreTscDeltasInSync();7442 pDevExt->fOsTscDeltasInSync = supdrvIsInvariantTsc() && supdrvOSAreTscDeltasInSync(); 7456 7443 7457 7444 /* … … 7479 7466 7480 7467 for (i = 0; i < cCpus; i++) 7481 supdrvGipInitCpu(p Gip, &pGip->aCPUs[i], u64NanoTS);7468 supdrvGipInitCpu(pDevExt, pGip, &pGip->aCPUs[i], u64NanoTS); 7482 7469 7483 7470 /* … … 7487 7474 pDevExt->HCPhysGip = HCPhys; 7488 7475 pDevExt->cGipUsers = 0; 7489 7490 /*7491 * Allocate the TSC delta sync. struct. on a separate cache line.7492 */7493 g_pvTscDeltaSync = RTMemAllocZ(sizeof(SUPTSCDELTASYNC) + 63);7494 g_pTscDeltaSync = RT_ALIGN_PT(g_pvTscDeltaSync, 64, PSUPTSCDELTASYNC);7495 Assert(RT_ALIGN_PT(g_pTscDeltaSync, 64, PSUPTSCDELTASYNC) == g_pTscDeltaSync);7496 7476 } 7497 7477 … … 7528 7508 pGip->aCPUs[i].u64TSCSample = 0; 7529 7509 pGip->aCPUs[i].i64TSCDelta = INT64_MAX; 7530 }7531 7532 if (g_pvTscDeltaSync)7533 {7534 RTMemFree(g_pvTscDeltaSync);7535 g_pTscDeltaSync = NULL;7536 g_pvTscDeltaSync = NULL;7537 7510 } 7538 7511 } … … 7884 7857 pGip = pDevExt->pGip; 7885 7858 7886 if (!GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip))7859 if (!GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)) 7887 7860 return VINF_SUCCESS; 7888 7861 … … 7978 7951 AssertMsgReturn(iCpu < pGip->cCpus, ("iCpu=%u cCpus=%u\n", iCpu, pGip->cCpus), VERR_INVALID_CPU_INDEX); 7979 7952 7980 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(p Gip));7953 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt)); 7981 7954 rc2 = supdrvMeasureTscDeltaOne(pDevExt, iCpu); 7982 7955 if (RT_SUCCESS(rc2)) -
trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
r53430 r53464 556 556 557 557 /** 558 * The TSC delta synchronization struct. rounded to cache line size. 559 */ 560 typedef union SUPTSCDELTASYNC 561 { 562 /** The synchronization variable, holds values GIP_TSC_DELTA_SYNC_*. */ 563 volatile uint32_t u; 564 /** Padding to cache line size. */ 565 uint8_t u8Padding[64]; 566 } SUPTSCDELTASYNC; 567 AssertCompileSize(SUPTSCDELTASYNC, 64); 568 typedef SUPTSCDELTASYNC *PSUPTSCDELTASYNC; 569 570 571 /** 558 572 * Device extension. 559 573 */ … … 679 693 /** @} */ 680 694 695 /** @name TSC-delta measurement. 696 * @{ */ 697 /** TSC reading during start of TSC frequency refinement phase. */ 698 uint64_t u64TscAnchor; 699 /** Timestamp (in nanosec) during start of TSC frequency refinement phase. */ 700 uint64_t u64NanoTSAnchor; 701 /** Pointer to the timer used to refine the TSC frequency. */ 702 PRTTIMER pTscRefineTimer; 703 /** Pointer to the TSC delta sync. struct. */ 704 void *pvTscDeltaSync; 705 /** The TSC delta measurement initiator Cpu Id. */ 706 RTCPUID volatile idTscDeltaInitiator; 707 /** Number of online/offline events, incremented each time a CPU goes online 708 * or offline. */ 709 uint32_t volatile cMpOnOffEvents; 710 /** Aligned pointer to the TSC delta sync. struct. */ 711 PSUPTSCDELTASYNC pTscDeltaSync; 712 /** Whether the host OS has already normalized the hardware TSC deltas across 713 * CPUs. */ 714 bool fOsTscDeltasInSync; 715 /** @} */ 716 681 717 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 682 /** @name TSC-delta measurement .718 /** @name TSC-delta measurement thread. 683 719 * @{ */ 684 720 /** Spinlock protecting enmTscDeltaState. */
Note:
See TracChangeset
for help on using the changeset viewer.