llprocessor.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:90k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llprocessor.cpp
  3.  * @brief Code to figure out the processor. Originally by Benjamin Jurke.
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. // Filename: Processor.cpp
  33. // =======================
  34. // Author: Benjamin Jurke
  35. // File history: 27.02.2002  - File created. Support for Intel and AMD processors
  36. //               05.03.2002  - Fixed the CPUID bug: On Pre-Pentium CPUs the CPUID
  37. //                             command is not available
  38. //                           - The CProcessor::WriteInfoTextFile function do not 
  39. //                             longer use Win32 file functions (-> os independend)
  40. //                           - Optional include of the windows.h header which is
  41. //                             still need for CProcessor::GetCPUFrequency.
  42. //               06.03.2002  - My birthday (18th :-))
  43. //                           - Replaced the 'rn' line endings in function 
  44. //                             CProcessor::CPUInfoToText by 'n'
  45. //                           - Replaced unsigned __int64 by signed __int64 for
  46. //                             solving some compiler conversion problems
  47. //                           - Fixed a bug at family=6, model=6 (Celeron -> P2)
  48. //////////////////////////////////////////////////////////////////////////////////
  49. #include "linden_common.h"
  50. #include "processor.h"
  51. #include <memory>
  52. #if LL_WINDOWS
  53. # define WIN32_LEAN_AND_MEAN
  54. # include <winsock2.h>
  55. # include <windows.h>
  56. #endif
  57. #if !LL_DARWIN && !LL_SOLARIS
  58. #ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
  59. // We need the QueryPerformanceCounter and Sleep functions
  60. #define FORCEINLINE __forceinline
  61. #else
  62. #define FORCEINLINE 
  63. #endif
  64. // Some macros we often need
  65. ////////////////////////////
  66. #define CheckBit(var, bit)   ((var & (1 << bit)) ? true : false)
  67. #ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
  68. // Delays for the specified amount of milliseconds
  69. static void _Delay(unsigned int ms)
  70. {
  71.    LARGE_INTEGER freq, c1, c2;
  72. __int64 x;
  73.    // Get High-Res Timer frequency
  74. if (!QueryPerformanceFrequency(&freq))
  75. return;
  76. // Convert ms to High-Res Timer value
  77. x = freq.QuadPart/1000*ms;
  78.    // Get first snapshot of High-Res Timer value
  79. QueryPerformanceCounter(&c1);
  80. do
  81. {
  82.             // Get second snapshot
  83.     QueryPerformanceCounter(&c2);
  84. }while(c2.QuadPart-c1.QuadPart < x);
  85. // Loop while (second-first < x)
  86. }
  87. #endif
  88. // CProcessor::CProcessor
  89. // ======================
  90. // Class constructor:
  91. /////////////////////////
  92. CProcessor::CProcessor()
  93. {
  94. uqwFrequency = 0;
  95. strCPUName[0] = 0;
  96. memset(&CPUInfo, 0, sizeof(CPUInfo));
  97. }
  98. // unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
  99. // =========================================================================
  100. // Function to measure the current CPU frequency
  101. ////////////////////////////////////////////////////////////////////////////
  102. F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
  103. {
  104. #ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
  105. return 0;
  106. #else
  107. // If there are invalid measure time parameters, zero msecs for example,
  108. // we've to exit the function
  109. if (uiMeasureMSecs < 1)
  110. {
  111. // If theres already a measured frequency available, we return it
  112.         if (uqwFrequency > 0)
  113. return uqwFrequency;
  114. else
  115. return 0;
  116. }
  117. // Now we check if the CPUID command is available
  118. if (!CheckCPUIDPresence())
  119. return 0;
  120. // First we get the CPUID standard level 0x00000001
  121. unsigned long reg;
  122. __asm
  123. {
  124. mov eax, 1
  125.         cpuid
  126. mov reg, edx
  127. }
  128. // Then we check, if the RDTSC (Real Date Time Stamp Counter) is available.
  129. // This function is necessary for our measure process.
  130. if (!(reg & (1 << 4)))
  131. return 0;
  132. // After that we declare some vars and check the frequency of the high
  133. // resolution timer for the measure process.
  134. // If there's no high-res timer, we exit.
  135. __int64 starttime, endtime, timedif, freq, start, end, dif;
  136. if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq))
  137. return 0;
  138. // Now we can init the measure process. We set the process and thread priority
  139. // to the highest available level (Realtime priority). Also we focus the
  140. // first processor in the multiprocessor system.
  141. HANDLE hProcess = GetCurrentProcess();
  142. HANDLE hThread = GetCurrentThread();
  143. unsigned long dwCurPriorityClass = GetPriorityClass(hProcess);
  144. int iCurThreadPriority = GetThreadPriority(hThread);
  145. unsigned long dwProcessMask, dwSystemMask, dwNewMask = 1;
  146. GetProcessAffinityMask(hProcess, &dwProcessMask, &dwSystemMask);
  147. SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
  148. SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
  149. SetProcessAffinityMask(hProcess, dwNewMask);
  150. // Now we call a CPUID to ensure, that all other prior called functions are
  151. // completed now (serialization)
  152. __asm cpuid
  153. // We ask the high-res timer for the start time
  154. QueryPerformanceCounter((LARGE_INTEGER *) &starttime);
  155. // Then we get the current cpu clock and store it
  156. __asm 
  157. {
  158. rdtsc
  159. mov dword ptr [start+4], edx
  160. mov dword ptr [start], eax
  161. }
  162. // Now we wart for some msecs
  163. _Delay(uiMeasureMSecs);
  164. // Sleep(uiMeasureMSecs);
  165. // We ask for the end time
  166. QueryPerformanceCounter((LARGE_INTEGER *) &endtime);
  167. // And also for the end cpu clock
  168. __asm 
  169. {
  170. rdtsc
  171. mov dword ptr [end+4], edx
  172. mov dword ptr [end], eax
  173. }
  174. // Now we can restore the default process and thread priorities
  175. SetProcessAffinityMask(hProcess, dwProcessMask);
  176. SetThreadPriority(hThread, iCurThreadPriority);
  177. SetPriorityClass(hProcess, dwCurPriorityClass);
  178. // Then we calculate the time and clock differences
  179. dif = end - start;
  180. timedif = endtime - starttime;
  181. // And finally the frequency is the clock difference divided by the time
  182. // difference. 
  183. uqwFrequency = (F64)dif / (((F64)timedif) / freq);
  184. // At last we just return the frequency that is also stored in the call
  185. // member var uqwFrequency
  186. return uqwFrequency;
  187. #endif
  188. }
  189. // bool CProcessor::AnalyzeIntelProcessor()
  190. // ========================================
  191. // Private class function for analyzing an Intel processor
  192. //////////////////////////////////////////////////////////
  193. bool CProcessor::AnalyzeIntelProcessor()
  194. {
  195. #if LL_WINDOWS
  196. unsigned long eaxreg, ebxreg, edxreg;
  197. // First we check if the CPUID command is available
  198. if (!CheckCPUIDPresence())
  199. return false;
  200. // Now we get the CPUID standard level 0x00000001
  201. __asm
  202. {
  203. mov eax, 1
  204. cpuid
  205. mov eaxreg, eax
  206. mov ebxreg, ebx
  207. mov edxreg, edx
  208. }
  209.     
  210. // Then get the cpu model, family, type, stepping and brand id by masking
  211. // the eax and ebx register
  212. CPUInfo.uiStepping = eaxreg & 0xF;
  213. CPUInfo.uiModel    = (eaxreg >> 4) & 0xF;
  214. CPUInfo.uiFamily   = (eaxreg >> 8) & 0xF;
  215. CPUInfo.uiType     = (eaxreg >> 12) & 0x3;
  216. CPUInfo.uiBrandID  = ebxreg & 0xF;
  217. static const char* INTEL_BRAND[] =
  218. {
  219. /* 0x00 */ "",
  220. /* 0x01 */ "0.18 micron Intel Celeron",
  221. /* 0x02 */ "0.18 micron Intel Pentium III",
  222. /* 0x03 */ "0.13 micron Intel Celeron",
  223. /* 0x04 */ "0.13 micron Intel Pentium III",
  224. /* 0x05 */ "",
  225. /* 0x06 */ "0.13 micron Intel Pentium III Mobile",
  226. /* 0x07 */ "0.13 micron Intel Celeron Mobile",
  227. /* 0x08 */ "0.18 micron Intel Pentium 4",
  228. /* 0x09 */ "0.13 micron Intel Pentium 4",
  229. /* 0x0A */ "0.13 micron Intel Celeron",
  230. /* 0x0B */ "0.13 micron Intel Pentium 4 Xeon",
  231. /* 0x0C */ "Intel Xeon MP",
  232. /* 0x0D */ "",
  233. /* 0x0E */ "0.18 micron Intel Pentium 4 Xeon",
  234. /* 0x0F */ "Mobile Intel Celeron",
  235. /* 0x10 */ "",
  236. /* 0x11 */ "Mobile Genuine Intel",
  237. /* 0x12 */ "Intel Celeron M",
  238. /* 0x13 */ "Mobile Intel Celeron",
  239. /* 0x14 */ "Intel Celeron",
  240. /* 0x15 */ "Mobile Genuine Intel",
  241. /* 0x16 */ "Intel Pentium M",
  242. /* 0x17 */ "Mobile Intel Celeron",
  243. };
  244. // Only override the brand if we have it in the lookup table.  We should
  245. // already have a string here from GetCPUInfo().  JC
  246. if ( CPUInfo.uiBrandID < LL_ARRAY_SIZE(INTEL_BRAND) )
  247. {
  248. strncpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID], sizeof(CPUInfo.strBrandID)-1);
  249. CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='';
  250. if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6)
  251. {
  252. strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon");
  253. }
  254. }
  255. // Then we translate the cpu family
  256.     switch (CPUInfo.uiFamily)
  257. {
  258. case 3: // Family = 3:  i386 (80386) processor family
  259. strcpy(CPUInfo.strFamily, "Intel i386"); /* Flawfinder: ignore */
  260. break;
  261. case 4: // Family = 4:  i486 (80486) processor family
  262. strcpy(CPUInfo.strFamily, "Intel i486"); /* Flawfinder: ignore */
  263. break;
  264. case 5: // Family = 5:  Pentium (80586) processor family
  265. strcpy(CPUInfo.strFamily, "Intel Pentium"); /* Flawfinder: ignore */
  266. break;
  267. case 6: // Family = 6:  Pentium Pro (80686) processor family
  268. strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core"); /* Flawfinder: ignore */
  269. break;
  270. case 15: // Family = 15:  Extended family specific
  271. // Masking the extended family
  272. CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF;
  273. switch (CPUInfo.uiExtendedFamily)
  274. {
  275. case 0: // Family = 15, Ext. Family = 0:  Pentium 4 (80786 ??) processor family
  276. strcpy(CPUInfo.strFamily, "Intel Pentium 4"); /* Flawfinder: ignore */
  277. break;
  278. case 1: // Family = 15, Ext. Family = 1:  McKinley (64-bit) processor family
  279. strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)"); /* Flawfinder: ignore */
  280. break;
  281. default: // Sure is sure
  282. strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+"); /* Flawfinder: ignore */
  283. break;
  284. }
  285. break;
  286. default: // Failsave
  287. strcpy(CPUInfo.strFamily, "Unknown"); /* Flawfinder: ignore */
  288. break;
  289.     }
  290. // Now we come to the big deal, the exact model name
  291. switch (CPUInfo.uiFamily)
  292. {
  293. case 3: // i386 (80386) processor family
  294. strcpy(CPUInfo.strModel, "Unknown Intel i386"); /* Flawfinder: ignore */
  295. strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  296. break;
  297. case 4: // i486 (80486) processor family
  298. switch (CPUInfo.uiModel)
  299. {
  300. case 0: // Model = 0:  i486 DX-25/33 processor model
  301. strcpy(CPUInfo.strModel, "Intel i486 DX-25/33"); /* Flawfinder: ignore */
  302. strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  303. break;
  304. case 1: // Model = 1:  i486 DX-50 processor model
  305. strcpy(CPUInfo.strModel, "Intel i486 DX-50"); /* Flawfinder: ignore */
  306. strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  307. break;
  308. case 2: // Model = 2:  i486 SX processor model
  309. strcpy(CPUInfo.strModel, "Intel i486 SX"); /* Flawfinder: ignore */
  310. strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  311. break;
  312. case 3: // Model = 3:  i486 DX2 (with i487 numeric coprocessor) processor model
  313. strcpy(CPUInfo.strModel, "Intel i486 487/DX2"); /* Flawfinder: ignore */
  314. strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  315. break;
  316. case 4: // Model = 4:  i486 SL processor model (never heard ?!?)
  317. strcpy(CPUInfo.strModel, "Intel i486 SL"); /* Flawfinder: ignore */
  318. strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  319. break;
  320. case 5: // Model = 5:  i486 SX2 processor model
  321. strcpy(CPUInfo.strModel, "Intel i486 SX2"); /* Flawfinder: ignore */
  322. strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  323. break;
  324. case 7: // Model = 7:  i486 write-back enhanced DX2 processor model
  325. strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2"); /* Flawfinder: ignore */
  326. strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  327. break;
  328. case 8: // Model = 8:  i486 DX4 processor model
  329. strcpy(CPUInfo.strModel, "Intel i486 DX4"); /* Flawfinder: ignore */
  330. strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  331. break;
  332. case 9: // Model = 9:  i486 write-back enhanced DX4 processor model
  333. strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4"); /* Flawfinder: ignore */
  334. strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  335. break;
  336. default: // ...
  337. strcpy(CPUInfo.strModel, "Unknown Intel i486"); /* Flawfinder: ignore */
  338. strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  339. break;
  340. }
  341. break;
  342. case 5: // Pentium (80586) processor family
  343. switch (CPUInfo.uiModel)
  344. {
  345. case 0: // Model = 0:  Pentium (P5 A-Step) processor model
  346. strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)"); /* Flawfinder: ignore */
  347. strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  348. break; // Famous for the DIV bug, as far as I know
  349. case 1: // Model = 1:  Pentium 60/66 processor model
  350. strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)"); /* Flawfinder: ignore */
  351. strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  352. break;
  353. case 2: // Model = 2:  Pentium 75-200 (P54C) processor model
  354. strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)"); /* Flawfinder: ignore */
  355. strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  356. break;
  357. case 3: // Model = 3:  Pentium overdrive for 486 systems processor model
  358. strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)"); /* Flawfinder: ignore */
  359. strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  360. break;
  361. case 4: // Model = 4:  Pentium MMX processor model
  362. strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)"); /*Flawfinder: ignore*/
  363. strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  364. break;
  365. case 7: // Model = 7:  Pentium processor model (don't know difference to Model=2)
  366. strcpy(CPUInfo.strModel, "Intel Pentium (P54C)"); /*Flawfinder: ignore*/
  367. strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  368. break;
  369. case 8: // Model = 8:  Pentium MMX (0.25 micron) processor model
  370. strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron"); /*Flawfinder: ignore*/
  371. strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  372. break;
  373. default: // ...
  374. strcpy(CPUInfo.strModel, "Unknown Intel Pentium"); /*Flawfinder: ignore*/
  375. strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  376. break;
  377. }
  378. break;
  379. case 6: // Pentium Pro (80686) processor family
  380. switch (CPUInfo.uiModel)
  381. {
  382. case 0: // Model = 0:  Pentium Pro (P6 A-Step) processor model
  383. strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)"); /*Flawfinder: ignore*/
  384. strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  385. break;
  386. case 1: // Model = 1:  Pentium Pro
  387. strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)"); /*Flawfinder: ignore*/
  388. strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  389. break;
  390. case 3: // Model = 3:  Pentium II (66 MHz FSB, I think) processor model
  391. strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron"); /*Flawfinder: ignore*/
  392. strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  393. break;
  394. case 5: // Model = 5:  Pentium II/Xeon/Celeron (0.25 micron) processor model
  395. strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron"); /*Flawfinder: ignore*/
  396. strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  397. break;
  398. case 6: // Model = 6:  Pentium II with internal L2 cache
  399. strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache"); /*Flawfinder: ignore*/
  400. strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  401. break;
  402. case 7: // Model = 7:  Pentium III/Xeon (extern L2 cache) processor model
  403. strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron");  /*Flawfinder: ignore*/
  404. strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  405. break;
  406. case 8: // Model = 8:  Pentium III/Xeon/Celeron (256 KB on-die L2 cache) processor model
  407. strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");  /*Flawfinder: ignore*/
  408. // We want to know it exactly:
  409. switch (CPUInfo.uiBrandID)
  410. {
  411. case 1: // Model = 8, Brand id = 1:  Celeron (on-die L2 cache) processor model
  412. strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  413. break;
  414.                         case 2: // Model = 8, Brand id = 2:  Pentium III (on-die L2 cache) processor model (my current cpu :-))
  415. strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  416. break;
  417. case 3: // Model = 8, Brand id = 3:  Pentium III Xeon (on-die L2 cache) processor model
  418.                             strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  419. break;
  420. default: // ...
  421. strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  422. break;
  423. }
  424. break;
  425. case 9: // Model = 9:  Intel Pentium M processor, Intel Celeron M processor, model 9
  426. strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");  /*Flawfinder: ignore*/
  427. strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  428. break;
  429. case 0xA: // Model = 0xA:  Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model
  430. strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");  /*Flawfinder: ignore*/
  431. // Exact detection:
  432. switch (CPUInfo.uiBrandID)
  433. {
  434. case 1: // Model = 0xA, Brand id = 1:  Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model
  435. strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  436. break;
  437.                         case 2: // Model = 0xA, Brand id = 2:  Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model
  438. strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  439. break;
  440. case 3: // Model = 0xA, Brand id = 3:  Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model
  441.                             strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  442. break;
  443. default: // Getting bored of this............
  444. strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  445. break;
  446. }
  447. break;
  448. case 0xB: // Model = 0xB: Pentium III/Xeon/Celeron (Tualatin core, on-die cache) processor model
  449. strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron");  /*Flawfinder: ignore*/
  450. // Omniscient: ;-)
  451. switch (CPUInfo.uiBrandID)
  452. {
  453. case 3: // Model = 0xB, Brand id = 3:  Celeron (Tualatin core) processor model
  454. strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  455. break;
  456.                         case 4: // Model = 0xB, Brand id = 4:  Pentium III (Tualatin core) processor model
  457. strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  458. break;
  459. case 7: // Model = 0xB, Brand id = 7:  Celeron mobile (Tualatin core) processor model
  460.                             strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  461. break;
  462. default: // *bored*
  463. strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  464. break;
  465. }
  466. break;
  467. case 0xD: // Model = 0xD:  Intel Pentium M processor, Intel Celeron M processor, model D
  468. strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");  /*Flawfinder: ignore*/
  469. strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  470. break;
  471. case 0xE: // Model = 0xE:  Intel Core Duo processor, Intel Core Solo processor, model E
  472. strcpy(CPUInfo.strModel, "Intel Core Series Processor");  /*Flawfinder: ignore*/
  473. strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  474. break;
  475. case 0xF: // Model = 0xF:  Intel Core 2 Duo processor, model F
  476. strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor");  /*Flawfinder: ignore*/
  477. strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  478. break;
  479. default: // *more bored*
  480. strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/
  481. strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  482. break;
  483. }
  484. break;
  485. case 15: // Extended processor family
  486. // Masking the extended model
  487. CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF;
  488. switch (CPUInfo.uiModel)
  489. {
  490. case 0: // Model = 0:  Pentium 4 Willamette (A-Step) core
  491. if ((CPUInfo.uiBrandID) == 8) // Brand id = 8:  P4 Willamette
  492. {
  493. strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)"); /*Flawfinder: ignore*/
  494. strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
  495. }
  496. else // else Xeon
  497. {
  498. strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)"); /* Flawfinder: ignore */
  499. strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
  500. }
  501. break;
  502. case 1: // Model = 1:  Pentium 4 Willamette core
  503. if ((CPUInfo.uiBrandID) == 8) // Brand id = 8:  P4 Willamette
  504. {
  505. strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette"); /* Flawfinder: ignore */
  506. strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
  507. }
  508. else // else Xeon
  509. {
  510. strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon"); /* Flawfinder: ignore */
  511. strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
  512. }
  513. break;
  514. case 2: // Model = 2:  Pentium 4 Northwood core
  515. if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA)) // P4 Willamette
  516. {
  517. strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood"); /* Flawfinder: ignore */
  518. strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
  519. }
  520. else // Xeon
  521. {
  522. strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon"); /* Flawfinder: ignore */
  523. strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
  524. }
  525. break;
  526. default: // Silly stupid never used failsave option
  527. strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4"); /* Flawfinder: ignore */
  528. strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
  529. break;
  530. }
  531. break;
  532. default: // *grmpf*
  533. strcpy(CPUInfo.strModel, "Unknown Intel model"); /* Flawfinder: ignore */
  534. strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
  535. break;
  536.     }
  537. // After the long processor model block we now come to the processors serial
  538. // number.
  539. // First of all we check if the processor supports the serial number
  540. if (CPUInfo.MaxSupportedLevel >= 3)
  541. {
  542. // If it supports the serial number CPUID level 0x00000003 we read the data
  543. unsigned long sig1, sig2, sig3;
  544. __asm
  545. {
  546. mov eax, 1
  547. cpuid
  548. mov sig1, eax
  549. mov eax, 3
  550. cpuid
  551. mov sig2, ecx
  552. mov sig3, edx
  553. }
  554. // Then we convert the data to a readable string
  555. snprintf( /* Flawfinder: ignore */
  556. CPUInfo.strProcessorSerial,
  557. sizeof(CPUInfo.strProcessorSerial),
  558. "%04lX-%04lX-%04lX-%04lX-%04lX-%04lX",
  559. sig1 >> 16,
  560. sig1 & 0xFFFF,
  561. sig3 >> 16,
  562. sig3 & 0xFFFF,
  563. sig2 >> 16, sig2 & 0xFFFF);
  564. }
  565. else
  566. {
  567. // If there's no serial number support we just put "No serial number"
  568. snprintf( /* Flawfinder: ignore */
  569. CPUInfo.strProcessorSerial,
  570. sizeof(CPUInfo.strProcessorSerial),
  571. "No Processor Serial Number");
  572. }
  573. // Now we get the standard processor extensions
  574. GetStandardProcessorExtensions();
  575. // And finally the processor configuration (caches, TLBs, ...) and translate
  576. // the data to readable strings
  577. GetStandardProcessorConfiguration();
  578. TranslateProcessorConfiguration();
  579. // At last...
  580. return true;
  581. #else
  582. return FALSE;
  583. #endif
  584. }
  585. // bool CProcessor::AnalyzeAMDProcessor()
  586. // ======================================
  587. // Private class function for analyzing an AMD processor
  588. ////////////////////////////////////////////////////////
  589. bool CProcessor::AnalyzeAMDProcessor()
  590. {
  591. #if LL_WINDOWS
  592. unsigned long eaxreg, ebxreg, ecxreg, edxreg;
  593. // First of all we check if the CPUID command is available
  594. if (!CheckCPUIDPresence())
  595. return 0;
  596. // Now we get the CPUID standard level 0x00000001
  597. __asm
  598. {
  599. mov eax, 1
  600. cpuid
  601. mov eaxreg, eax
  602. mov ebxreg, ebx
  603. mov edxreg, edx
  604. }
  605.     
  606. // Then we mask the model, family, stepping and type (AMD does not support brand id)
  607. CPUInfo.uiStepping = eaxreg & 0xF;
  608. CPUInfo.uiModel    = (eaxreg >> 4) & 0xF;
  609. CPUInfo.uiFamily   = (eaxreg >> 8) & 0xF;
  610. CPUInfo.uiType     = (eaxreg >> 12) & 0x3;
  611. // Now we check if the processor supports the brand id string extended CPUID level
  612. if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004)
  613. {
  614. // If it supports the extended CPUID level 0x80000004 we read the data
  615. char tmp[52]; /* Flawfinder: ignore */
  616. memset(tmp, 0, sizeof(tmp));
  617.         __asm
  618. {
  619. mov eax, 0x80000002
  620. cpuid
  621. mov dword ptr [tmp], eax
  622. mov dword ptr [tmp+4], ebx
  623. mov dword ptr [tmp+8], ecx
  624. mov dword ptr [tmp+12], edx
  625. mov eax, 0x80000003
  626. cpuid
  627. mov dword ptr [tmp+16], eax
  628. mov dword ptr [tmp+20], ebx
  629. mov dword ptr [tmp+24], ecx
  630. mov dword ptr [tmp+28], edx
  631. mov eax, 0x80000004
  632. cpuid
  633. mov dword ptr [tmp+32], eax
  634. mov dword ptr [tmp+36], ebx
  635. mov dword ptr [tmp+40], ecx
  636. mov dword ptr [tmp+44], edx
  637. }
  638. // And copy it to the brand id string
  639. strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1);
  640. CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='';
  641. }
  642. else
  643. {
  644. // Or just tell there is no brand id string support
  645. strcpy(CPUInfo.strBrandID, ""); /* Flawfinder: ignore */
  646. }
  647. // After that we translate the processor family
  648.     switch(CPUInfo.uiFamily)
  649. {
  650. case 4: // Family = 4:  486 (80486) or 5x86 (80486) processor family
  651. switch (CPUInfo.uiModel)
  652. {
  653. case 3: // Thanks to AMD for this nice form of family
  654. case 7: // detection.... *grmpf*
  655. case 8:
  656. case 9:
  657. strcpy(CPUInfo.strFamily, "AMD 80486"); /* Flawfinder: ignore */
  658. break;
  659. case 0xE:
  660. case 0xF:
  661. strcpy(CPUInfo.strFamily, "AMD 5x86"); /* Flawfinder: ignore */
  662. break;
  663. default:
  664. strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */
  665. break;
  666. }
  667. break;
  668. case 5: // Family = 5:  K5 or K6 processor family
  669. switch (CPUInfo.uiModel)
  670. {
  671. case 0:
  672. case 1:
  673. case 2:
  674. case 3:
  675. strcpy(CPUInfo.strFamily, "AMD K5"); /* Flawfinder: ignore */
  676. break;
  677. case 6:
  678. case 7:
  679. case 8:
  680. case 9:
  681. strcpy(CPUInfo.strFamily, "AMD K6"); /* Flawfinder: ignore */
  682. break;
  683. default:
  684. strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */
  685. break;
  686. }
  687. break;
  688. case 6: // Family = 6:  K7 (Athlon, ...) processor family
  689. strcpy(CPUInfo.strFamily, "AMD K7"); /* Flawfinder: ignore */
  690. break;
  691. default: // For security
  692. strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */
  693. break;
  694. }
  695. // After the family detection we come to the specific processor model
  696. // detection
  697. switch (CPUInfo.uiFamily)
  698. {
  699. case 4: // Family = 4:  486 (80486) or 5x85 (80486) processor family
  700. switch (CPUInfo.uiModel)
  701. {
  702. case 3: // Model = 3:  80486 DX2
  703. strcpy(CPUInfo.strModel, "AMD 80486 DX2"); /* Flawfinder: ignore */
  704. strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  705. break;
  706. case 7: // Model = 7:  80486 write-back enhanced DX2
  707. strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2"); /* Flawfinder: ignore */
  708. strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  709. break;
  710. case 8: // Model = 8:  80486 DX4
  711. strcpy(CPUInfo.strModel, "AMD 80486 DX4"); /* Flawfinder: ignore */
  712. strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  713. break;
  714. case 9: // Model = 9:  80486 write-back enhanced DX4
  715. strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4"); /* Flawfinder: ignore */
  716. strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  717. break;
  718. case 0xE: // Model = 0xE:  5x86
  719. strcpy(CPUInfo.strModel, "AMD 5x86"); /* Flawfinder: ignore */
  720. strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  721. break;
  722. case 0xF: // Model = 0xF:  5x86 write-back enhanced (oh my god.....)
  723. strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced"); /* Flawfinder: ignore */
  724. strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  725. break;
  726. default: // ...
  727. strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model"); /* Flawfinder: ignore */
  728. strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  729. break;
  730. }
  731. break;
  732. case 5: // Family = 5:  K5 / K6 processor family
  733. switch (CPUInfo.uiModel)
  734. {
  735. case 0: // Model = 0:  K5 SSA 5 (Pentium Rating *ggg* 75, 90 and 100 Mhz)
  736. strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)"); /* Flawfinder: ignore */
  737. strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  738. break;
  739. case 1: // Model = 1:  K5 5k86 (PR 120 and 133 MHz)
  740. strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)"); /* Flawfinder: ignore */
  741. strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  742. break;
  743. case 2: // Model = 2:  K5 5k86 (PR 166 MHz)
  744. strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)"); /* Flawfinder: ignore */
  745. strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  746. break;
  747. case 3: // Model = 3:  K5 5k86 (PR 200 MHz)
  748. strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)"); /* Flawfinder: ignore */
  749. strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  750. break;
  751. case 6: // Model = 6:  K6
  752. strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)"); /* Flawfinder: ignore */
  753. strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  754. break;
  755. case 7: // Model = 7:  K6 (0.25 micron)
  756. strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)"); /* Flawfinder: ignore */
  757. strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  758. break;
  759. case 8: // Model = 8:  K6-2
  760. strcpy(CPUInfo.strModel, "AMD K6-2"); /* Flawfinder: ignore */
  761. strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  762. break;
  763. case 9: // Model = 9:  K6-III
  764. strcpy(CPUInfo.strModel, "AMD K6-III"); /* Flawfinder: ignore */
  765. strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  766. break;
  767. case 0xD: // Model = 0xD:  K6-2+ / K6-III+
  768. strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)"); /* Flawfinder: ignore */
  769. strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  770. break;
  771. default: // ...
  772. strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model"); /* Flawfinder: ignore */
  773. strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  774. break;
  775. }
  776. break;
  777. case 6: // Family = 6:  K7 processor family (AMDs first good processors)
  778. switch (CPUInfo.uiModel)
  779. {
  780. case 1: // Athlon
  781. strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)"); /* Flawfinder: ignore */
  782. strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  783. break;
  784. case 2: // Athlon (0.18 micron)
  785. strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)"); /* Flawfinder: ignore */
  786. strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  787. break;
  788. case 3: // Duron (Spitfire core)
  789. strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)"); /* Flawfinder: ignore */
  790. strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  791. break;
  792. case 4: // Athlon (Thunderbird core)
  793. strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)"); /* Flawfinder: ignore */
  794. strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  795. break;
  796. case 6: // Athlon MP / Mobile Athlon (Palomino core)
  797. strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)"); /* Flawfinder: ignore */
  798. strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  799. break;
  800. case 7: // Mobile Duron (Morgan core)
  801. strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)"); /* Flawfinder: ignore */
  802. strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  803. break;
  804. default: // ...
  805. strcpy(CPUInfo.strModel, "Unknown AMD K7 model"); /* Flawfinder: ignore */
  806. strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  807. break;
  808. }
  809. break;
  810. default: // ...
  811. strcpy(CPUInfo.strModel, "Unknown AMD model"); /* Flawfinder: ignore */
  812. strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
  813. break;
  814.     }
  815. // Now we read the standard processor extension that are stored in the same
  816. // way the Intel standard extensions are
  817. GetStandardProcessorExtensions();
  818. // Then we check if theres an extended CPUID level support
  819. if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001)
  820. {
  821. // If we can access the extended CPUID level 0x80000001 we get the
  822. // edx register
  823. __asm
  824. {
  825. mov eax, 0x80000001
  826. cpuid
  827. mov edxreg, edx
  828. }
  829. // Now we can mask some AMD specific cpu extensions
  830. CPUInfo._Ext.EMMX_MultimediaExtensions = CheckBit(edxreg, 22);
  831. CPUInfo._Ext.AA64_AMD64BitArchitecture = CheckBit(edxreg, 29);
  832. CPUInfo._Ext._E3DNOW_InstructionExtensions = CheckBit(edxreg, 30);
  833. CPUInfo._Ext._3DNOW_InstructionExtensions = CheckBit(edxreg, 31);
  834. }
  835. // After that we check if the processor supports the ext. CPUID level
  836. // 0x80000006
  837. if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006)
  838. {
  839. // If it's present, we read it out
  840.         __asm
  841. {
  842.             mov eax, 0x80000005
  843. cpuid
  844. mov eaxreg, eax
  845. mov ebxreg, ebx
  846. mov ecxreg, ecx
  847. mov edxreg, edx
  848. }
  849. // Then we mask the L1 Data TLB information
  850. if ((ebxreg >> 16) && (eaxreg >> 16))
  851. {
  852. CPUInfo._Data.bPresent = true;
  853. strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB");  /*Flawfinder: ignore*/
  854. CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
  855. CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
  856. }
  857. else if (eaxreg >> 16)
  858. {
  859. CPUInfo._Data.bPresent = true;
  860. strcpy(CPUInfo._Data.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/
  861. CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
  862. CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
  863. }
  864. else if (ebxreg >> 16)
  865. {
  866. CPUInfo._Data.bPresent = true;
  867. strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/
  868. CPUInfo._Data.uiAssociativeWays = (ebxreg >> 24) & 0xFF;
  869. CPUInfo._Data.uiEntries = (ebxreg >> 16) & 0xFF;
  870. }
  871. if (CPUInfo._Data.uiAssociativeWays == 0xFF)
  872. CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
  873. // Now the L1 Instruction/Code TLB information
  874. if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF))
  875. {
  876. CPUInfo._Instruction.bPresent = true;
  877. strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/
  878. CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
  879. CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
  880. }
  881. else if (eaxreg & 0xFFFF)
  882. {
  883. CPUInfo._Instruction.bPresent = true;
  884. strcpy(CPUInfo._Instruction.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/
  885. CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
  886. CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
  887. }
  888. else if (ebxreg & 0xFFFF)
  889. {
  890. CPUInfo._Instruction.bPresent = true;
  891. strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/
  892. CPUInfo._Instruction.uiAssociativeWays = (ebxreg >> 8) & 0xFF;
  893. CPUInfo._Instruction.uiEntries = ebxreg & 0xFF;
  894. }
  895. if (CPUInfo._Instruction.uiAssociativeWays == 0xFF)
  896. CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
  897. // Then we read the L1 data cache information
  898. if ((ecxreg >> 24) > 0)
  899. {
  900. CPUInfo._L1.Data.bPresent = true;
  901. snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", ecxreg >> 24); /* Flawfinder: ignore */
  902. CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF;
  903. CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF;
  904. }
  905. // After that we read the L2 instruction/code cache information
  906. if ((edxreg >> 24) > 0)
  907. {
  908. CPUInfo._L1.Instruction.bPresent = true;
  909. snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", edxreg >> 24);  /* Flawfinder: ignore */
  910. CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF;
  911. CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF;
  912. }
  913. // Note: I'm not absolutely sure that the L1 page size code (the
  914. // 'if/else if/else if' structs above) really detects the real page
  915. // size for the TLB. Somebody should check it....
  916. // Now we read the ext. CPUID level 0x80000006
  917.         __asm
  918. {
  919. mov eax, 0x80000006
  920. cpuid
  921. mov eaxreg, eax
  922. mov ebxreg, ebx
  923. mov ecxreg, ecx
  924. }
  925. // We only mask the unified L2 cache masks (never heard of an
  926. // L2 cache that is divided in data and code parts)
  927. if (((ecxreg >> 12) & 0xF) > 0)
  928. {
  929. CPUInfo._L2.bPresent = true;
  930. snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16); /* Flawfinder: ignore */
  931. switch ((ecxreg >> 12) & 0xF)
  932. {
  933. case 1:
  934. CPUInfo._L2.uiAssociativeWays = 1;
  935. break;
  936. case 2:
  937. CPUInfo._L2.uiAssociativeWays = 2;
  938. break;
  939. case 4:
  940. CPUInfo._L2.uiAssociativeWays = 4;
  941. break;
  942. case 6:
  943. CPUInfo._L2.uiAssociativeWays = 8;
  944. break;
  945. case 8:
  946. CPUInfo._L2.uiAssociativeWays = 16;
  947. break;
  948. case 0xF:
  949. CPUInfo._L2.uiAssociativeWays = (unsigned int) -1;
  950. break;
  951. default:
  952. CPUInfo._L2.uiAssociativeWays = 0;
  953. break;
  954. }
  955. CPUInfo._L2.uiLineSize = ecxreg & 0xFF;
  956. }
  957. }
  958. else
  959. {
  960. // If we could not detect the ext. CPUID level 0x80000006 we
  961. // try to read the standard processor configuration.
  962. GetStandardProcessorConfiguration();
  963. }
  964. // After reading we translate the configuration to strings
  965. TranslateProcessorConfiguration();
  966. // And finally exit
  967. return true;
  968. #else
  969. return FALSE;
  970. #endif
  971. }
  972. // bool CProcessor::AnalyzeUnknownProcessor()
  973. // ==========================================
  974. // Private class function to analyze an unknown (No Intel or AMD) processor
  975. ///////////////////////////////////////////////////////////////////////////
  976. bool CProcessor::AnalyzeUnknownProcessor()
  977. {
  978. #if LL_WINDOWS
  979. unsigned long eaxreg, ebxreg;
  980. // We check if the CPUID command is available
  981. if (!CheckCPUIDPresence())
  982. return false;
  983. // First of all we read the standard CPUID level 0x00000001
  984. // This level should be available on every x86-processor clone
  985. __asm
  986. {
  987.         mov eax, 1
  988. cpuid
  989. mov eaxreg, eax
  990. mov ebxreg, ebx
  991. }
  992. // Then we mask the processor model, family, type and stepping
  993. CPUInfo.uiStepping = eaxreg & 0xF;
  994. CPUInfo.uiModel    = (eaxreg >> 4) & 0xF;
  995. CPUInfo.uiFamily   = (eaxreg >> 8) & 0xF;
  996. CPUInfo.uiType     = (eaxreg >> 12) & 0x3;
  997. // To have complete information we also mask the brand id
  998. CPUInfo.uiBrandID  = ebxreg & 0xF;
  999. // Then we get the standard processor extensions
  1000. GetStandardProcessorExtensions();
  1001. // Now we mark everything we do not know as unknown
  1002. strcpy(strCPUName, "Unknown"); /*Flawfinder: ignore*/
  1003. strcpy(CPUInfo._Data.strTLB, "Unknown"); /*Flawfinder: ignore*/
  1004. strcpy(CPUInfo._Instruction.strTLB, "Unknown"); /*Flawfinder: ignore*/
  1005. strcpy(CPUInfo._Trace.strCache, "Unknown"); /*Flawfinder: ignore*/
  1006. strcpy(CPUInfo._L1.Data.strCache, "Unknown"); /*Flawfinder: ignore*/
  1007. strcpy(CPUInfo._L1.Instruction.strCache, "Unknown"); /*Flawfinder: ignore*/
  1008. strcpy(CPUInfo._L2.strCache, "Unknown"); /*Flawfinder: ignore*/
  1009. strcpy(CPUInfo._L3.strCache, "Unknown"); /*Flawfinder: ignore*/
  1010. strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported"); /*Flawfinder: ignore*/
  1011. // For the family, model and brand id we can only print the numeric value
  1012. snprintf(CPUInfo.strBrandID, sizeof(CPUInfo.strBrandID), "Brand-ID number %d", CPUInfo.uiBrandID); /* Flawfinder: ignore */
  1013. snprintf(CPUInfo.strFamily, sizeof(CPUInfo.strFamily), "Family number %d", CPUInfo.uiFamily); /* Flawfinder: ignore */
  1014. snprintf(CPUInfo.strModel, sizeof(CPUInfo.strModel), "Model number %d", CPUInfo.uiModel); /* Flawfinder: ignore */
  1015. // And thats it
  1016. return true;
  1017. #else
  1018. return FALSE;
  1019. #endif
  1020. }
  1021. // bool CProcessor::CheckCPUIDPresence()
  1022. // =====================================
  1023. // This function checks if the CPUID command is available on the current
  1024. // processor
  1025. ////////////////////////////////////////////////////////////////////////
  1026. bool CProcessor::CheckCPUIDPresence()
  1027. {
  1028. #if LL_WINDOWS
  1029. unsigned long BitChanged;
  1030. // We've to check if we can toggle the flag register bit 21
  1031. // If we can't the processor does not support the CPUID command
  1032. __asm
  1033. {
  1034. pushfd
  1035. pop eax
  1036. mov ebx, eax
  1037. xor eax, 0x00200000 
  1038. push eax
  1039. popfd
  1040. pushfd
  1041. pop eax
  1042. xor eax,ebx 
  1043. mov BitChanged, eax
  1044. }
  1045. return ((BitChanged) ? true : false);
  1046. #else
  1047. return FALSE;
  1048. #endif
  1049. }
  1050. // void CProcessor::DecodeProcessorConfiguration(unsigned int cfg)
  1051. // ===============================================================
  1052. // This function (or switch ?!) just translates a one-byte processor configuration
  1053. // byte to understandable values
  1054. //////////////////////////////////////////////////////////////////////////////////
  1055. void CProcessor::DecodeProcessorConfiguration(unsigned int cfg)
  1056. {
  1057. // First we ensure that there's only one single byte
  1058. cfg &= 0xFF;
  1059. // Then we do a big switch
  1060. switch(cfg)
  1061. {
  1062. case 0: // cfg = 0:  Unused
  1063. break;
  1064. case 0x1: // cfg = 0x1:  code TLB present, 4 KB pages, 4 ways, 32 entries
  1065. CPUInfo._Instruction.bPresent = true;
  1066. strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/
  1067. CPUInfo._Instruction.uiAssociativeWays = 4;
  1068. CPUInfo._Instruction.uiEntries = 32;
  1069. break;
  1070. case 0x2: // cfg = 0x2:  code TLB present, 4 MB pages, fully associative, 2 entries
  1071. CPUInfo._Instruction.bPresent = true;
  1072. strcpy(CPUInfo._Instruction.strPageSize, "4 MB"); /*Flawfinder: ignore*/
  1073. CPUInfo._Instruction.uiAssociativeWays = 4;
  1074. CPUInfo._Instruction.uiEntries = 2;
  1075. break;
  1076. case 0x3: // cfg = 0x3:  data TLB present, 4 KB pages, 4 ways, 64 entries
  1077. CPUInfo._Data.bPresent = true;
  1078. strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/
  1079. CPUInfo._Data.uiAssociativeWays = 4;
  1080. CPUInfo._Data.uiEntries = 64;
  1081. break;
  1082. case 0x4: // cfg = 0x4:  data TLB present, 4 MB pages, 4 ways, 8 entries
  1083. CPUInfo._Data.bPresent = true;
  1084. strcpy(CPUInfo._Data.strPageSize, "4 MB"); /*Flawfinder: ignore*/
  1085. CPUInfo._Data.uiAssociativeWays = 4;
  1086. CPUInfo._Data.uiEntries = 8;
  1087. break;
  1088. case 0x6: // cfg = 0x6:  code L1 cache present, 8 KB, 4 ways, 32 byte lines
  1089. CPUInfo._L1.Instruction.bPresent = true;
  1090. strcpy(CPUInfo._L1.Instruction.strSize, "8 KB"); /*Flawfinder: ignore*/
  1091. CPUInfo._L1.Instruction.uiAssociativeWays = 4;
  1092. CPUInfo._L1.Instruction.uiLineSize = 32;
  1093. break;
  1094. case 0x8: // cfg = 0x8:  code L1 cache present, 16 KB, 4 ways, 32 byte lines
  1095. CPUInfo._L1.Instruction.bPresent = true;
  1096. strcpy(CPUInfo._L1.Instruction.strSize, "16 KB"); /*Flawfinder: ignore*/
  1097. CPUInfo._L1.Instruction.uiAssociativeWays = 4;
  1098. CPUInfo._L1.Instruction.uiLineSize = 32;
  1099. break;
  1100. case 0xA: // cfg = 0xA:  data L1 cache present, 8 KB, 2 ways, 32 byte lines
  1101. CPUInfo._L1.Data.bPresent = true;
  1102. strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /*Flawfinder: ignore*/
  1103. CPUInfo._L1.Data.uiAssociativeWays = 2;
  1104. CPUInfo._L1.Data.uiLineSize = 32;
  1105. break;
  1106. case 0xC: // cfg = 0xC:  data L1 cache present, 16 KB, 4 ways, 32 byte lines
  1107. CPUInfo._L1.Data.bPresent = true;
  1108. strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /*Flawfinder: ignore*/
  1109. CPUInfo._L1.Data.uiAssociativeWays = 4;
  1110. CPUInfo._L1.Data.uiLineSize = 32;
  1111. break;
  1112. case 0x22: // cfg = 0x22:  code and data L3 cache present, 512 KB, 4 ways, 64 byte lines, sectored
  1113. CPUInfo._L3.bPresent = true;
  1114. strcpy(CPUInfo._L3.strSize, "512 KB"); /*Flawfinder: ignore*/
  1115. CPUInfo._L3.uiAssociativeWays = 4;
  1116. CPUInfo._L3.uiLineSize = 64;
  1117. CPUInfo._L3.bSectored = true;
  1118. break;
  1119. case 0x23: // cfg = 0x23:  code and data L3 cache present, 1024 KB, 8 ways, 64 byte lines, sectored
  1120. CPUInfo._L3.bPresent = true;
  1121. strcpy(CPUInfo._L3.strSize, "1024 KB"); /*Flawfinder: ignore*/
  1122. CPUInfo._L3.uiAssociativeWays = 8;
  1123. CPUInfo._L3.uiLineSize = 64;
  1124. CPUInfo._L3.bSectored = true;
  1125. break;
  1126. case 0x25: // cfg = 0x25:  code and data L3 cache present, 2048 KB, 8 ways, 64 byte lines, sectored
  1127. CPUInfo._L3.bPresent = true;
  1128. strcpy(CPUInfo._L3.strSize, "2048 KB"); /*Flawfinder: ignore*/
  1129. CPUInfo._L3.uiAssociativeWays = 8;
  1130. CPUInfo._L3.uiLineSize = 64;
  1131. CPUInfo._L3.bSectored = true;
  1132. break;
  1133. case 0x29: // cfg = 0x29:  code and data L3 cache present, 4096 KB, 8 ways, 64 byte lines, sectored
  1134. CPUInfo._L3.bPresent = true;
  1135. strcpy(CPUInfo._L3.strSize, "4096 KB"); /*Flawfinder: ignore*/
  1136. CPUInfo._L3.uiAssociativeWays = 8;
  1137. CPUInfo._L3.uiLineSize = 64;
  1138. CPUInfo._L3.bSectored = true;
  1139. break;
  1140. case 0x40: // cfg = 0x40:  no integrated L2 cache (P6 core) or L3 cache (P4 core)
  1141. break;
  1142. case 0x41: // cfg = 0x41:  code and data L2 cache present, 128 KB, 4 ways, 32 byte lines
  1143. CPUInfo._L2.bPresent = true;
  1144. strcpy(CPUInfo._L2.strSize, "128 KB"); /*Flawfinder: ignore*/
  1145. CPUInfo._L2.uiAssociativeWays = 4;
  1146. CPUInfo._L2.uiLineSize = 32;
  1147. break;
  1148. case 0x42: // cfg = 0x42:  code and data L2 cache present, 256 KB, 4 ways, 32 byte lines
  1149. CPUInfo._L2.bPresent = true;
  1150. strcpy(CPUInfo._L2.strSize, "256 KB"); /*Flawfinder: ignore*/
  1151. CPUInfo._L2.uiAssociativeWays = 4;
  1152. CPUInfo._L2.uiLineSize = 32;
  1153. break;
  1154. case 0x43: // cfg = 0x43:  code and data L2 cache present, 512 KB, 4 ways, 32 byte lines
  1155. CPUInfo._L2.bPresent = true;
  1156. strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */
  1157. CPUInfo._L2.uiAssociativeWays = 4;
  1158. CPUInfo._L2.uiLineSize = 32;
  1159. break;
  1160. case 0x44: // cfg = 0x44:  code and data L2 cache present, 1024 KB, 4 ways, 32 byte lines
  1161. CPUInfo._L2.bPresent = true;
  1162. strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */
  1163. CPUInfo._L2.uiAssociativeWays = 4;
  1164. CPUInfo._L2.uiLineSize = 32;
  1165. break;
  1166. case 0x45: // cfg = 0x45:  code and data L2 cache present, 2048 KB, 4 ways, 32 byte lines
  1167. CPUInfo._L2.bPresent = true;
  1168. strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */
  1169. CPUInfo._L2.uiAssociativeWays = 4;
  1170. CPUInfo._L2.uiLineSize = 32;
  1171. break;
  1172. case 0x50: // cfg = 0x50:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 64 entries
  1173. CPUInfo._Instruction.bPresent = true;
  1174. strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */
  1175. CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
  1176. CPUInfo._Instruction.uiEntries = 64;
  1177. break;
  1178. case 0x51: // cfg = 0x51:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 128 entries
  1179. CPUInfo._Instruction.bPresent = true;
  1180. strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */
  1181. CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
  1182. CPUInfo._Instruction.uiEntries = 128;
  1183. break;
  1184. case 0x52: // cfg = 0x52:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 256 entries
  1185. CPUInfo._Instruction.bPresent = true;
  1186. strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */
  1187. CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
  1188. CPUInfo._Instruction.uiEntries = 256;
  1189. break;
  1190. case 0x5B: // cfg = 0x5B:  data TLB present, 4 KB / 4 MB pages, fully associative, 64 entries
  1191. CPUInfo._Data.bPresent = true;
  1192. strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */
  1193. CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
  1194. CPUInfo._Data.uiEntries = 64;
  1195. break;
  1196. case 0x5C: // cfg = 0x5C:  data TLB present, 4 KB / 4 MB pages, fully associative, 128 entries
  1197. CPUInfo._Data.bPresent = true;
  1198. strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */
  1199. CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
  1200. CPUInfo._Data.uiEntries = 128;
  1201. break;
  1202. case 0x5d: // cfg = 0x5D:  data TLB present, 4 KB / 4 MB pages, fully associative, 256 entries
  1203. CPUInfo._Data.bPresent = true;
  1204. strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */
  1205. CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
  1206. CPUInfo._Data.uiEntries = 256;
  1207. break;
  1208. case 0x66: // cfg = 0x66:  data L1 cache present, 8 KB, 4 ways, 64 byte lines, sectored
  1209. CPUInfo._L1.Data.bPresent = true;
  1210. strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /* Flawfinder: ignore */
  1211. CPUInfo._L1.Data.uiAssociativeWays = 4;
  1212. CPUInfo._L1.Data.uiLineSize = 64;
  1213. break;
  1214. case 0x67: // cfg = 0x67:  data L1 cache present, 16 KB, 4 ways, 64 byte lines, sectored
  1215. CPUInfo._L1.Data.bPresent = true;
  1216. strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /* Flawfinder: ignore */
  1217. CPUInfo._L1.Data.uiAssociativeWays = 4;
  1218. CPUInfo._L1.Data.uiLineSize = 64;
  1219. break;
  1220. case 0x68: // cfg = 0x68:  data L1 cache present, 32 KB, 4 ways, 64 byte lines, sectored
  1221. CPUInfo._L1.Data.bPresent = true;
  1222. strcpy(CPUInfo._L1.Data.strSize, "32 KB"); /* Flawfinder: ignore */
  1223. CPUInfo._L1.Data.uiAssociativeWays = 4;
  1224. CPUInfo._L1.Data.uiLineSize = 64;
  1225. break;
  1226. case 0x70: // cfg = 0x70:  trace L1 cache present, 12 KuOPs, 4 ways
  1227. CPUInfo._Trace.bPresent = true;
  1228. strcpy(CPUInfo._Trace.strSize, "12 K-micro-ops"); /* Flawfinder: ignore */
  1229. CPUInfo._Trace.uiAssociativeWays = 4;
  1230. break;
  1231. case 0x71: // cfg = 0x71:  trace L1 cache present, 16 KuOPs, 4 ways
  1232. CPUInfo._Trace.bPresent = true;
  1233. strcpy(CPUInfo._Trace.strSize, "16 K-micro-ops"); /* Flawfinder: ignore */
  1234. CPUInfo._Trace.uiAssociativeWays = 4;
  1235. break;
  1236. case 0x72: // cfg = 0x72:  trace L1 cache present, 32 KuOPs, 4 ways
  1237. CPUInfo._Trace.bPresent = true;
  1238. strcpy(CPUInfo._Trace.strSize, "32 K-micro-ops"); /* Flawfinder: ignore */
  1239. CPUInfo._Trace.uiAssociativeWays = 4;
  1240. break;
  1241. case 0x79: // cfg = 0x79:  code and data L2 cache present, 128 KB, 8 ways, 64 byte lines, sectored
  1242. CPUInfo._L2.bPresent = true;
  1243. strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */
  1244. CPUInfo._L2.uiAssociativeWays = 8;
  1245. CPUInfo._L2.uiLineSize = 64;
  1246. CPUInfo._L2.bSectored = true;
  1247. break;
  1248. case 0x7A: // cfg = 0x7A:  code and data L2 cache present, 256 KB, 8 ways, 64 byte lines, sectored
  1249. CPUInfo._L2.bPresent = true;
  1250. strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */
  1251. CPUInfo._L2.uiAssociativeWays = 8;
  1252. CPUInfo._L2.uiLineSize = 64;
  1253. CPUInfo._L2.bSectored = true;
  1254. break;
  1255. case 0x7B: // cfg = 0x7B:  code and data L2 cache present, 512 KB, 8 ways, 64 byte lines, sectored
  1256. CPUInfo._L2.bPresent = true;
  1257. strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */
  1258. CPUInfo._L2.uiAssociativeWays = 8;
  1259. CPUInfo._L2.uiLineSize = 64;
  1260. CPUInfo._L2.bSectored = true;
  1261. break;
  1262. case 0x7C: // cfg = 0x7C:  code and data L2 cache present, 1024 KB, 8 ways, 64 byte lines, sectored
  1263. CPUInfo._L2.bPresent = true;
  1264. strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */
  1265. CPUInfo._L2.uiAssociativeWays = 8;
  1266. CPUInfo._L2.uiLineSize = 64;
  1267. CPUInfo._L2.bSectored = true;
  1268. break;
  1269. case 0x81: // cfg = 0x81:  code and data L2 cache present, 128 KB, 8 ways, 32 byte lines
  1270. CPUInfo._L2.bPresent = true;
  1271. strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */
  1272. CPUInfo._L2.uiAssociativeWays = 8;
  1273. CPUInfo._L2.uiLineSize = 32;
  1274. break;
  1275. case 0x82: // cfg = 0x82:  code and data L2 cache present, 256 KB, 8 ways, 32 byte lines
  1276. CPUInfo._L2.bPresent = true;
  1277. strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */
  1278. CPUInfo._L2.uiAssociativeWays = 8;
  1279. CPUInfo._L2.uiLineSize = 32;
  1280. break;
  1281. case 0x83: // cfg = 0x83:  code and data L2 cache present, 512 KB, 8 ways, 32 byte lines
  1282. CPUInfo._L2.bPresent = true;
  1283. strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */
  1284. CPUInfo._L2.uiAssociativeWays = 8;
  1285. CPUInfo._L2.uiLineSize = 32;
  1286. break;
  1287. case 0x84: // cfg = 0x84:  code and data L2 cache present, 1024 KB, 8 ways, 32 byte lines
  1288. CPUInfo._L2.bPresent = true;
  1289. strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */
  1290. CPUInfo._L2.uiAssociativeWays = 8;
  1291. CPUInfo._L2.uiLineSize = 32;
  1292. break;
  1293. case 0x85: // cfg = 0x85:  code and data L2 cache present, 2048 KB, 8 ways, 32 byte lines
  1294. CPUInfo._L2.bPresent = true;
  1295. strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */
  1296. CPUInfo._L2.uiAssociativeWays = 8;
  1297. CPUInfo._L2.uiLineSize = 32;
  1298. break;
  1299. }
  1300. }
  1301. FORCEINLINE static char *TranslateAssociativeWays(unsigned int uiWays, char *buf)
  1302. {
  1303. // We define 0xFFFFFFFF (= -1) as fully associative
  1304.     if (uiWays == ((unsigned int) -1))
  1305. strcpy(buf, "fully associative"); /* Flawfinder: ignore */
  1306. else
  1307. {
  1308. if (uiWays == 1) // A one way associative cache is just direct mapped
  1309. strcpy(buf, "direct mapped"); /* Flawfinder: ignore */
  1310. else if (uiWays == 0) // This should not happen...
  1311. strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */
  1312. else // The x-way associative cache
  1313. sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */
  1314. }
  1315. // To ease the function use we return the buffer
  1316. return buf;
  1317. }
  1318. FORCEINLINE static void TranslateTLB(ProcessorTLB *tlb)
  1319. {
  1320. char buf[64]; /* Flawfinder: ignore */
  1321. // We just check if the TLB is present
  1322. if (tlb->bPresent)
  1323.         snprintf(tlb->strTLB,sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */
  1324. else
  1325.         strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */
  1326. }
  1327. FORCEINLINE static void TranslateCache(ProcessorCache *cache)
  1328. {
  1329. char buf[64]; /* Flawfinder: ignore */
  1330. // We just check if the cache is present
  1331.     if (cache->bPresent)
  1332. {
  1333. // If present we construct the string
  1334. snprintf(cache->strCache, sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */
  1335. if (cache->bSectored)
  1336. strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */
  1337. }
  1338. else
  1339. {
  1340. // Else we just say "Not present"
  1341. strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */
  1342. }
  1343. }
  1344. // void CProcessor::TranslateProcessorConfiguration()
  1345. // ==================================================
  1346. // Private class function to translate the processor configuration values
  1347. // to strings
  1348. /////////////////////////////////////////////////////////////////////////
  1349. void CProcessor::TranslateProcessorConfiguration()
  1350. {
  1351. // We just call the small functions defined above
  1352. TranslateTLB(&CPUInfo._Data);
  1353. TranslateTLB(&CPUInfo._Instruction);
  1354. TranslateCache(&CPUInfo._Trace);
  1355. TranslateCache(&CPUInfo._L1.Instruction);
  1356. TranslateCache(&CPUInfo._L1.Data);
  1357. TranslateCache(&CPUInfo._L2);
  1358. TranslateCache(&CPUInfo._L3);
  1359. }
  1360. // void CProcessor::GetStandardProcessorConfiguration()
  1361. // ====================================================
  1362. // Private class function to read the standard processor configuration
  1363. //////////////////////////////////////////////////////////////////////
  1364. void CProcessor::GetStandardProcessorConfiguration()
  1365. {
  1366. #if LL_WINDOWS
  1367. unsigned long eaxreg, ebxreg, ecxreg, edxreg;
  1368. // We check if the CPUID function is available
  1369. if (!CheckCPUIDPresence())
  1370. return;
  1371. // First we check if the processor supports the standard
  1372. // CPUID level 0x00000002
  1373. if (CPUInfo.MaxSupportedLevel >= 2)
  1374. {
  1375. // Now we go read the std. CPUID level 0x00000002 the first time
  1376. unsigned long count, num = 255;
  1377. for (count = 0; count < num; count++)
  1378. {
  1379. __asm
  1380. {
  1381. mov eax, 2
  1382. cpuid
  1383. mov eaxreg, eax
  1384. mov ebxreg, ebx
  1385. mov ecxreg, ecx
  1386. mov edxreg, edx
  1387. }
  1388. // We have to repeat this reading for 'num' times
  1389. num = eaxreg & 0xFF;
  1390. // Then we call the big decode switch function
  1391. DecodeProcessorConfiguration(eaxreg >> 8);
  1392. DecodeProcessorConfiguration(eaxreg >> 16);
  1393. DecodeProcessorConfiguration(eaxreg >> 24);
  1394. // If ebx contains additional data we also decode it
  1395. if ((ebxreg & 0x80000000) == 0)
  1396. {
  1397. DecodeProcessorConfiguration(ebxreg);
  1398. DecodeProcessorConfiguration(ebxreg >> 8);
  1399. DecodeProcessorConfiguration(ebxreg >> 16);
  1400. DecodeProcessorConfiguration(ebxreg >> 24);
  1401. }
  1402. // And also the ecx register
  1403. if ((ecxreg & 0x80000000) == 0)
  1404. {
  1405. DecodeProcessorConfiguration(ecxreg);
  1406. DecodeProcessorConfiguration(ecxreg >> 8);
  1407. DecodeProcessorConfiguration(ecxreg >> 16);
  1408. DecodeProcessorConfiguration(ecxreg >> 24);
  1409. }
  1410. // At last the edx processor register
  1411. if ((edxreg & 0x80000000) == 0)
  1412. {
  1413. DecodeProcessorConfiguration(edxreg);
  1414. DecodeProcessorConfiguration(edxreg >> 8);
  1415. DecodeProcessorConfiguration(edxreg >> 16);
  1416. DecodeProcessorConfiguration(edxreg >> 24);
  1417. }
  1418. }
  1419. }
  1420. #endif
  1421. }
  1422. // void CProcessor::GetStandardProcessorExtensions()
  1423. // =================================================
  1424. // Private class function to read the standard processor extensions
  1425. ///////////////////////////////////////////////////////////////////
  1426. void CProcessor::GetStandardProcessorExtensions()
  1427. {
  1428. #if LL_WINDOWS
  1429. unsigned long ebxreg, edxreg;
  1430. // We check if the CPUID command is available
  1431. if (!CheckCPUIDPresence())
  1432. return;
  1433. // We just get the standard CPUID level 0x00000001 which should be
  1434. // available on every x86 processor
  1435. __asm
  1436. {
  1437. mov eax, 1
  1438. cpuid
  1439. mov ebxreg, ebx
  1440. mov edxreg, edx
  1441. }
  1442.     
  1443. // Then we mask some bits
  1444. CPUInfo._Ext.FPU_FloatingPointUnit = CheckBit(edxreg, 0);
  1445. CPUInfo._Ext.VME_Virtual8086ModeEnhancements = CheckBit(edxreg, 1);
  1446. CPUInfo._Ext.DE_DebuggingExtensions = CheckBit(edxreg, 2);
  1447. CPUInfo._Ext.PSE_PageSizeExtensions = CheckBit(edxreg, 3);
  1448. CPUInfo._Ext.TSC_TimeStampCounter = CheckBit(edxreg, 4);
  1449. CPUInfo._Ext.MSR_ModelSpecificRegisters = CheckBit(edxreg, 5);
  1450. CPUInfo._Ext.PAE_PhysicalAddressExtension = CheckBit(edxreg, 6);
  1451. CPUInfo._Ext.MCE_MachineCheckException = CheckBit(edxreg, 7);
  1452. CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = CheckBit(edxreg, 8);
  1453. CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController = CheckBit(edxreg, 9);
  1454. CPUInfo._Ext.APIC_ID = (ebxreg >> 24) & 0xFF;
  1455. CPUInfo._Ext.SEP_FastSystemCall = CheckBit(edxreg, 11);
  1456. CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters = CheckBit(edxreg, 12);
  1457. CPUInfo._Ext.PGE_PTE_GlobalFlag = CheckBit(edxreg, 13);
  1458. CPUInfo._Ext.MCA_MachineCheckArchitecture = CheckBit(edxreg, 14);
  1459. CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions = CheckBit(edxreg, 15);
  1460. CPUInfo._Ext.FGPAT_PageAttributeTable = CheckBit(edxreg, 16);
  1461. CPUInfo._Ext.PSE36_36bitPageSizeExtension = CheckBit(edxreg, 17);
  1462. CPUInfo._Ext.PN_ProcessorSerialNumber = CheckBit(edxreg, 18);
  1463. CPUInfo._Ext.CLFSH_CFLUSH_Instruction = CheckBit(edxreg, 19);
  1464. CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize = (ebxreg >> 8) & 0xFF;
  1465. CPUInfo._Ext.DS_DebugStore = CheckBit(edxreg, 21);
  1466. CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl = CheckBit(edxreg, 22);
  1467. CPUInfo._Ext.MMX_MultimediaExtensions = CheckBit(edxreg, 23);
  1468. CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = CheckBit(edxreg, 24);
  1469. CPUInfo._Ext.SSE_StreamingSIMD_Extensions = CheckBit(edxreg, 25);
  1470. CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = CheckBit(edxreg, 26);
  1471. CPUInfo._Ext.Altivec_Extensions = false;
  1472. CPUInfo._Ext.SS_SelfSnoop = CheckBit(edxreg, 27);
  1473. CPUInfo._Ext.HT_HyperThreading = CheckBit(edxreg, 28);
  1474. CPUInfo._Ext.HT_HyterThreadingSiblings = (ebxreg >> 16) & 0xFF;
  1475. CPUInfo._Ext.TM_ThermalMonitor = CheckBit(edxreg, 29);
  1476. CPUInfo._Ext.IA64_Intel64BitArchitecture = CheckBit(edxreg, 30);
  1477. #endif
  1478. }
  1479. // const ProcessorInfo *CProcessor::GetCPUInfo()
  1480. // =============================================
  1481. // Calls all the other detection function to create an detailed
  1482. // processor information
  1483. ///////////////////////////////////////////////////////////////
  1484. const ProcessorInfo *CProcessor::GetCPUInfo()
  1485. {
  1486. #if LL_WINDOWS
  1487. unsigned long eaxreg, ebxreg, ecxreg, edxreg;
  1488.  
  1489. // First of all we check if the CPUID command is available
  1490. if (!CheckCPUIDPresence())
  1491. return NULL;
  1492. // We read the standard CPUID level 0x00000000 which should
  1493. // be available on every x86 processor
  1494. __asm
  1495. {
  1496. mov eax, 0
  1497. cpuid
  1498. mov eaxreg, eax
  1499. mov ebxreg, ebx
  1500. mov edxreg, edx
  1501. mov ecxreg, ecx
  1502. }
  1503. // Then we connect the single register values to the vendor string
  1504. *((unsigned long *) CPUInfo.strVendor) = ebxreg;
  1505. *((unsigned long *) (CPUInfo.strVendor+4)) = edxreg;
  1506. *((unsigned long *) (CPUInfo.strVendor+8)) = ecxreg;
  1507. // Null terminate for string comparisons below.
  1508. CPUInfo.strVendor[12] = 0;
  1509. // We can also read the max. supported standard CPUID level
  1510. CPUInfo.MaxSupportedLevel = eaxreg & 0xFFFF;
  1511. // Then we read the ext. CPUID level 0x80000000
  1512. __asm
  1513. {
  1514.         mov eax, 0x80000000
  1515. cpuid
  1516. mov eaxreg, eax
  1517. }
  1518. // ...to check the max. supportted extended CPUID level
  1519. CPUInfo.MaxSupportedExtendedLevel = eaxreg;
  1520. // Then we switch to the specific processor vendors
  1521. // See http://www.sandpile.org/ia32/cpuid.htm
  1522. if (!strcmp(CPUInfo.strVendor, "GenuineIntel"))
  1523. {
  1524. AnalyzeIntelProcessor();
  1525. }
  1526. else if (!strcmp(CPUInfo.strVendor, "AuthenticAMD"))
  1527. {
  1528. AnalyzeAMDProcessor();
  1529. }
  1530. else if (!strcmp(CPUInfo.strVendor, "UMC UMC UMC"))
  1531. {
  1532. AnalyzeUnknownProcessor();
  1533. }
  1534. else if (!strcmp(CPUInfo.strVendor, "CyrixInstead"))
  1535. {
  1536. AnalyzeUnknownProcessor();
  1537. }
  1538. else if (!strcmp(CPUInfo.strVendor, "NexGenDriven"))
  1539. {
  1540. AnalyzeUnknownProcessor();
  1541. }
  1542. else if (!strcmp(CPUInfo.strVendor, "CentaurHauls"))
  1543. {
  1544. AnalyzeUnknownProcessor();
  1545. }
  1546. else if (!strcmp(CPUInfo.strVendor, "RiseRiseRise"))
  1547. {
  1548. AnalyzeUnknownProcessor();
  1549. }
  1550. else if (!strcmp(CPUInfo.strVendor, "SiS SiS SiS"))
  1551. {
  1552. AnalyzeUnknownProcessor();
  1553. }
  1554. else if (!strcmp(CPUInfo.strVendor, "GenuineTMx86"))
  1555. {
  1556. // Transmeta
  1557. AnalyzeUnknownProcessor();
  1558. }
  1559. else if (!strcmp(CPUInfo.strVendor, "Geode by NSC"))
  1560. {
  1561. AnalyzeUnknownProcessor();
  1562. }
  1563. else
  1564. {
  1565. AnalyzeUnknownProcessor();
  1566. }
  1567. #endif
  1568. // After all we return the class CPUInfo member var
  1569. return (&CPUInfo);
  1570. }
  1571. #elif LL_SOLARIS
  1572. #include <kstat.h>
  1573. #if defined(__i386)
  1574. #include <sys/auxv.h>
  1575. #endif
  1576. // ======================
  1577. // Class constructor:
  1578. /////////////////////////
  1579. CProcessor::CProcessor()
  1580. {
  1581. uqwFrequency = 0;
  1582. strCPUName[0] = 0;
  1583. memset(&CPUInfo, 0, sizeof(CPUInfo));
  1584. }
  1585. // unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
  1586. // =========================================================================
  1587. // Function to query the current CPU frequency
  1588. ////////////////////////////////////////////////////////////////////////////
  1589. F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/)
  1590. {
  1591. if(uqwFrequency == 0){
  1592. GetCPUInfo();
  1593. }
  1594. return uqwFrequency;
  1595. }
  1596. // const ProcessorInfo *CProcessor::GetCPUInfo()
  1597. // =============================================
  1598. // Calls all the other detection function to create an detailed
  1599. // processor information
  1600. ///////////////////////////////////////////////////////////////
  1601. const ProcessorInfo *CProcessor::GetCPUInfo()
  1602. {
  1603. // In Solaris the CPU info is in the kstats
  1604. // try "psrinfo" or "kstat cpu_info" to see all
  1605. // that's available
  1606. int ncpus=0, i; 
  1607. kstat_ctl_t *kc;
  1608. kstat_t  *ks;
  1609. kstat_named_t   *ksinfo, *ksi;
  1610. kstat_t  *CPU_stats_list;
  1611. kc = kstat_open();
  1612. if((int)kc == -1){
  1613. llwarns << "kstat_open(0 failed!" << llendl;
  1614. return (&CPUInfo);
  1615. }
  1616. for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) {
  1617. if (strncmp(ks->ks_module, "cpu_info", 8) == 0 &&
  1618. strncmp(ks->ks_name, "cpu_info", 8) == 0)
  1619. ncpus++;
  1620. }
  1621. if(ncpus < 1){
  1622. llwarns << "No cpus found in kstats!" << llendl;
  1623. return (&CPUInfo);
  1624. }
  1625. for (ks = kc->kc_chain; ks; ks = ks->ks_next) {
  1626. if (strncmp(ks->ks_module, "cpu_info", 8) == 0 
  1627. &&  strncmp(ks->ks_name, "cpu_info", 8) == 0 
  1628. &&  kstat_read(kc, ks, NULL) != -1){     
  1629. CPU_stats_list = ks; // only looking at the first CPU
  1630. break;
  1631. }
  1632. }
  1633. if(ncpus > 1)
  1634.          snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpus); 
  1635. kstat_read(kc, CPU_stats_list, NULL);
  1636. ksinfo = (kstat_named_t *)CPU_stats_list->ks_data;
  1637. for(i=0; i < (int)(CPU_stats_list->ks_ndata); ++i){ // Walk the kstats for this cpu gathering what we need
  1638. ksi = ksinfo++;
  1639. if(!strcmp(ksi->name, "brand")){
  1640. strncat(strCPUName, (char *)KSTAT_NAMED_STR_PTR(ksi),
  1641. sizeof(strCPUName)-strlen(strCPUName)-1);
  1642. strncat(CPUInfo.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi),
  1643. sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
  1644. strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1);
  1645. CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='';
  1646. // DEBUG llinfos << "CPU brand: " << strCPUName << llendl;
  1647. continue;
  1648. }
  1649. if(!strcmp(ksi->name, "clock_MHz")){
  1650. #if defined(__sparc)
  1651. llinfos << "Raw kstat clock rate is: " << ksi->value.l << llendl;
  1652. uqwFrequency = (F64)(ksi->value.l * 1000000);
  1653. #else
  1654. uqwFrequency = (F64)(ksi->value.i64 * 1000000);
  1655. #endif
  1656. //DEBUG llinfos << "CPU frequency: " << uqwFrequency << llendl;
  1657. continue;
  1658. }
  1659. #if defined(__i386)
  1660. if(!strcmp(ksi->name, "vendor_id")){
  1661. strncpy(CPUInfo.strVendor, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(CPUInfo.strVendor)-1);
  1662. // DEBUG llinfos << "CPU vendor: " << CPUInfo.strVendor << llendl;
  1663. continue;
  1664. }
  1665. #endif
  1666. }
  1667. kstat_close(kc);
  1668. #if defined(__sparc) // SPARC does not define a vendor string in kstat
  1669. strncpy(CPUInfo.strVendor, "Sun Microsystems, Inc.", sizeof(CPUInfo.strVendor)-1);
  1670. #endif
  1671. // DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " <<  uqwFrequency << "MHz." << llendl;
  1672. #if defined (__i386)  //  we really don't care about the CPU extensions on SPARC but on x86...
  1673. // Now get cpu extensions
  1674. uint_t ui;
  1675. (void) getisax(&ui, 1);
  1676. if(ui & AV_386_FPU)
  1677. CPUInfo._Ext.FPU_FloatingPointUnit = true;
  1678. if(ui & AV_386_CX8)
  1679. CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = true;
  1680. if(ui & AV_386_MMX)
  1681. CPUInfo._Ext.MMX_MultimediaExtensions = true;
  1682. if(ui & AV_386_AMD_MMX)
  1683. CPUInfo._Ext.MMX_MultimediaExtensions = true;
  1684. if(ui & AV_386_FXSR)
  1685. CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = true;
  1686. if(ui & AV_386_SSE)
  1687.  CPUInfo._Ext.SSE_StreamingSIMD_Extensions = true;
  1688. if(ui & AV_386_SSE2)
  1689. CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = true;
  1690. /* Left these here since they may get used later
  1691. if(ui & AV_386_SSE3)
  1692. CPUInfo._Ext.... = true;
  1693. if(ui & AV_386_AMD_3DNow)
  1694. CPUInfo._Ext.... = true;
  1695. if(ui & AV_386_AMD_3DNowx)
  1696. CPUInfo._Ext.... = true;
  1697. */
  1698. #endif
  1699. return (&CPUInfo);
  1700. }
  1701. #else
  1702. // LL_DARWIN
  1703. #include <mach/machine.h>
  1704. #include <sys/sysctl.h>
  1705. static char *TranslateAssociativeWays(unsigned int uiWays, char *buf)
  1706. {
  1707. // We define 0xFFFFFFFF (= -1) as fully associative
  1708.     if (uiWays == ((unsigned int) -1))
  1709. strcpy(buf, "fully associative"); /* Flawfinder: ignore */
  1710. else
  1711. {
  1712. if (uiWays == 1) // A one way associative cache is just direct mapped
  1713. strcpy(buf, "direct mapped"); /* Flawfinder: ignore */
  1714. else if (uiWays == 0) // This should not happen...
  1715. strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */
  1716. else // The x-way associative cache
  1717. sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */
  1718. }
  1719. // To ease the function use we return the buffer
  1720. return buf;
  1721. }
  1722. static void TranslateTLB(ProcessorTLB *tlb)
  1723. {
  1724. char buf[64]; /* Flawfinder: ignore */
  1725. // We just check if the TLB is present
  1726. if (tlb->bPresent)
  1727.         snprintf(tlb->strTLB, sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */
  1728. else
  1729.         strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */
  1730. }
  1731. static void TranslateCache(ProcessorCache *cache)
  1732. {
  1733. char buf[64]; /* Flawfinder: ignore */
  1734. // We just check if the cache is present
  1735.     if (cache->bPresent)
  1736. {
  1737. // If present we construct the string
  1738. snprintf(cache->strCache,sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */
  1739. if (cache->bSectored)
  1740. strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */
  1741. }
  1742. else
  1743. {
  1744. // Else we just say "Not present"
  1745. strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */
  1746. }
  1747. }
  1748. // void CProcessor::TranslateProcessorConfiguration()
  1749. // ==================================================
  1750. // Private class function to translate the processor configuration values
  1751. // to strings
  1752. /////////////////////////////////////////////////////////////////////////
  1753. void CProcessor::TranslateProcessorConfiguration()
  1754. {
  1755. // We just call the small functions defined above
  1756. TranslateTLB(&CPUInfo._Data);
  1757. TranslateTLB(&CPUInfo._Instruction);
  1758. TranslateCache(&CPUInfo._Trace);
  1759. TranslateCache(&CPUInfo._L1.Instruction);
  1760. TranslateCache(&CPUInfo._L1.Data);
  1761. TranslateCache(&CPUInfo._L2);
  1762. TranslateCache(&CPUInfo._L3);
  1763. }
  1764. // CProcessor::CProcessor
  1765. // ======================
  1766. // Class constructor:
  1767. /////////////////////////
  1768. CProcessor::CProcessor()
  1769. {
  1770. uqwFrequency = 0;
  1771. strCPUName[0] = 0;
  1772. memset(&CPUInfo, 0, sizeof(CPUInfo));
  1773. }
  1774. // unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
  1775. // =========================================================================
  1776. // Function to query the current CPU frequency
  1777. ////////////////////////////////////////////////////////////////////////////
  1778. F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/)
  1779. {
  1780. U64 frequency = 0;
  1781. size_t len = sizeof(frequency);
  1782. if(sysctlbyname("hw.cpufrequency", &frequency, &len, NULL, 0) == 0)
  1783. {
  1784. uqwFrequency = (F64)frequency;
  1785. }
  1786. return uqwFrequency;
  1787. }
  1788. static bool hasFeature(const char *name)
  1789. {
  1790. bool result = false;
  1791. int val = 0;
  1792. size_t len = sizeof(val);
  1793. if(sysctlbyname(name, &val, &len, NULL, 0) == 0)
  1794. {
  1795. if(val != 0)
  1796. result = true;
  1797. }
  1798. return result;
  1799. }
  1800. // const ProcessorInfo *CProcessor::GetCPUInfo()
  1801. // =============================================
  1802. // Calls all the other detection function to create an detailed
  1803. // processor information
  1804. ///////////////////////////////////////////////////////////////
  1805. const ProcessorInfo *CProcessor::GetCPUInfo()
  1806. {
  1807. int pagesize = 0;
  1808. int cachelinesize = 0;
  1809. int l1icachesize = 0;
  1810. int l1dcachesize = 0;
  1811. int l2settings = 0;
  1812. int l2cachesize = 0;
  1813. int l3settings = 0;
  1814. int l3cachesize = 0;
  1815. int ncpu = 0;
  1816. int cpusubtype = 0;
  1817. // sysctl knows all.
  1818. int mib[2];
  1819. size_t len;
  1820. mib[0] = CTL_HW;
  1821. mib[1] = HW_PAGESIZE;
  1822. len = sizeof(pagesize);
  1823. sysctl(mib, 2, &pagesize, &len, NULL, 0);
  1824. mib[1] = HW_CACHELINE;
  1825. len = sizeof(cachelinesize);
  1826. sysctl(mib, 2, &cachelinesize, &len, NULL, 0);
  1827. mib[1] = HW_L1ICACHESIZE;
  1828. len = sizeof(l1icachesize);
  1829. sysctl(mib, 2, &l1icachesize, &len, NULL, 0);
  1830. mib[1] = HW_L1DCACHESIZE;
  1831. len = sizeof(l1dcachesize);
  1832. sysctl(mib, 2, &l1dcachesize, &len, NULL, 0);
  1833. mib[1] = HW_L2SETTINGS;
  1834. len = sizeof(l2settings);
  1835. sysctl(mib, 2, &l2settings, &len, NULL, 0);
  1836. mib[1] = HW_L2CACHESIZE;
  1837. len = sizeof(l2cachesize);
  1838. sysctl(mib, 2, &l2cachesize, &len, NULL, 0);
  1839. mib[1] = HW_L3SETTINGS;
  1840. len = sizeof(l3settings);
  1841. sysctl(mib, 2, &l3settings, &len, NULL, 0);
  1842. mib[1] = HW_L3CACHESIZE;
  1843. len = sizeof(l3cachesize);
  1844. sysctl(mib, 2, &l3cachesize, &len, NULL, 0);
  1845. mib[1] = HW_NCPU;
  1846. len = sizeof(ncpu);
  1847. sysctl(mib, 2, &ncpu, &len, NULL, 0);
  1848. sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0);
  1849. strCPUName[0] = 0;
  1850. if((ncpu == 0) || (ncpu == 1))
  1851. {
  1852. // Uhhh...
  1853. }
  1854. else if(ncpu == 2)
  1855. {
  1856. strncat(strCPUName, "Dual ", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1857. }
  1858. else
  1859. {
  1860. snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpu); /* Flawfinder: ignore */
  1861. }
  1862. #if __ppc__
  1863. switch(cpusubtype)
  1864. {
  1865. case CPU_SUBTYPE_POWERPC_601://         ((cpu_subtype_t) 1)
  1866. strncat(strCPUName, "PowerPC 601", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1867. strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1868. break;
  1869. case CPU_SUBTYPE_POWERPC_602://         ((cpu_subtype_t) 2)
  1870. strncat(strCPUName, "PowerPC 602", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1871. strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1872. break;
  1873. case CPU_SUBTYPE_POWERPC_603://         ((cpu_subtype_t) 3)
  1874. strncat(strCPUName, "PowerPC 603", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1875. strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1876. break;
  1877. case CPU_SUBTYPE_POWERPC_603e://        ((cpu_subtype_t) 4)
  1878. strncat(strCPUName, "PowerPC 603e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1879. strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1880. break;
  1881. case CPU_SUBTYPE_POWERPC_603ev://       ((cpu_subtype_t) 5)
  1882. strncat(strCPUName, "PowerPC 603ev", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1883. strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1884. break;
  1885. case CPU_SUBTYPE_POWERPC_604://         ((cpu_subtype_t) 6)
  1886. strncat(strCPUName, "PowerPC 604", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1887. strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1888. break;
  1889. case CPU_SUBTYPE_POWERPC_604e://        ((cpu_subtype_t) 7)
  1890. strncat(strCPUName, "PowerPC 604e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1891. strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1892. break;
  1893. case CPU_SUBTYPE_POWERPC_620:// ((cpu_subtype_t) 8)
  1894. strncat(strCPUName, "PowerPC 620", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1895. strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1896. break;
  1897. case CPU_SUBTYPE_POWERPC_750://         ((cpu_subtype_t) 9)
  1898. strncat(strCPUName, "PowerPC 750", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1899. strncat(CPUInfo.strFamily, "PowerPC G3", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1900. break;
  1901. case CPU_SUBTYPE_POWERPC_7400://        ((cpu_subtype_t) 10)
  1902. strncat(strCPUName, "PowerPC 7400", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1903. strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1904. break;
  1905. case CPU_SUBTYPE_POWERPC_7450://        ((cpu_subtype_t) 11)
  1906. strncat(strCPUName, "PowerPC 7450", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1907. strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1908. break;
  1909. case CPU_SUBTYPE_POWERPC_970://         ((cpu_subtype_t) 100)
  1910. strncat(strCPUName, "PowerPC 970", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1911. strncat(CPUInfo.strFamily, "PowerPC G5", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
  1912. break;
  1913. default:
  1914. strncat(strCPUName, "PowerPC (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1915. break;
  1916. }
  1917. CPUInfo._Ext.EMMX_MultimediaExtensions = 
  1918. CPUInfo._Ext.MMX_MultimediaExtensions = 
  1919. CPUInfo._Ext.SSE_StreamingSIMD_Extensions =
  1920. CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = false;
  1921. CPUInfo._Ext.Altivec_Extensions = hasFeature("hw.optional.altivec");
  1922. #endif
  1923. #if __i386__
  1924. // MBW -- XXX -- TODO -- make this call AnalyzeIntelProcessor()?
  1925. switch(cpusubtype)
  1926. {
  1927. default:
  1928. strncat(strCPUName, "i386 (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
  1929. break;
  1930. }
  1931. CPUInfo._Ext.EMMX_MultimediaExtensions = hasFeature("hw.optional.mmx");  // MBW -- XXX -- this may be wrong...
  1932. CPUInfo._Ext.MMX_MultimediaExtensions = hasFeature("hw.optional.mmx");
  1933. CPUInfo._Ext.SSE_StreamingSIMD_Extensions = hasFeature("hw.optional.sse");
  1934. CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.sse2");
  1935. CPUInfo._Ext.Altivec_Extensions = false;
  1936. CPUInfo._Ext.AA64_AMD64BitArchitecture = hasFeature("hw.optional.x86_64");
  1937. #endif
  1938. // Terse CPU info uses this string...
  1939. strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1); /* Flawfinder: ignore */
  1940. CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='';
  1941. // Fun cache config stuff...
  1942. if(l1dcachesize != 0)
  1943. {
  1944. CPUInfo._L1.Data.bPresent = true;
  1945. snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", l1dcachesize / 1024); /* Flawfinder: ignore */
  1946. // CPUInfo._L1.Data.uiAssociativeWays = ???;
  1947. CPUInfo._L1.Data.uiLineSize = cachelinesize;
  1948. }
  1949. if(l1icachesize != 0)
  1950. {
  1951. CPUInfo._L1.Instruction.bPresent = true;
  1952. snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", l1icachesize / 1024); /* Flawfinder: ignore */
  1953. // CPUInfo._L1.Instruction.uiAssociativeWays = ???;
  1954. CPUInfo._L1.Instruction.uiLineSize = cachelinesize;
  1955. }
  1956. if(l2cachesize != 0)
  1957. {
  1958. CPUInfo._L2.bPresent = true;
  1959. snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l2cachesize / 1024); /* Flawfinder: ignore */
  1960. // CPUInfo._L2.uiAssociativeWays = ???;
  1961. CPUInfo._L2.uiLineSize = cachelinesize;
  1962. }
  1963. if(l3cachesize != 0)
  1964. {
  1965. CPUInfo._L2.bPresent = true;
  1966. snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l3cachesize / 1024); /* Flawfinder: ignore */
  1967. // CPUInfo._L2.uiAssociativeWays = ???;
  1968. CPUInfo._L2.uiLineSize = cachelinesize;
  1969. }
  1970. CPUInfo._Ext.FPU_FloatingPointUnit = hasFeature("hw.optional.floatingpoint");
  1971. // printf("pagesize = 0x%xn", pagesize);
  1972. // printf("cachelinesize = 0x%xn", cachelinesize);
  1973. // printf("l1icachesize = 0x%xn", l1icachesize);
  1974. // printf("l1dcachesize = 0x%xn", l1dcachesize);
  1975. // printf("l2settings = 0x%xn", l2settings);
  1976. // printf("l2cachesize = 0x%xn", l2cachesize);
  1977. // printf("l3settings = 0x%xn", l3settings);
  1978. // printf("l3cachesize = 0x%xn", l3cachesize);
  1979. // After reading we translate the configuration to strings
  1980. TranslateProcessorConfiguration();
  1981. // After all we return the class CPUInfo member var
  1982. return (&CPUInfo);
  1983. }
  1984. #endif // LL_DARWIN
  1985. // bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
  1986. // ======================================================================
  1987. // Gets the frequency and processor information and writes it to a string
  1988. /////////////////////////////////////////////////////////////////////////
  1989. bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
  1990. {
  1991. #define LENCHECK                len = (unsigned int) strlen(buf); if (len >= uiMaxLen) return false; strcpy(strBuffer, buf); strBuffer += len;     /*Flawfinder: ignore*/
  1992. #define COPYADD(str)            strcpy(buf, str); LENCHECK;    /* Flawfinder: ignore */
  1993. #define FORMATADD(format, var)  sprintf(buf, format, var); LENCHECK;    /* Flawfinder: ignore */
  1994. #define BOOLADD(str, boolvar)   COPYADD(str); if (boolvar) { COPYADD(" Yesn"); } else { COPYADD(" Non"); }
  1995. char buf[1024]; /* Flawfinder: ignore */
  1996. unsigned int len;
  1997. // First we have to get the frequency
  1998.     GetCPUFrequency(50);
  1999. // Then we get the processor information
  2000. GetCPUInfo();
  2001.     // Now we construct the string (see the macros at function beginning)
  2002. strBuffer[0] = 0;
  2003. COPYADD("// CPU General Informationn//////////////////////////n");
  2004. FORMATADD("Processor name:   %sn", strCPUName);
  2005. FORMATADD("Frequency:        %.2f MHznn", (float) uqwFrequency / 1000000.0f);
  2006. FORMATADD("Vendor:           %sn", CPUInfo.strVendor);
  2007. FORMATADD("Family:           %sn", CPUInfo.strFamily);
  2008. FORMATADD("Extended family:  %dn", CPUInfo.uiExtendedFamily);
  2009. FORMATADD("Model:            %sn", CPUInfo.strModel);
  2010. FORMATADD("Extended model:   %dn", CPUInfo.uiExtendedModel);
  2011. FORMATADD("Type:             %sn", CPUInfo.strType);
  2012. FORMATADD("Brand ID:         %sn", CPUInfo.strBrandID);
  2013. if (CPUInfo._Ext.PN_ProcessorSerialNumber)
  2014. {
  2015. FORMATADD("Processor Serial: %sn", CPUInfo.strProcessorSerial);
  2016. }
  2017. else
  2018. {
  2019.   COPYADD("Processor Serial: Disabledn");
  2020. }
  2021. #if !LL_SOLARIS //  NOTE: Why bother printing all this when it's irrelavent
  2022. COPYADD("nn// CPU Configurationn////////////////////n");
  2023. FORMATADD("L1 instruction cache:           %sn", CPUInfo._L1.Instruction.strCache);
  2024. FORMATADD("L1 data cache:                  %sn", CPUInfo._L1.Data.strCache);
  2025. FORMATADD("L2 cache:                       %sn", CPUInfo._L2.strCache);
  2026. FORMATADD("L3 cache:                       %sn", CPUInfo._L3.strCache);
  2027. FORMATADD("Trace cache:                    %sn", CPUInfo._Trace.strCache);
  2028. FORMATADD("Instruction TLB:                %sn", CPUInfo._Instruction.strTLB);
  2029. FORMATADD("Data TLB:                       %sn", CPUInfo._Data.strTLB);
  2030. FORMATADD("Max Supported CPUID-Level:      0x%08lXn", CPUInfo.MaxSupportedLevel);
  2031. FORMATADD("Max Supported Ext. CPUID-Level: 0x%08lXn", CPUInfo.MaxSupportedExtendedLevel);
  2032. COPYADD("nn// CPU Extensionsn/////////////////n");
  2033. BOOLADD("AA64   AMD 64-bit Architecture:                    ", CPUInfo._Ext.AA64_AMD64BitArchitecture);
  2034. BOOLADD("ACPI   Thermal Monitor And Clock Control:          ", CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl);
  2035. BOOLADD("APIC   Advanced Programmable Interrupt Controller: ", CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController);
  2036. FORMATADD("       APIC-ID:                                     %dn", CPUInfo._Ext.APIC_ID);
  2037. BOOLADD("CLFSH  CLFLUSH Instruction Presence:               ", CPUInfo._Ext.CLFSH_CFLUSH_Instruction);
  2038. FORMATADD("       CLFLUSH Instruction Cache Line Size:         %dn", CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize);
  2039. BOOLADD("CMOV   Conditional Move And Compare Instructions:  ", CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions);
  2040. BOOLADD("CX8    COMPXCHG8B Instruction:                     ", CPUInfo._Ext.CX8_COMPXCHG8B_Instruction);
  2041. BOOLADD("DE     Debugging Extensions:                       ", CPUInfo._Ext.DE_DebuggingExtensions);
  2042. BOOLADD("DS     Debug Store:                                ", CPUInfo._Ext.DS_DebugStore);
  2043. BOOLADD("FGPAT  Page Attribute Table:                       ", CPUInfo._Ext.FGPAT_PageAttributeTable);
  2044. BOOLADD("FPU    Floating Point Unit:                        ", CPUInfo._Ext.FPU_FloatingPointUnit);
  2045. BOOLADD("FXSR   Fast Streaming SIMD Extensions Save/Restore:", CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore);
  2046. BOOLADD("HT     Hyper Threading:                            ", CPUInfo._Ext.HT_HyperThreading);
  2047. BOOLADD("IA64   Intel 64-Bit Architecture:                  ", CPUInfo._Ext.IA64_Intel64BitArchitecture);
  2048. BOOLADD("MCA    Machine Check Architecture:                 ", CPUInfo._Ext.MCA_MachineCheckArchitecture);
  2049. BOOLADD("MCE    Machine Check Exception:                    ", CPUInfo._Ext.MCE_MachineCheckException);
  2050. BOOLADD("MMX    Multimedia Extensions:                      ", CPUInfo._Ext.MMX_MultimediaExtensions);
  2051. BOOLADD("MMX+   Multimedia Extensions:                      ", CPUInfo._Ext.EMMX_MultimediaExtensions);
  2052. BOOLADD("MSR    Model Specific Registers:                   ", CPUInfo._Ext.MSR_ModelSpecificRegisters);
  2053. BOOLADD("MTRR   Memory Type Range Registers:                ", CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters);
  2054. BOOLADD("PAE    Physical Address Extension:                 ", CPUInfo._Ext.PAE_PhysicalAddressExtension);
  2055. BOOLADD("PGE    PTE Global Flag:                            ", CPUInfo._Ext.PGE_PTE_GlobalFlag);
  2056. if (CPUInfo._Ext.PN_ProcessorSerialNumber)
  2057. {
  2058. FORMATADD("PN     Processor Serial Number:                     %sn", CPUInfo.strProcessorSerial);
  2059. }
  2060. else
  2061. {
  2062. COPYADD("PN     Processor Serial Number:                     Disabledn");
  2063. }
  2064. BOOLADD("PSE    Page Size Extensions:                       ", CPUInfo._Ext.PSE_PageSizeExtensions);
  2065. BOOLADD("PSE36  36-bit Page Size Extension:                 ", CPUInfo._Ext.PSE36_36bitPageSizeExtension);
  2066. BOOLADD("SEP    Fast System Call:                           ", CPUInfo._Ext.SEP_FastSystemCall);
  2067. BOOLADD("SS     Self Snoop:                                 ", CPUInfo._Ext.SS_SelfSnoop);
  2068. BOOLADD("SSE    Streaming SIMD Extensions:                  ", CPUInfo._Ext.SSE_StreamingSIMD_Extensions);
  2069. BOOLADD("SSE2   Streaming SIMD 2 Extensions:                ", CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions);
  2070. BOOLADD("ALTVEC Altivec Extensions:                         ", CPUInfo._Ext.Altivec_Extensions);
  2071. BOOLADD("TM     Thermal Monitor:                            ", CPUInfo._Ext.TM_ThermalMonitor);
  2072. BOOLADD("TSC    Time Stamp Counter:                         ", CPUInfo._Ext.TSC_TimeStampCounter);
  2073. BOOLADD("VME    Virtual 8086 Mode Enhancements:             ", CPUInfo._Ext.VME_Virtual8086ModeEnhancements);
  2074. BOOLADD("3DNow! Instructions:                               ", CPUInfo._Ext._3DNOW_InstructionExtensions);
  2075. BOOLADD("Enhanced 3DNow! Instructions:                      ", CPUInfo._Ext._E3DNOW_InstructionExtensions);
  2076. #endif
  2077. // Yippie!!!
  2078. return true;
  2079. }
  2080. // bool CProcessor::WriteInfoTextFile(const std::string& strFilename)
  2081. // ===========================================================
  2082. // Takes use of CProcessor::CPUInfoToText and saves the string to a
  2083. // file
  2084. ///////////////////////////////////////////////////////////////////
  2085. bool CProcessor::WriteInfoTextFile(const std::string& strFilename)
  2086. {
  2087. char buf[16384]; /* Flawfinder: ignore */
  2088. // First we get the string
  2089. if (!CPUInfoToText(buf, 16383))
  2090. return false;
  2091. // Then we create a new file (CREATE_ALWAYS)
  2092. LLFILE *file = LLFile::fopen(strFilename, "w"); /* Flawfinder: ignore */
  2093. if (!file)
  2094. return false;
  2095. // After that we write the string to the file
  2096. unsigned long dwBytesToWrite, dwBytesWritten;
  2097. dwBytesToWrite = (unsigned long) strlen(buf);  /*Flawfinder: ignore*/
  2098. dwBytesWritten = (unsigned long) fwrite(buf, 1, dwBytesToWrite, file);
  2099. fclose(file);
  2100. if (dwBytesToWrite != dwBytesWritten)
  2101. return false;
  2102. // Done
  2103. return true;
  2104. }