Changeset 9621 in vbox for trunk/src/VBox/HostDrivers
- Timestamp:
- Jun 11, 2008 4:42:07 PM (16 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDRV.h
r9470 r9621 712 712 /** GIP timer interval (ms). */ 713 713 ULONG ulGipTimerInterval; 714 /** Flag to force async GIP timer mode. */715 BOOLEAN fForceAsyncTsc;716 714 /** Current CPU affinity mask. */ 717 715 KAFFINITY uAffinityMask; -
trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c
r9607 r9621 3999 3999 static DECLCALLBACK(void) supdrvDetermineAsyncTscWorker(RTCPUID idCpu, void *pvUser1, void *pvUser2) 4000 4000 { 4001 #if 1 4002 ASMAtomicWriteU64((uint64_t volatile *)pvUser1, ASMReadTSC()); 4003 #else 4001 4004 *(uint64_t *)pvUser1 = ASMReadTSC(); 4005 #endif 4002 4006 } 4003 4007 … … 4012 4016 * case we have to choose the asynchronous timer mode. 4013 4017 * 4014 * @param p u64Diff pointer to the determined difference between different cores.4018 * @param poffMin Pointer to the determined difference between different cores. 4015 4019 * @return false if the time stamp counters appear to be synchron, true otherwise. 4016 4020 */ 4017 bool VBOXCALL supdrvDetermineAsyncTsc(uint64_t *pu64DiffCores) 4018 { 4019 static uint64_t s_aTsc[8][RTCPUSET_MAX_CPUS]; 4020 uint64_t u64Diff, u64DiffMin, u64DiffMax, u64TscLast; 4021 int iSlot, iCpu, cCpus; 4022 bool fBackwards; 4023 RTCPUSET OnlineCpus; 4024 int rc; 4025 4026 *pu64DiffCores = 1; 4027 4028 RTMpGetOnlineSet(&OnlineCpus); 4029 cCpus = RTCpuSetCount(&OnlineCpus); 4030 if (cCpus < 2) 4031 return false; 4032 Assert(cCpus <= RT_ELEMENTS(s_aTsc[0])); 4033 4034 /* 4035 * Collect data from the online CPUs. 4036 */ 4037 for (iSlot = 0; iSlot < RT_ELEMENTS(s_aTsc); iSlot++) 4038 { 4039 RTCPUID iCpuSet = 0; 4040 for (iCpu = 0; iCpu < cCpus; iCpu++) 4041 { 4042 while (!RTCpuSetIsMemberByIndex(&OnlineCpus, iCpuSet)) 4021 bool VBOXCALL supdrvDetermineAsyncTsc(uint64_t *poffMin) 4022 { 4023 /* 4024 * Just iterate all the cpus 8 times and make sure that the TSC is 4025 * ever increasing. We don't bother taking TSC rollover into account. 4026 */ 4027 RTCPUSET CpuSet; 4028 int iLastCpu = RTCpuLastIndex(RTMpGetSet(&CpuSet)); 4029 int iCpu; 4030 int cLoops = 8; 4031 bool fAsync = false; 4032 int rc; 4033 uint64_t offMax = 0; 4034 uint64_t offMin = ~(uint64_t)0; 4035 uint64_t PrevTsc = ASMReadTSC(); 4036 4037 while (cLoops-- > 0) 4038 { 4039 for (iCpu = 0; iCpu <= iLastCpu; iCpu++) 4040 { 4041 uint64_t CurTsc; 4042 rc = RTMpOnSpecific(RTMpCpuIdFromSetIndex(iCpu), supdrvDetermineAsyncTscWorker, &CurTsc, NULL); 4043 if (RT_SUCCESS(rc)) 4043 4044 { 4044 iCpuSet++; /* skip offline CPU */ 4045 dprintf2(("skipping %d\n", iCpuSet)); 4045 if (CurTsc <= PrevTsc) 4046 { 4047 fAsync = true; 4048 offMin = offMax = PrevTsc - CurTsc; 4049 dprintf(("supdrvDetermineAsyncTsc: iCpu=%d cLoops=%d CurTsc=%llx PrevTsc=%llx\n", 4050 iCpu, cLoops, CurTsc, PrevTsc)); 4051 break; 4052 } 4053 4054 /* Gather statistics (except the first time). */ 4055 if (iCpu != 0 || cLoops != 7) 4056 { 4057 uint64_t off = CurTsc - PrevTsc; 4058 if (off < offMin) 4059 offMin = off; 4060 if (off > offMax) 4061 offMax = off; 4062 dprintf2(("%d/%d: off=%llx\n", cLoops, iCpu, off)); 4063 } 4064 4065 /* Next */ 4066 PrevTsc = CurTsc; 4046 4067 } 4047 rc = RTMpOnSpecific(RTMpCpuIdFromSetIndex(iCpuSet), supdrvDetermineAsyncTscWorker, &s_aTsc[iSlot][iCpu], NULL); 4048 if (rc == VERR_NOT_SUPPORTED) 4049 return false; 4050 iCpuSet++; 4051 } 4052 } 4053 4054 /* 4055 * Check that the TSC reads are strictly ascending. 4056 */ 4057 /** @todo This doesn't work if a CPU is offline. Make these loops ignore 4058 * offline CPUs. */ 4059 fBackwards = false; 4060 u64DiffMin = (uint64_t)~0; 4061 u64TscLast = 0; 4062 for (iSlot = 0; iSlot < RT_ELEMENTS(s_aTsc); iSlot++) 4063 { 4064 uint64_t u64Tsc0 = s_aTsc[iSlot][0]; 4065 u64DiffMax = 0; 4066 if (u64Tsc0 <= u64TscLast) 4067 { 4068 dprintf2(("iSlot=%d u64Tsc0=%#x%#08x u64TscLast=%#x%#08x\n", iSlot, 4069 (long)(u64Tsc0 >> 32), (long)u64Tsc0, (long)(u64TscLast >> 32), (long)u64TscLast)); 4070 fBackwards = true; 4071 } 4072 u64TscLast = u64Tsc0; 4073 for (iCpu = 1; iCpu < cCpus; iCpu++) 4074 { 4075 uint64_t u64TscN = s_aTsc[iSlot][iCpu]; 4076 if (u64TscN <= u64TscLast) 4077 { 4078 dprintf2(("iSlot=%d iCpu=%d u64TscN=%#x%#08x u64TscLast=%#x%#08x\n", iSlot, iCpu, 4079 (long)(u64TscN >> 32), (long)u64TscN, (long)(u64TscLast >> 32), (long)u64TscLast)); 4080 fBackwards = true; 4081 } 4082 u64TscLast = u64TscN; 4083 4084 u64Diff = u64TscN > u64Tsc0 ? u64TscN - u64Tsc0 : u64Tsc0 - u64TscN; 4085 if (u64DiffMax < u64Diff) 4086 u64DiffMax = u64Diff; 4087 } 4088 if (u64DiffMin > u64DiffMax) 4089 u64DiffMin = u64DiffMax; 4090 } 4091 /* informational */ 4092 *pu64DiffCores = u64DiffMin; 4093 4094 return fBackwards; 4068 else if (rc == VERR_NOT_SUPPORTED) 4069 break; 4070 else 4071 AssertMsg(rc == VERR_CPU_NOT_FOUND || rc == VERR_CPU_OFFLINE, ("%d\n", rc)); 4072 } 4073 4074 /* broke out of the loop. */ 4075 if (iCpu <= iLastCpu) 4076 break; 4077 } 4078 4079 *poffMin = offMin; /* Almost RTMpOnSpecific profiling. */ 4080 dprintf(("supdrvDetermineAsyncTsc: returns %d; iLastCpu=%d rc=%d offMin=%llx offMax=%llx\n", 4081 fAsync, iLastCpu, rc, offMin, offMax)); 4082 #if !defined(RT_OS_SOLARIS) && !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) 4083 OSDBGPRINT(("vboxdrv: fAsync=%d offMin=%#lx offMax=%#lx\n", fAsync, (long)offMin, (long)offMax)); 4084 #endif 4085 return fAsync; 4095 4086 } 4096 4087 … … 4106 4097 /* 4107 4098 * On SMP we're faced with two problems: 4108 * (1) There might be a skew between the CPU, so that cpu0 4109 * returns a TSC that is sligtly different from cpu1. 4099 * (1) There might be a skew between the CPU, so that cpu0 4100 * returns a TSC that is sligtly different from cpu1. 4110 4101 * (2) Power management (and other things) may cause the TSC 4111 4102 * to run at a non-constant speed, and cause the speed 4112 4103 * to be different on the cpus. This will result in (1). 4113 * 4104 * 4114 4105 * So, on SMP systems we'll have to select the ASYNC update method 4115 4106 * if there are symphoms of these problems. -
trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
r9602 r9621 478 478 { 479 479 int rc; 480 bool fAsync;481 uint64_t u64DiffCores;482 480 483 481 dprintf(("VBoxDrv::ModuleInit\n")); … … 603 601 */ 604 602 printk(KERN_DEBUG DEVICE_NAME ": Found %u processor cores.\n", (unsigned)RTMpGetOnlineCount()); 605 fAsync = supdrvDetermineAsyncTsc(&u64DiffCores);606 /* no 64-bit arithmetics here, we assume that the TSC difference between the cores is < 2^32 */607 printk(KERN_DEBUG DEVICE_NAME ": fAsync=%d u64DiffCores=%u.\n", fAsync, (uint32_t)u64DiffCores);608 if (fAsync)609 force_async_tsc = 1;610 611 603 #ifdef CONFIG_VBOXDRV_AS_MISC 612 604 rc = misc_register(&gMiscDevice); -
trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
r9587 r9621 136 136 { 137 137 #ifndef USE_NEW_OS_INTERFACE_FOR_GIP 138 /* Make sure the tsc is consistent across cpus/cores. */139 uint64_t u64DiffCores;140 pDevExt->fForceAsyncTsc = supdrvDetermineAsyncTsc(&u64DiffCores);141 dprintf(("supdrvDetermineAsyncTsc: fAsync=%d u64DiffCores=%u.\n", pDevExt->fForceAsyncTsc, (uint32_t)u64DiffCores));142 143 138 /* 144 139 * Inititalize the GIP. … … 802 797 bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt) 803 798 { 804 #ifdef USE_NEW_OS_INTERFACE_FOR_GIP805 799 return false; 806 #else807 return pDevExt->fForceAsyncTsc != 0;808 #endif809 800 } 810 801
Note:
See TracChangeset
for help on using the changeset viewer.