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