📄 lincpuid.c
字号:
/*Copyright (c) 2008, Intel Corporation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*///#include <windows.h>#include <math.h>#include <assert.h>#include "LinCPUID.h"#include "Cpuid.h"static char g_ci2str[NCACHETYPES][8] = { "NULL", "L1I", "L1D", "L2", "TC", "L3", "ITLB", "DTLB" };static char g_bri2str[256][128] = { "This processor does not support the brand identification feature", // 0 "Intel(R) Celeron(R) Processor", // 1 "Intel(R) Pentium(R) III Processor", // 2 "Intel(R) Xeon(TM) Processor", // 3, If signature== 0x6b1, then "Intel(R) Celeron(R) Processor" "Intel(R) Pentium(R) III Processor", // 4 "Reserved (5)", // 5 "Mobile Intel(R) Pentium(R) III Processor-M", // 6 "Mobile Intel(R) Celeron(R) Processor", // 7 "Intel(R) Pentium(R) 4 Processor", // 8 "Intel(R) Pentium(R) 4 Processor", // 9 "Intel(R) Celeron(R) Processor", // "Intel(R) Pentium(R) 4 Processor", // 10 (Second-Generation) "Intel(R) Xeon(TM) Processor", // 0xB, 11, If signature >= 0xF13, then "Intel(R) Xeon(tm) Processor MP" "Intel(R) Xeon(TM) Processor MP", //Reserved (12)", // 12 "Reserved (13)", // 13 "Mobile Intel(R) Pentium(R) 4 Processor-M", // 14 "Intel(R) Xeon(tm) Processor", // 14, except if 0xF2X, then it's a P4-M "Mobile Intel(R) Celeron(R) Processor", //"Intel(R) Xeon(tm) Processor", // 15 "Intel(R) Pentium(R) M Processor (ID=16)", // 16 "Reserved (17)", // 17 "Reserved (18)", // 18 "Mobile Intel(R) Celeron(R) Processor", //"Reserved (19)", // 19, 0x13 "Reserved (20)", // 20 "Reserved (21)", // 21 "Intel(R) Pentium(R) M Processor" // 22 };static char g_type2str[4][64] = { "Original OEM Processor", "Intel OverDrive?Processor", "Dual processor", "Intel reserved"};static char g_htRes2str[htAvailable+1][64] = { "Error detecting HT", "HT processors not detected", "HT detected, but not enabled", "HT enabled, but not available", "HT enabled and available"};#define HT_BIT 0x10000000#define FXSR_BIT 0x01000000#define SSE_BIT 0x02000000#define SSE2_BIT 0x04000000#define PNI_BIT 0x00000001 // PNI indicator in ecx after cpuid(eax(1))#define TNI_BIT 0x00000200 // TNI indicator in ecx after cpuid(eax(1))#define AMDSSEMMXEXT_BIT 0x00400000#define AMD3DNOW_BIT 0x80000000 #define AMDEXT3DNOW_BIT 0x40000000#define PSN_BIT 0x00040000 // XTODO: Add processor serial number#define NUM_LOGICAL_BITS 0x00FF0000 // ebx[23:16] indicate number of logical processors per package#define INITIAL_APIC_ID_BITS 0xFF000000 // ebx[31:24] unique APIC ID// JS - Added 0 to the fourth positions below to accommodate lines info reported by AMD// ITLBstatic CACHEINFO_T CI_01 = { 32, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_02 = { 2, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_50 = { 64, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_51 = { 128, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_52 = { 256, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_B0 = { 128, 0, 0, 0, 0, 0 }; // Banias// DTLBstatic CACHEINFO_T CI_03 = { 64, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_04 = { 8, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_5B = { 64, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_5C = { 128, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_5D = { 256, 0, 0, 0, 0, 0 };static CACHEINFO_T CI_B3 = { 128, 0, 0, 0, 0, 0 }; // Banias// L1Dstatic CACHEINFO_T CI_0A = { 8, 2, 32, 0, 0, 0 };static CACHEINFO_T CI_0C = { 16, 4, 32, 0, 0, 0 };static CACHEINFO_T CI_60 = { 16, 8, 64, 0, 0, 0 }; // PSCstatic CACHEINFO_T CI_66 = { 8, 4, 64, 0, 0, 0 };static CACHEINFO_T CI_67 = { 16, 4, 64, 0, 0, 0 };static CACHEINFO_T CI_68 = { 32, 4, 64, 0, 0, 0 };static CACHEINFO_T CI_2C = { 32, 8, 64, 0, 0, 0 }; // Banias// L2//static CACHEINFO_T CI_40 = { 0, 0, 0, 0 };static CACHEINFO_T CI_41 = { 128, 4, 32, 0, 0, 0 };static CACHEINFO_T CI_42 = { 256, 4, 32, 0, 0, 0 };static CACHEINFO_T CI_43 = { 512, 4, 32, 0, 0, 0 };static CACHEINFO_T CI_44 = { 1024, 4, 32, 0, 0, 0 };static CACHEINFO_T CI_45 = { 2048, 4, 32, 0, 0, 0 };static CACHEINFO_T CI_78 = { 1024, 4, 64, 0, 0, 0 }; // Dothanstatic CACHEINFO_T CI_79 = { 128, 8, 64, 0, 0, 0 };static CACHEINFO_T CI_7A = { 256, 8, 64, 0, 0, 0 };static CACHEINFO_T CI_7B = { 512, 8, 64, 0, 0, 0 };static CACHEINFO_T CI_7C = { 1024, 8, 64, 0, 0, 0 };static CACHEINFO_T CI_7D = { 2048, 8, 64, 0, 0, 0 }; // Dothanstatic CACHEINFO_T CI_82 = { 256, 8, 32, 0, 0, 0 };static CACHEINFO_T CI_84 = { 1024, 8, 32, 0, 0, 0 };static CACHEINFO_T CI_85 = { 2048, 8, 32, 0, 0, 0 };static CACHEINFO_T CI_86 = { 512, 8, 64, 0, 0, 0 }; // Baniasstatic CACHEINFO_T CI_87 = { 1024, 8, 64, 0, 0, 0 }; // Banias//0x78: L2: 1MB, 4-way set associative, 64 byte line size//0x7d: L2: 2MB, 4-way set associative, 64 byte line size// L3static CACHEINFO_T CI_22 = { 512, 4, 64, 0, 0, 0 };static CACHEINFO_T CI_23 = { 1024, 8, 64, 0, 0, 0 };static CACHEINFO_T CI_25 = { 2048, 8, 64, 0, 0, 0 };static CACHEINFO_T CI_29 = { 4096, 8, 64, 0, 0, 0 };// TCstatic CACHEINFO_T CI_70 = { 12, 8, 0, 0, 0, 0 };static CACHEINFO_T CI_71 = { 16, 8, 0, 0, 0, 0 };static CACHEINFO_T CI_72 = { 32, 8, 0, 0, 0, 0 };// L1Istatic CACHEINFO_T CI_06 = { 8, 4, 32, 0, 0, 0 };static CACHEINFO_T CI_08 = { 16, 4, 32, 0, 0, 0 };static CACHEINFO_T CI_30 = { 32, 8, 64, 0, 0, 0 }; // Baniasstatic int g_ciTableLU[256];static CACHEINFO_T g_ciInfoLU[NCACHETYPES][256];static void initDescTable();static int getCacheInfo();static int getProcStr(char *outStr);WINCPUID_API int WinCPUID_GetNumExplicitCaches();WINCPUID_API BOOL WinCPUID_GetExplicitCache(EXPLICITCACHEINFO_T *expCache, int nExpCache); // get 1 cache info at zero-based nExpCacheWINCPUID_API BOOL WinCPUID_GetExplicitCaches(EXPLICITCACHEINFO_T *expCaches, int nExpCaches); // calls WinCPUID_GetExplicitCache nExpCaches times for 0 to nExpCaches-1WINCPUID_API BOOL WinCPUID_GetExpCacheCommonInfo(EXPCACHE_COMMON_T *pECCmn, EXPLICITCACHEINFO_T *pEC);#ifndef WINCPUID_STATIC// Dynamic version checkingWINCPUID_API BOOL WinCPUID_CheckVer(char *ver) { BOOL bRet = TRUE; static char dllVer[] = WINCPUID_VERSION_STR; if (strcmp(dllVer, ver)) bRet = FALSE; return bRet;}BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE;}#endif// Private functionsstatic void GetSpeed(DWORD msTime);static int getLogicalProcessorsPerPackage();static int testHT(CPUINFO_T *pi);static int WinCPUID_getAPIC_ID();static int WinCPUID_getLogicalPerPackage(CPUINFO_T *pi);static int getFeatures8_1(CPUINFO_T *pi);static int getFeatures8_8(CPUINFO_T *pi);// Private Datastatic CPUINFO_T g_WinCPUID_Info = CPUINFO_T_INIT_VAL;// Function ExportsWINCPUID_API int LinCPUID_getCurLogPhysID(CPUINFO_T *pi, unsigned int *pdwLogID, unsigned int *pdwPhysID) { unsigned char APIC_ID; unsigned char LOG_ID; unsigned char PHY_ID; unsigned char PHY_ID_MASK = 0xFF; unsigned char PHY_ID_SHIFT = 0; unsigned char i = 1; while (i < pi->htInfo.nLogicalPerPackage) { i *= 2; PHY_ID_MASK <<= 1; PHY_ID_SHIFT++; } APIC_ID = (unsigned char) WinCPUID_getAPIC_ID(); LOG_ID = APIC_ID & ~PHY_ID_MASK; PHY_ID = APIC_ID >> PHY_ID_SHIFT; *pdwLogID = (unsigned int)LOG_ID; *pdwPhysID = (unsigned int)PHY_ID; return TRUE;}WINCPUID_API int LinCPUID_getCacheStr(char *p, int len, int id) { if ((!p) || (id < 0) || (id > NCACHETYPES)) return FALSE; if (g_WinCPUID_Info.eCPUVendor == VENDOR_INTEL) strncpy(p, g_ci2str[id], len); else if (g_WinCPUID_Info.eCPUVendor == VENDOR_AMD) { if (id < 5) strncpy(p, g_ci2str[id], len); else return FALSE; } else return FALSE; return TRUE;}WINCPUID_API int LinCPUID_getBrandStr(char *p, int len, int id) { if ((!p) || (id < 0) || (id > 255)) return FALSE; strncpy(p, g_bri2str[id], len); return TRUE;}WINCPUID_API int LinCPUID_getBrandStrEx(char *p, int len, CPUCOREINFO_T *info) { if ((!p) || (!info) || (info->dwBrandIndex < 0) || (info->dwBrandIndex > 255)) return FALSE; if ((info->dwCPUFamily == 0x6) && (info->dwCPUModel >= 0x9)) { strncpy(p, "Intel(R) Pentium(R) M Processor", len); } else if ((info->dwCPUFamily == 0xF) && (info->dwCPUModel == 0x1) && (info->dwCPUStepping==0x3)) { if ((info->dwBrandIndex & 0xFFFFFFFE) == 0xE) { strncpy(p, "Intel(R) Xeon(TM) Processor", len); } else if ((info->dwBrandIndex & 0xFFFFFFFE) == 0xB) { strncpy(p, "Intel(R) Xeon(TM) Processor MP", len); } } else { strncpy(p, g_bri2str[info->dwBrandIndex], len); } return TRUE;}WINCPUID_API int LinCPUID_getTypeStr(char *p, int len, int id) { if ((!p) || (id < 0) || (id > 3)) return FALSE; strncpy(p, g_type2str[id], len); return TRUE;}WINCPUID_API int LinCPUID_getHTResultStr(char *p, int len, int id) { if ((!p) || (id < 0) || (id > htAvailable)) return FALSE; strncpy(p, g_htRes2str[id], len); return TRUE;}WINCPUID_API BOOL WinCPUID_PreHTCheck() { BOOL rval = TRUE; HANDLE hCurrentProcessHandle; DWORD_PTR dwProcessAffinity; DWORD_PTR dwSystemAffinity; hCurrentProcessHandle = GetCurrentProcess(); GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity, &dwSystemAffinity); // Application should check this before calling WinCPUID if (dwProcessAffinity != dwSystemAffinity) rval = FALSE; return rval;}static int checkDAZ() { int bRet = 0;#ifndef _M_AMD64// __declspec(align(16)) BYTE fxsrTemp[512]; //gcc extension BYTE __attribute__((aligned(16))) fxsrTemp[512]; DWORD dwtmp;#endif if (g_WinCPUID_Info.bCPUID_Supported && (g_WinCPUID_Info.coreInfo.dwCPUFeatures & FXSR_BIT) && (g_WinCPUID_Info.coreInfo.dwCPUFeatures & (SSE_BIT|SSE2_BIT))) {#ifndef _M_AMD64 // assume EM64T has DAZ ZeroMemory(&fxsrTemp, 512); //__asm fxsave fxsrTemp; __asm__("fxsave %0":"=m"(fxsrTemp)); dwtmp = *(DWORD*)(&fxsrTemp[28]); if (dwtmp == 0) { dwtmp = 0xFFBF; } if (dwtmp & 0x40) { bRet = 1; }#else // DAZ should be available on all 64-bit parts bRet = 1;#endif } return bRet;}static void getAMDExtendedSignature() { DWORD maxb = 0; DWORD extSig; CPUID_ARGS ca; ca.eax = 0x80000000; CPUIDF(&ca); maxb = ca.eax; if (maxb >= 0x80000001) { ca.eax = 0x80000001; CPUIDF(&ca); extSig = ca.edx; g_WinCPUID_Info.coreInfo.dwCPUAMDExtSignature = extSig; }}// TODO: This call is not thread-safe. Remove use of global g_WinCPUID_InfoWINCPUID_API int LinCPUID_Init(int msGetFrequency, CPUINFO_T *pInfo) { int wil_quad_fix = 0; WORD cpu_type = 0; // CPU Family variable DWORD extensions = 0; // CPU Extensions variable DWORD features = 0; // CPU Features variable DWORD maxBrand = 0; DWORD extFeatures = 0; int logProcs = 0; DWORD pscNewECX = 0; int ven; // JS - Flag to determine who is the proc vendor int cpuid_support; // Flag to determine whether // CPUID opcode is // supported int kni_support = FALSE; // Flag to determine whether // Pentium III Instructions are // supported int wil_support = FALSE; //Flag to determine whether //SSE2 Instructions are supported if (!pInfo) { return FALSE; } ZeroMemory(&g_WinCPUID_Info, sizeof(CPUINFO_T));#if 0 if (g_WinCPUID_Info.bIsInitialized) { *pInfo = g_WinCPUID_Info; return TRUE; }#endif // ** Section 1: (Required) First, make sure that cpuid is supported cpuid_support = wincpuidsupport(); g_WinCPUID_Info.bCPUID_Supported = cpuid_support; if (!cpuid_support) { g_WinCPUID_Info.bIsInitialized = 1; return TRUE; } // JS - To determine CPU Vendor ven = wincpuidven(); //printf("wincpuidven ven = %d\n", ven); if (ven == 0) g_WinCPUID_Info.eCPUVendor = VENDOR_INTEL; else if (ven == 1) { g_WinCPUID_Info.eCPUVendor = VENDOR_AMD;#ifdef WINCPUID_INTERNAL g_WinCPUID_init_detect_base = WinCPUID_detect_base();#endif } else g_WinCPUID_Info.eCPUVendor = VENDOR_UNKNOWN; // ** Section 2: (Optional) Finds the cpu type, family, model, and stepping // for genuine Intel processors cpu_type = wincpuid(); // Detect clone, but keep going. Assume clone will not improperly report features, ELP // First clone test if ( cpu_type & CLONE_MASK ) { g_WinCPUID_Info.bCloneFlag = 1; } extensions = wincpuidext(&extFeatures, &pscNewECX); // Second clone test if (extensions & DWCLONE_MASK) { g_WinCPUID_Info.bCloneFlag = 1; } g_WinCPUID_Info.coreInfo.dwCPUType = (extensions>>12) & 0x3; g_WinCPUID_Info.coreInfo.dwCPUFamily = (extensions>>8) & 0xf; g_WinCPUID_Info.coreInfo.dwCPUModel = (extensions>>4) & 0xf; g_WinCPUID_Info.coreInfo.dwCPUStepping = extensions & 0xf; g_WinCPUID_Info.coreInfo.dwCPUExtFamily = (extensions>>20) & 0xff; g_WinCPUID_Info.coreInfo.dwCPUExtModel = (extensions>>16) & 0xf; g_WinCPUID_Info.coreInfo.dwBrandIndex = extFeatures & 0xF; // 7:0 g_WinCPUID_Info.coreInfo.dwCLFlushLineSize = (extFeatures & 0xff00) >> 8; g_WinCPUID_Info.coreInfo.dwCPUExtFeatures = extFeatures; g_WinCPUID_Info.coreInfo.dwCPUPscNewECX = pscNewECX; if (g_WinCPUID_Info.coreInfo.dwCPUFamily >= 6) { // PPro or higher g_WinCPUID_Info.bCMOV_Supported = 1; } // ** Section 3: (Optional) Detects speed of the processor // [pyw] check features here to determine if wmt processor is present // if so, scale cpu frequency appropriately features = wincpufeatures(); g_WinCPUID_Info.coreInfo.dwCPUFeatures = features; getAMDExtendedSignature(); wil_support = winwilsupport(); if ((features & 0x04000000) && (wil_support==TRUE)) wil_quad_fix = 1; if ( features & 0x00000010 ) { g_WinCPUID_Info.bRDTSC_Supported = 1; if (msGetFrequency) GetSpeed(msGetFrequency); // updates g_WinCPUID_Info.llCPUFreq } else { g_WinCPUID_Info.llCPUFreq = -1; // flag error } // ** Section 4: (Optional) Finds special features for genuine Intel processors. // Currently tests for Pentium III Instructions, MMX technology, and SSE2 Instructions //Print extra line in message for MMX(TM) technology processor, ie, features(23)=1 if (features & 0x00800000) g_WinCPUID_Info.bMMX_Supported = 1; //Print extra line in message for Pentium III Instruction support, ie, features(25)=1 if (features & 0x02000000) { // Test first for Pentium III support bit // Need to run a special test to make sure the whole system // supports Pentium III Instructions kni_support = winknisupport(); if (kni_support) { g_WinCPUID_Info.bSSE_Supported = 1; g_WinCPUID_Info.bSSEMMXExt_Supported = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -