📄 lincpuid.c
字号:
} } if ( wil_quad_fix ) { g_WinCPUID_Info.bSSE2_Supported = 1; } else if (!(features & 0x04000000) && (wil_support==TRUE)) { g_WinCPUID_Info.bSSE2_Supported = 1; // SSE2 Instructions Supported Due To Pentium 4 Emulator Being Present g_WinCPUID_Info.EmulCode = SSE2_BIT; // flag SSE2 being emulated } // TODO: suuport it on Linux //CheckPNISupport(&g_WinCPUID_Info); //CheckTNISupport(&g_WinCPUID_Info); getFeatures8_1(&g_WinCPUID_Info); getFeatures8_8(&g_WinCPUID_Info); g_WinCPUID_Info.bEM64T_Supported = !(g_WinCPUID_Info.bCloneFlag) && ((g_WinCPUID_Info.coreInfo.dwFeatures8_1_edx & (1<<29)) != 0); g_WinCPUID_Info.bNX_Supported = !(g_WinCPUID_Info.bCloneFlag) && ((g_WinCPUID_Info.coreInfo.dwFeatures8_1_edx & (1<<20)) != 0); // AMD Features check if (g_WinCPUID_Info.eCPUVendor == VENDOR_AMD) { if (g_WinCPUID_Info.coreInfo.dwCPUAMDExtSignature & AMD3DNOW_BIT) { g_WinCPUID_Info.b3DNow_Supported = 1; } if (g_WinCPUID_Info.coreInfo.dwCPUAMDExtSignature & AMDEXT3DNOW_BIT) { g_WinCPUID_Info.bExt3DNow_Supported = 1; } if (g_WinCPUID_Info.coreInfo.dwCPUAMDExtSignature & AMDSSEMMXEXT_BIT) { g_WinCPUID_Info.bSSEMMXExt_Supported = 1; } } g_WinCPUID_Info.bDAZ_Supported = checkDAZ(); g_WinCPUID_Info.htInfo.nLogicalPerPackage = WinCPUID_getLogicalPerPackage(&g_WinCPUID_Info); // Set extended HT info pointer if (pInfo->htInfo.pPhysProcAff) { g_WinCPUID_Info.htInfo.pPhysProcAff = pInfo->htInfo.pPhysProcAff; g_WinCPUID_Info.htInfo.nMaxPhysGetProcAff = pInfo->htInfo.nMaxPhysGetProcAff; g_WinCPUID_Info.htInfo.nMaxCoreGetProcAff = pInfo->htInfo.nMaxCoreGetProcAff; } if (testHT(&g_WinCPUID_Info)) g_WinCPUID_Info.bHT_Supported = 1; g_WinCPUID_Info.bIsInitialized = 1; if (((!g_WinCPUID_Info.bCloneFlag) || (g_WinCPUID_Info.eCPUVendor == VENDOR_AMD)) && (g_WinCPUID_Info.coreInfo.dwCPUFamily >= 6)) { if (pInfo->pCacheInfo) { g_WinCPUID_Info.pCacheInfo = pInfo->pCacheInfo; // Cache Info initDescTable(); getCacheInfo(); } } else { if (pInfo->pCacheInfo) { g_WinCPUID_Info.pCacheInfo = pInfo->pCacheInfo; } } // Processor string if (g_WinCPUID_Info.coreInfo.dwCPUFamily >= 6) { if (pInfo->pProcString) { g_WinCPUID_Info.pProcString = pInfo->pProcString; getProcStr(g_WinCPUID_Info.pProcString); } } else { if (pInfo->pProcString) { g_WinCPUID_Info.pProcString = pInfo->pProcString; strcpy(g_WinCPUID_Info.pProcString, ""); } } *pInfo = g_WinCPUID_Info; // copy to external structure; //printf("LinCPU Init Success!\n"); return TRUE;}#ifndef _M_X64DWORD WinCPUID_FindMaskWidth(DWORD Max_Count){ DWORD mask_width=0, cnt = Max_Count; return mask_width;}#endif// Returns the value of the sub ID, this is not a zero-based valuestatic BYTE GetSubID(BYTE Full_ID, BYTE MaxSubIDValue, BYTE ShiftValue){ DWORD MaskWidth, Shift_Count; BYTE MaskBits, SubID; Shift_Count = (ShiftValue == 0) ? 0 : WinCPUID_FindMaskWidth(ShiftValue); MaskWidth = WinCPUID_FindMaskWidth(MaxSubIDValue); MaskBits = ((BYTE) (0xff << Shift_Count)) ^ ((BYTE) (0xff << (Shift_Count + MaskWidth))) ; // New version, but it is the same as SK's //MaskBits = (0xff << ShiftCount) ^ ((BYTE) (0xff << (Shift_Count + MaskWidth))); SubID = Full_ID & MaskBits; return SubID;}static int GetMaxCacheLevel(const CPUINFO_T *pInfo){ DWORD maxLLCLevel = 0; DWORD HT_MC_Sup = pInfo->coreInfo.dwCPUFeatures & HT_BIT; int nExpCaches; if (!HT_MC_Sup || pInfo->bNonIntelFlag) { // must be single-core and discrete cache return 2; } nExpCaches = WinCPUID_GetNumExplicitCaches(); if (nExpCaches > 0) { EXPLICITCACHEINFO_T expCI; EXPCACHE_COMMON_T expCC; BOOL bRet; int i; for (i=0; i < nExpCaches; i++) { ZeroMemory(&expCC, sizeof(EXPCACHE_COMMON_T)); bRet = WinCPUID_GetExplicitCache(&expCI, i); //BREAK_ON_ERR_B(bRet); bRet = WinCPUID_GetExpCacheCommonInfo(&expCC, &expCI); //BREAK_ON_ERR_B(bRet); if (expCC.CacheLevel > maxLLCLevel) maxLLCLevel = expCC.CacheLevel; } } else { maxLLCLevel = 2; } return maxLLCLevel;} /*** end GetMaxNumLPSharingCache() ***/static DWORD GetIndexForCacheLevelAndType(int level, int type){ EXPLICITCACHEINFO_T expCI; DWORD cacheIndex; DWORD targetIdx = (DWORD)-1; int nExpCaches = WinCPUID_GetNumExplicitCaches(); DWORD t; CPUID_ARGS ca; ca.eax = 0; CPUIDF(&ca); t = ca.eax; for (cacheIndex=0; cacheIndex < nExpCaches; cacheIndex++) { EXPCACHE_COMMON_T expCC; BOOL bRet; ZeroMemory(&expCC, sizeof(EXPCACHE_COMMON_T)); bRet = WinCPUID_GetExplicitCache(&expCI, cacheIndex); if (!bRet) break; bRet = WinCPUID_GetExpCacheCommonInfo(&expCC, &expCI); //BREAK_ON_ERR_B(bRet); if ( (expCC.CacheLevel == level) && (expCC.CacheType == type) ) { targetIdx = cacheIndex; break; } } return targetIdx;}// From Shihjong Kuo// Only for unified inst & data (UL2, UL3, etc) cachesstatic DWORD getMaxNumLPSharingCache(int level, const CPUINFO_T *pInfo){ DWORD maxLPSharingCache = 0; DWORD HT_MC_Sup = pInfo->coreInfo.dwCPUFeatures & HT_BIT; if (!HT_MC_Sup || pInfo->bNonIntelFlag) { // must be single-core and discrete cache return 1; } if (WinCPUID_GetNumExplicitCaches() > 0) { EXPLICITCACHEINFO_T expCI; EXPCACHE_COMMON_T expCC; BOOL bRet; ZeroMemory(&expCC, sizeof(EXPCACHE_COMMON_T)); bRet = WinCPUID_GetExplicitCache(&expCI, GetIndexForCacheLevelAndType(level, 3)); //BREAK_ON_ERR_B(bRet); bRet = WinCPUID_GetExpCacheCommonInfo(&expCC, &expCI); //BREAK_ON_ERR_B(bRet); maxLPSharingCache = expCC.ThreadsPerCache; } else { maxLPSharingCache = pInfo->htInfo.nLogicalPerPackage; } return maxLPSharingCache;} /*** end GetMaxNumLPSharingCache() ***/// If this was C++, these structs would belong in a private namespacetypedef struct _log_ids_s{ BYTE SMT_ID; BYTE CORE_ID; BYTE PACKAGE_ID; BYTE LLC_ID; // Extend SK's alg by adding the core/pkg index into this array when the affinity masks are computed // This makes filling in the 3-level array for package/core/logical mapping much easier int coreIndex; int packageIndex; int L2CacheIndex; int CacheSharedIndex; int bIsFirstSMTonCore; // TRUE if this is the first SMT logical on a core} TLogicalID;static BOOL getLogPhysProcs(CPUINFO_T *pi) { HANDLE hCurrentProcessHandle; DWORD_PTR dwProcessAffinity; DWORD_PTR dwSystemAffinity; DWORD_PTR dwAffinityMask; BOOL MCorHT_Enabled = FALSE; EXPLICITCACHEINFO_T expCI; EXPCACHE_COMMON_T expCC; int nCores = 0; TLogicalID *LogIDs; // index is logical number int *PackageIDBucket; // index is package number int *CoreIDBucket; // index is core number int *L2CacheIDBucket; int *LLCSharingBucket; DWORD_PTR *PackageProcessorMask; // index is package number DWORD_PTR *CoreProcessorMask; // index is core number DWORD_PTR PackagesAffinity = 0; // Affinity mask for the first logical on each package, for WinCPUID API DWORD_PTR CoresAffinity = 0; // Affinity mask for the first logical on each core, for WinCPUID API CPUAFFINITY LLCSharingAffinity = 0; int curLogical; int nLogicalFound = 0; // number of booted logicals found int nPackagesFound = 0; int nCoresFound = 0; int L2CachesFound = 0; int curSharedIndex = 0; int LLC_Level = GetMaxCacheLevel(pi); int nLogicalSystem; // number reported by sytem SYSTEM_INFO si; ZeroMemory(&si, sizeof(SYSTEM_INFO));// GetSystemInfo(&si);// nLogicalSystem = si.dwNumberOfProcessors; nLogicalSystem = 1; LogIDs = (TLogicalID*)_alloca( nLogicalSystem * sizeof(TLogicalID) ); ZeroMemory(LogIDs, sizeof( nLogicalSystem * sizeof(TLogicalID)) ); ZeroMemory(&expCC, sizeof(EXPCACHE_COMMON_T)); // If the cpu has the explicit cache info, check any explicit cache to get the number of cores per package if (WinCPUID_GetNumExplicitCaches() > 0) { WinCPUID_GetExplicitCaches(&expCI, 1); WinCPUID_GetExpCacheCommonInfo(&expCC, &expCI); pi->htInfo.nCoresPerPackage = expCC.CoresPerPackage; } else if (pi->eCPUVendor == VENDOR_AMD) { // nCoresPerPackage already set by WinCPUID_GetLogicalPerPackage if (pi->htInfo.nCoresPerPackage == 0) pi->htInfo.nCoresPerPackage = 1; } else { // We know it is not multi-core pi->htInfo.nCoresPerPackage = 1; } pi->htInfo.nLogicalPerCore = pi->htInfo.nLogicalPerPackage / pi->htInfo.nCoresPerPackage; hCurrentProcessHandle = GetCurrentProcess(); GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity, &dwSystemAffinity); // Iterate over all available logical processors and collect topology info for (curLogical = 0, dwAffinityMask = 1; ( (dwAffinityMask != 0) && (dwAffinityMask <= dwProcessAffinity) && (curLogical < nLogicalSystem) ); curLogical++) { if (SetProcessAffinityMask(hCurrentProcessHandle, dwAffinityMask)) { BYTE PackageIDMask, CacheIDMask; BYTE APIC_ID, SMT_ID, CORE_ID, PACKAGE_ID, LLC_ID; Sleep(0); // continue from next time slice on appropriate CPU APIC_ID = (BYTE) WinCPUID_getAPIC_ID(); SMT_ID = GetSubID(APIC_ID, pi->htInfo.nLogicalPerCore, 0); CORE_ID = GetSubID(APIC_ID, pi->htInfo.nCoresPerPackage, pi->htInfo.nLogicalPerCore); PackageIDMask = (BYTE) (0xff << WinCPUID_FindMaskWidth(pi->htInfo.nLogicalPerPackage)); PACKAGE_ID = APIC_ID & PackageIDMask; // Cache topology may vary for each cache level, one mask for each level. // The target level is selected by the input value index CacheIDMask = ((BYTE) (0xff << WinCPUID_FindMaskWidth(getMaxNumLPSharingCache(LLC_Level, pi)))); // Find LLC's level and max sharing LLC_ID = APIC_ID & CacheIDMask; LogIDs[curLogical].SMT_ID = SMT_ID; LogIDs[curLogical].CORE_ID = CORE_ID; LogIDs[curLogical].PACKAGE_ID = PACKAGE_ID; LogIDs[curLogical].LLC_ID = LLC_ID; LogIDs[curLogical].packageIndex = -1; LogIDs[curLogical].coreIndex = -1; LogIDs[curLogical].bIsFirstSMTonCore = FALSE; } else { pi->htInfo.htResultCode = htError; } dwAffinityMask <<= 1; nLogicalFound++; } // Reset affinity to all logical CPUs SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity); Sleep(0); PackageIDBucket = (int*)_alloca(nLogicalFound * sizeof(int)); memset(PackageIDBucket, -1, nLogicalFound * sizeof(int)); CoreIDBucket = (int*)_alloca(nLogicalFound * sizeof(int)); memset(CoreIDBucket, -1, nLogicalFound * sizeof(int)); L2CacheIDBucket = (int*)_alloca(nLogicalFound * sizeof(int)); memset(L2CacheIDBucket, -1, nLogicalFound * sizeof(int)); LLCSharingBucket = (int*)_alloca(nLogicalFound*sizeof(int)); memset(LLCSharingBucket, 0, nLogicalFound * sizeof(int)); PackageProcessorMask = (DWORD_PTR*)_alloca(nLogicalFound * sizeof(DWORD_PTR)); ZeroMemory(PackageProcessorMask, nLogicalFound * sizeof(DWORD_PTR)); CoreProcessorMask = (DWORD_PTR*)_alloca(nLogicalFound * sizeof(DWORD_PTR)); ZeroMemory(CoreProcessorMask, nLogicalFound * sizeof(DWORD_PTR)); // Find the number of distinct packages // To start, there must be at least 1 package nPackagesFound = 1; dwAffinityMask = 1; LogIDs[0].packageIndex = 0; PackageIDBucket[0] = LogIDs[0].PACKAGE_ID; PackageProcessorMask[0] = dwAffinityMask; PackagesAffinity = dwAffinityMask; for (curLogical=1; curLogical < nLogicalFound; curLogical++) { int curPackage; dwAffinityMask <<= 1; for (curPackage=0; curPackage < nPackagesFound; curPackage++) { if (LogIDs[curLogical].PACKAGE_ID == PackageIDBucket[curPackage]) { PackageProcessorMask[curPackage] |= dwAffinityMask; LogIDs[curLogical].packageIndex = curPackage; break; } } if (curPackage == nPackagesFound) { // no match, found a new package PackageIDBucket[curPackage] = LogIDs[curLogical].PACKAGE_ID; LogIDs[curLogical].packageIndex = curPackage; PackagesAffinity |= dwAffinityMask; PackageProcessorMask[curPackage] |= dwAffinityMask; nPackagesFound++; } } nCoresFound = 1; dwAffinityMask = 1; LogIDs[0].coreIndex = 0; LogIDs[0].bIsFirstSMTonCore = TRUE; // mark first logical on core CoreIDBucket[0] = LogIDs[0].PACKAGE_ID | LogIDs[0].CORE_ID; CoreProcessorMask[0] = dwAffinityMask; CoresAffinity = dwAffinityMask; for (curLogical=1; curLogical < nLogicalFound; curLogical++) { int curCore; dwAffinityMask <<= 1; for (curCore=0; curCore < nCoresFound; curCore++) { if ( (LogIDs[curLogical].PACKAGE_ID | LogIDs[curLogical].CORE_ID) == CoreIDBucket[curCore]) { CoreProcessorMask[curCore] |= dwAffinityMask; LogIDs[curLogical].coreIndex = curCore; break; } } if (curCore == nCoresFound) { // no match, found a new core CoreIDBucket[curCore] = LogIDs[curLogical].PACKAGE_ID | LogIDs[curLogical].CORE_ID; LogIDs[curLogical].coreIndex = curCore; LogIDs[curLogical].bIsFirstSMTonCore = TRUE; // mark first logical on core CoresAffinity |= dwAffinityMask; CoreProcessorMask[curCore] |= dwAffinityMask; nCoresFound++; } } // Find number of unique LLC IDs L2CachesFound = 1; dwAffinityMask = 1; LogIDs[0].L2CacheIndex = 0; LogIDs[0].CacheSharedIndex = 0; L2CacheIDBucket[0] = LogIDs[0].LLC_ID; LLCSharingBucket[0]++; LLCSharingAffinity = dwAffinityMask; for (curLogical=1; curLogical < nLogicalFound; curLogical++) { int curL2Cache; dwAffinityMask <<= 1; for (curL2Cache=0; curL2Cache < L2CachesFound; curL2Cache++) { if (LogIDs[curLogical].LLC_ID == L2CacheIDBucket[curL2Cache]) { LogIDs[curLogical].L2CacheIndex = curL2Cache; LogIDs[curLogical].CacheSharedIndex = LLCSharingBucket[curL2Cache]++; break; } } if (curL2Cache == L2CachesFound) { // no match, found a new package L2CacheIDBucket[curL2Cache] = LogIDs[curLogical].LLC_ID; LogIDs[curLogical].L2CacheIndex = curL2Cache; LogIDs[curLogical].CacheSharedIndex = LLCSharingBucket[curL2Cache]++; L2CachesFound++; curSharedIndex = 0; LLCSharingAffinity |= dwAffinityMask; } } // The rest of this is for translating the information found above into the format // used by the WinCPUID API pi->htInfo.nPhysicalProcs = nPackagesFound; pi->htInfo.nCores = pi->htInfo.nCoresPerPackage * pi->htInfo.nPhysicalProcs; pi->htInfo.nCoresAvailable = nCoresFound; pi->htInfo.nLogicalProcs = nLogicalFound; pi->htInfo.nLogicalPerCoreAvailable = nLogicalFound / nCoresFound; pi->htInfo.dwPhysicalAffinity = PackagesAffinity; pi->htInfo.CoreAffinity = CoresAffinity; pi->htInfo.dwLogicalAffinity = dwProcessAffinity & ~PackagesAffinity; pi->htInfo.CoreLogicalAffinity = dwProcessAffinity & ~CoresAffinity; pi->htInfo.LLCDomainAffinity = LLCSharingAffinity; pi->htInfo.nLastLevelCachesAvailable = L2CachesFound; pi->htInfo.LLC_Level = LLC_Level; MCorHT_Enabled = (nLogicalFound > nPackagesFound); { int nPhy; for (nPhy = 0; pi->htInfo.pPhysProcAff && (nPhy < pi->htInfo.nMaxPhysGetProcAff) && (nPhy < pi->htInfo.nPhysicalProcs); nPhy++) { int nCoreOnPhy=0; pi->htInfo.pPhysProcAff[nPhy].physID = PackageIDBucket[nPhy]; pi->htInfo.pPhysProcAff[nPhy].dwPhysAffinity = PackageProcessorMask[nPhy] & PackagesAffinity; pi->htInfo.pPhysProcAff[nPhy].dwLogAffinity = PackageProcessorMask[nPhy] & ~PackagesAffinity; // Find all cores on this package for (curLogical=0; curLogical < nLogicalFound; curLogical++) { if ((LogIDs[curLogical].packageIndex == nPhy) && (LogIDs[curLogical].bIsFirstSMTonCore == TRUE)) { // curLogical belongs to core nCoreOnPhy on this package if (pi->htInfo.pPhysProcAff[nPhy].pCoreProcAff && (nCoreOnPhy < pi->htInfo.nMaxCoreGetProcAff)) // check that pCoreProcAff is big enough { pi->htInfo.pPhysProcAff[nPhy].pCoreProcAff[nCoreOnPhy].coreID = LogIDs[curLogical].CORE_ID; //pi->htInfo.pPhysProcAff[nPhy].pCoreProcAff[nCoreOnPhy].LLC_ID = LogIDs[curLogical].LLC_ID; //pi->htInfo.pPhysProcAff[nPhy].pCoreProcAff[nCoreOnPhy].LLC_Index = LogIDs[curLogical].L2CacheIndex; //pi->htInfo.pPhysProcAff[nPhy].pCoreProcAff[nCoreOnPhy].LLC_SharedIndex = LogIDs[curLogical].CacheSharedIndex; pi->htInfo.pPhysProcAff[nPhy].pCoreProcAff[nCoreOnPhy].dwCoreAffinity = CoreProcessorMask[LogIDs[curLogical].coreIndex] & CoresAffinity; pi->htInfo.pPhysProcAff[nPhy].pCoreProcAff[nCoreOnPhy].dwLogAffinity = CoreProcessorMask[LogIDs[curLogical].coreIndex] & ~CoresAffinity; } pi->htInfo.pPhysProcAff[nPhy].nCores++; nCoreOnPhy++; } } } } return MCorHT_Enabled;}static int testHT(CPUINFO_T *pi) { int rval = 0; int JT_Enabled = 0; // Test number of procs first so it is consistent on P3/P4, DP/HT/non-HT pi->htInfo.nLogicalPerPackage = WinCPUID_getLogicalPerPackage(pi); JT_Enabled = getLogPhysProcs(pi); if (!pi->bCloneFlag && (pi->coreInfo.dwCPUFeatures & HT_BIT) ) { if (pi->htInfo.nLogicalPerPackage > 1) { if (JT_Enabled) { // Processors with HT enabled and available pi->htInfo.htResultCode = htAvailable; rval = 1; } else { // Processors with HT enabled, but HT not available pi->htInfo.htResultCode = htNotAvailable; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -