- Timestamp:
- Feb 19, 2015 3:19:34 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r54290 r54298 4321 4321 { 4322 4322 SUPDRVGIPDETECTGETCPU DetectState; 4323 RT_ ZERO(DetectState.bmApicId);4323 RT_BZERO((void *)&DetectState.bmApicId, sizeof(DetectState.bmApicId)); 4324 4324 DetectState.fSupported = UINT32_MAX; 4325 4325 DetectState.idCpuProblem = NIL_RTCPUID; … … 5965 5965 return VERR_NOT_IMPLEMENTED; 5966 5966 #endif 5967 }5968 5969 5970 /**5971 * Returns whether the host CPU sports an invariant TSC or not.5972 *5973 * @returns true if invariant TSC is supported, false otherwise.5974 */5975 static bool supdrvIsInvariantTsc(void)5976 {5977 static bool s_fQueried = false;5978 static bool s_fIsInvariantTsc = false;5979 if (!s_fQueried)5980 {5981 if (ASMHasCpuId())5982 {5983 uint32_t uEax, uEbx, uEcx, uEdx;5984 ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx);5985 if (uEax >= 0x80000007)5986 {5987 ASMCpuId(0x80000007, &uEax, &uEbx, &uEcx, &uEdx);5988 if (uEdx & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR)5989 s_fIsInvariantTsc = true;5990 }5991 }5992 s_fQueried = true;5993 }5994 5995 return s_fIsInvariantTsc;5996 5967 } 5997 5968 … … 7159 7130 /* Reset the TSC delta, we will recalculate it lazily. */ 7160 7131 if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED) 7132 { 7161 7133 ASMAtomicWriteS64(&pGip->aCPUs[i].i64TSCDelta, INT64_MAX); 7162 7163 7134 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 7164 /* Remove this CPU from the set of CPUs that we have obtained the TSC deltas. */ 7165 if (supdrvIsInvariantTsc()) 7135 /* Remove this CPU from the set of CPUs that we have obtained the TSC deltas. */ 7166 7136 RTCpuSetDel(&pDevExt->TscDeltaObtainedCpuSet, idCpu); 7167 7137 #endif 7138 } 7168 7139 7169 7140 /* commit it */ … … 7769 7740 7770 7741 /** 7771 * Determinethe GIP TSC mode.7742 * supdrvGipInit() worker that determines the GIP TSC mode. 7772 7743 * 7773 7744 * @returns The most suitable TSC mode. 7774 7745 * @param pDevExt Pointer to the device instance data. 7775 7746 */ 7776 static SUPGIPMODE supdrvGipDetermineTscMode(PSUPDRVDEVEXT pDevExt) 7777 { 7778 /* Trust CPUs that declare their TSC to be invariant. */ 7779 #if 0 /** @todo this cannot be enabled until Michal's AMD laptop with insane deltas are working. */ 7780 if (supdrvIsInvariantTsc()) 7747 static SUPGIPMODE supdrvGipInitDetermineTscMode(PSUPDRVDEVEXT pDevExt) 7748 { 7749 uint64_t u64DiffCoresIgnored; 7750 uint32_t uEAX, uEBX, uECX, uEDX; 7751 7752 /* 7753 * Establish whether the CPU advertises TSC as invariant, we need that in 7754 * a couple of places below. 7755 */ 7756 bool fInvariantTsc = false; 7757 if (ASMHasCpuId()) 7758 { 7759 uEAX = ASMCpuId_EAX(0x80000000); 7760 if (ASMIsValidExtRange(uEAX) && uEAX >= 0x80000007) 7761 { 7762 uEDX = ASMCpuId_EDX(0x80000007); 7763 if (uEDX & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR) 7764 fInvariantTsc = true; 7765 } 7766 } 7767 7768 /* 7769 * On single CPU systems, we don't need to consider ASYNC mode. 7770 */ 7771 if (RTMpGetCount() <= 1) 7772 return fInvariantTsc ? SUPGIPMODE_INVARIANT_TSC : SUPGIPMODE_SYNC_TSC; 7773 7774 /* 7775 * Allow the user and/or OS specific bits to force async mode. 7776 */ 7777 if (supdrvOSGetForcedAsyncTscMode(pDevExt)) 7778 return SUPGIPMODE_ASYNC_TSC; 7779 7780 7781 #if 0 /** @todo enable this when i64TscDelta is applied in all places where it's needed */ 7782 /* 7783 * Use invariant mode if the CPU says TSC is invariant. 7784 */ 7785 if (fInvariantTsc) 7781 7786 return SUPGIPMODE_INVARIANT_TSC; 7782 7787 #endif 7783 7788 7784 7789 /* 7785 * Without invariant CPU ID bit - On SMP we're faced with two problems: 7790 * TSC is not invariant and we're on SMP, this presents two problems: 7791 * 7786 7792 * (1) There might be a skew between the CPU, so that cpu0 7787 7793 * returns a TSC that is slightly different from cpu1. 7794 * This screw may be due to (2), bad TSC initialization 7795 * or slightly different TSC rates. 7796 * 7788 7797 * (2) Power management (and other things) may cause the TSC 7789 7798 * to run at a non-constant speed, and cause the speed 7790 7799 * to be different on the cpus. This will result in (1). 7791 7800 * 7792 * So, on SMP systems we'll have to select the ASYNC update method 7793 * if there are symptoms of these problems. 7794 */ 7795 if (RTMpGetCount() > 1) 7796 { 7797 uint32_t uEAX, uEBX, uECX, uEDX; 7798 uint64_t u64DiffCoresIgnored; 7799 7800 /* Permit the user and/or the OS specific bits to force async mode. */ 7801 if (supdrvOSGetForcedAsyncTscMode(pDevExt)) 7802 return SUPGIPMODE_ASYNC_TSC; 7803 7804 /* Try check for current differences between the cpus. */ 7805 if (supdrvDetermineAsyncTsc(&u64DiffCoresIgnored)) 7806 return SUPGIPMODE_ASYNC_TSC; 7807 7808 /* 7809 * If the CPU supports power management and is an AMD one we 7810 * won't trust it unless it has the TscInvariant bit is set. 7811 */ 7812 /** @todo this is now redundant. remove later. */ 7813 /* Check for "AuthenticAMD" */ 7814 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX); 7815 if ( uEAX >= 1 7816 && ASMIsAmdCpuEx(uEBX, uECX, uEDX)) 7817 { 7818 /* Check for APM support and that TscInvariant is cleared. */ 7819 ASMCpuId(0x80000000, &uEAX, &uEBX, &uECX, &uEDX); 7820 if (uEAX >= 0x80000007) 7821 { 7822 ASMCpuId(0x80000007, &uEAX, &uEBX, &uECX, &uEDX); 7823 if ( !(uEDX & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR) /* TscInvariant */ 7824 && (uEDX & 0x3e)) /* STC|TM|THERMTRIP|VID|FID. Ignore TS. */ 7825 return SUPGIPMODE_ASYNC_TSC; 7826 } 7827 } 7828 } 7829 7830 /** @todo later remove this when the above todo with AMD laptop is done (i.e. 7831 * TSC deltas handled everywhere). */ 7832 if (supdrvIsInvariantTsc()) 7801 * If any of the above is detected, we will have to use ASYNC mode. 7802 */ 7803 7804 /* (1). Try check for current differences between the cpus. */ 7805 if (supdrvDetermineAsyncTsc(&u64DiffCoresIgnored)) 7806 return SUPGIPMODE_ASYNC_TSC; 7807 7808 #if 1 /** @todo remove once i64TscDelta is applied everywhere. Enable #if 0 above. */ 7809 if (fInvariantTsc) 7833 7810 return SUPGIPMODE_INVARIANT_TSC; 7811 #endif 7812 7813 /* (2) If it's an AMD CPU with power management, we won't trust its TSC. */ 7814 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX); 7815 if ( ASMIsValidStdRange(uEAX) 7816 && ASMIsAmdCpuEx(uEBX, uECX, uEDX)) 7817 { 7818 /* Check for APM support. */ 7819 uEAX = ASMCpuId_EAX(0x80000000); 7820 if (ASMIsValidExtRange(uEAX) && uEAX >= 0x80000007) 7821 { 7822 uEDX = ASMCpuId_EDX(0x80000007); 7823 if (uEDX & 0x3e) /* STC|TM|THERMTRIP|VID|FID. Ignore TS. */ 7824 return SUPGIPMODE_ASYNC_TSC; 7825 } 7826 } 7827 7834 7828 return SUPGIPMODE_SYNC_TSC; 7835 7829 } … … 7907 7901 pGip->u32Magic = SUPGLOBALINFOPAGE_MAGIC; 7908 7902 pGip->u32Version = SUPGLOBALINFOPAGE_VERSION; 7909 pGip->u32Mode = supdrvGip DetermineTscMode(pDevExt);7903 pGip->u32Mode = supdrvGipInitDetermineTscMode(pDevExt); 7910 7904 if ( pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC 7911 7905 /*|| pGip->u32Mode == SUPGIPMODE_SYNC_TSC */) 7912 pGip->enmUseTscDelta = supdrv IsInvariantTsc() && supdrvOSAreTscDeltasInSync() /* Allow OS override (windows). */7906 pGip->enmUseTscDelta = supdrvOSAreTscDeltasInSync() /* Allow OS override (windows). */ 7913 7907 ? SUPGIPUSETSCDELTA_ZERO_CLAIMED : SUPGIPUSETSCDELTA_PRACTICALLY_ZERO /* downgrade later */; 7914 7908 else
Note:
See TracChangeset
for help on using the changeset viewer.