Newer
Older
/**
* @file llprocessor.cpp
* @brief Code to figure out the processor. Originally by Benjamin Jurke.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
// Filename: Processor.cpp
// =======================
// Author: Benjamin Jurke
// File history: 27.02.2002 - File created. Support for Intel and AMD processors
// 05.03.2002 - Fixed the CPUID bug: On Pre-Pentium CPUs the CPUID
// command is not available
// - The CProcessor::WriteInfoTextFile function do not
// longer use Win32 file functions (-> os independend)
// - Optional include of the windows.h header which is
// still need for CProcessor::GetCPUFrequency.
// 06.03.2002 - My birthday (18th :-))
// - Replaced the '\r\n' line endings in function
// CProcessor::CPUInfoToText by '\n'
// - Replaced unsigned __int64 by signed __int64 for
// solving some compiler conversion problems
// - Fixed a bug at family=6, model=6 (Celeron -> P2)
//////////////////////////////////////////////////////////////////////////////////
#include "linden_common.h"
#include "processor.h"
Aaron Brashears
committed
#include <memory>
#if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN
# include <winsock2.h>
# include <windows.h>
#endif
Tofu Linden
committed
#if LL_LINUX
#include "llsys.h"
#endif // LL_LINUX
Don Kjer
committed
#if !LL_DARWIN && !LL_SOLARIS
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
// We need the QueryPerformanceCounter and Sleep functions
#define FORCEINLINE __forceinline
#else
#define FORCEINLINE
#endif
// Some macros we often need
////////////////////////////
#define CheckBit(var, bit) ((var & (1 << bit)) ? true : false)
#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
// Delays for the specified amount of milliseconds
static void _Delay(unsigned int ms)
{
LARGE_INTEGER freq, c1, c2;
__int64 x;
// Get High-Res Timer frequency
if (!QueryPerformanceFrequency(&freq))
return;
// Convert ms to High-Res Timer value
x = freq.QuadPart/1000*ms;
// Get first snapshot of High-Res Timer value
QueryPerformanceCounter(&c1);
do
{
// Get second snapshot
QueryPerformanceCounter(&c2);
}while(c2.QuadPart-c1.QuadPart < x);
// Loop while (second-first < x)
}
#endif
// CProcessor::CProcessor
// ======================
// Class constructor:
/////////////////////////
CProcessor::CProcessor()
{
uqwFrequency = 0;
Josh Bell
committed
strCPUName[0] = 0;
memset(&CPUInfo, 0, sizeof(CPUInfo));
}
// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
// =========================================================================
// Function to measure the current CPU frequency
////////////////////////////////////////////////////////////////////////////
F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
{
Tofu Linden
committed
#if LL_LINUX
// use the shinier LLCPUInfo interface
return 1000000.0F * gSysCPU.getMHz();
#endif
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
return 0;
#else
// If there are invalid measure time parameters, zero msecs for example,
// we've to exit the function
if (uiMeasureMSecs < 1)
{
// If theres already a measured frequency available, we return it
if (uqwFrequency > 0)
return uqwFrequency;
else
return 0;
}
// Now we check if the CPUID command is available
if (!CheckCPUIDPresence())
return 0;
// First we get the CPUID standard level 0x00000001
unsigned long reg;
__asm
{
mov eax, 1
cpuid
mov reg, edx
}
// Then we check, if the RDTSC (Real Date Time Stamp Counter) is available.
// This function is necessary for our measure process.
if (!(reg & (1 << 4)))
return 0;
// After that we declare some vars and check the frequency of the high
// resolution timer for the measure process.
// If there's no high-res timer, we exit.
__int64 starttime, endtime, timedif, freq, start, end, dif;
if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq))
return 0;
// Now we can init the measure process. We set the process and thread priority
// to the highest available level (Realtime priority). Also we focus the
// first processor in the multiprocessor system.
HANDLE hProcess = GetCurrentProcess();
HANDLE hThread = GetCurrentThread();
unsigned long dwCurPriorityClass = GetPriorityClass(hProcess);
int iCurThreadPriority = GetThreadPriority(hThread);
unsigned long dwProcessMask, dwSystemMask, dwNewMask = 1;
GetProcessAffinityMask(hProcess, &dwProcessMask, &dwSystemMask);
SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
SetProcessAffinityMask(hProcess, dwNewMask);
// Now we call a CPUID to ensure, that all other prior called functions are
// completed now (serialization)
__asm cpuid
// We ask the high-res timer for the start time
QueryPerformanceCounter((LARGE_INTEGER *) &starttime);
// Then we get the current cpu clock and store it
__asm
{
rdtsc
mov dword ptr [start+4], edx
mov dword ptr [start], eax
}
// Now we wart for some msecs
_Delay(uiMeasureMSecs);
// Sleep(uiMeasureMSecs);
// We ask for the end time
QueryPerformanceCounter((LARGE_INTEGER *) &endtime);
// And also for the end cpu clock
__asm
{
rdtsc
mov dword ptr [end+4], edx
mov dword ptr [end], eax
}
// Now we can restore the default process and thread priorities
SetProcessAffinityMask(hProcess, dwProcessMask);
SetThreadPriority(hThread, iCurThreadPriority);
SetPriorityClass(hProcess, dwCurPriorityClass);
// Then we calculate the time and clock differences
dif = end - start;
timedif = endtime - starttime;
// And finally the frequency is the clock difference divided by the time
// difference.
uqwFrequency = (F64)dif / (((F64)timedif) / freq);
// At last we just return the frequency that is also stored in the call
// member var uqwFrequency
return uqwFrequency;
#endif
}
// bool CProcessor::AnalyzeIntelProcessor()
// ========================================
// Private class function for analyzing an Intel processor
//////////////////////////////////////////////////////////
bool CProcessor::AnalyzeIntelProcessor()
{
#if LL_WINDOWS
unsigned long eaxreg, ebxreg, edxreg;
// First we check if the CPUID command is available
if (!CheckCPUIDPresence())
return false;
// Now we get the CPUID standard level 0x00000001
__asm
{
mov eax, 1
cpuid
mov eaxreg, eax
mov ebxreg, ebx
mov edxreg, edx
}
// Then get the cpu model, family, type, stepping and brand id by masking
// the eax and ebx register
CPUInfo.uiStepping = eaxreg & 0xF;
CPUInfo.uiModel = (eaxreg >> 4) & 0xF;
CPUInfo.uiFamily = (eaxreg >> 8) & 0xF;
CPUInfo.uiType = (eaxreg >> 12) & 0x3;
CPUInfo.uiBrandID = ebxreg & 0xF;
Josh Bell
committed
static const char* INTEL_BRAND[] =
Josh Bell
committed
/* 0x00 */ "",
/* 0x01 */ "0.18 micron Intel Celeron",
/* 0x02 */ "0.18 micron Intel Pentium III",
/* 0x03 */ "0.13 micron Intel Celeron",
/* 0x04 */ "0.13 micron Intel Pentium III",
/* 0x05 */ "",
/* 0x06 */ "0.13 micron Intel Pentium III Mobile",
/* 0x07 */ "0.13 micron Intel Celeron Mobile",
Josh Bell
committed
/* 0x08 */ "0.18 micron Intel Pentium 4",
/* 0x09 */ "0.13 micron Intel Pentium 4",
/* 0x0A */ "0.13 micron Intel Celeron",
Josh Bell
committed
/* 0x0B */ "0.13 micron Intel Pentium 4 Xeon",
Josh Bell
committed
/* 0x0D */ "",
/* 0x0E */ "0.18 micron Intel Pentium 4 Xeon",
/* 0x0F */ "Mobile Intel Celeron",
Josh Bell
committed
/* 0x10 */ "",
/* 0x11 */ "Mobile Genuine Intel",
Josh Bell
committed
/* 0x12 */ "Intel Celeron M",
/* 0x13 */ "Mobile Intel Celeron",
Josh Bell
committed
/* 0x14 */ "Intel Celeron",
/* 0x15 */ "Mobile Genuine Intel",
Josh Bell
committed
/* 0x16 */ "Intel Pentium M",
/* 0x17 */ "Mobile Intel Celeron",
Josh Bell
committed
};
// Only override the brand if we have it in the lookup table. We should
// already have a string here from GetCPUInfo(). JC
if ( CPUInfo.uiBrandID < LL_ARRAY_SIZE(INTEL_BRAND) )
strncpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID], sizeof(CPUInfo.strBrandID)-1);
CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
Josh Bell
committed
if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6)
{
strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon");
}
}
// Then we translate the cpu family
switch (CPUInfo.uiFamily)
{
case 3: // Family = 3: i386 (80386) processor family
strcpy(CPUInfo.strFamily, "Intel i386"); /* Flawfinder: ignore */
break;
case 4: // Family = 4: i486 (80486) processor family
strcpy(CPUInfo.strFamily, "Intel i486"); /* Flawfinder: ignore */
break;
case 5: // Family = 5: Pentium (80586) processor family
strcpy(CPUInfo.strFamily, "Intel Pentium"); /* Flawfinder: ignore */
break;
case 6: // Family = 6: Pentium Pro (80686) processor family
Bryan O'Sullivan
committed
strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core"); /* Flawfinder: ignore */
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
break;
case 15: // Family = 15: Extended family specific
// Masking the extended family
CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF;
switch (CPUInfo.uiExtendedFamily)
{
case 0: // Family = 15, Ext. Family = 0: Pentium 4 (80786 ??) processor family
strcpy(CPUInfo.strFamily, "Intel Pentium 4"); /* Flawfinder: ignore */
break;
case 1: // Family = 15, Ext. Family = 1: McKinley (64-bit) processor family
strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)"); /* Flawfinder: ignore */
break;
default: // Sure is sure
strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+"); /* Flawfinder: ignore */
break;
}
break;
default: // Failsave
strcpy(CPUInfo.strFamily, "Unknown"); /* Flawfinder: ignore */
break;
}
// Now we come to the big deal, the exact model name
switch (CPUInfo.uiFamily)
{
case 3: // i386 (80386) processor family
strcpy(CPUInfo.strModel, "Unknown Intel i386"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 4: // i486 (80486) processor family
switch (CPUInfo.uiModel)
{
case 0: // Model = 0: i486 DX-25/33 processor model
strcpy(CPUInfo.strModel, "Intel i486 DX-25/33"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 1: // Model = 1: i486 DX-50 processor model
strcpy(CPUInfo.strModel, "Intel i486 DX-50"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 2: // Model = 2: i486 SX processor model
strcpy(CPUInfo.strModel, "Intel i486 SX"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 3: // Model = 3: i486 DX2 (with i487 numeric coprocessor) processor model
strcpy(CPUInfo.strModel, "Intel i486 487/DX2"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 4: // Model = 4: i486 SL processor model (never heard ?!?)
strcpy(CPUInfo.strModel, "Intel i486 SL"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 5: // Model = 5: i486 SX2 processor model
strcpy(CPUInfo.strModel, "Intel i486 SX2"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 7: // Model = 7: i486 write-back enhanced DX2 processor model
strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 8: // Model = 8: i486 DX4 processor model
strcpy(CPUInfo.strModel, "Intel i486 DX4"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 9: // Model = 9: i486 write-back enhanced DX4 processor model
strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
default: // ...
strcpy(CPUInfo.strModel, "Unknown Intel i486"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
}
break;
case 5: // Pentium (80586) processor family
switch (CPUInfo.uiModel)
{
case 0: // Model = 0: Pentium (P5 A-Step) processor model
strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break; // Famous for the DIV bug, as far as I know
case 1: // Model = 1: Pentium 60/66 processor model
strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 2: // Model = 2: Pentium 75-200 (P54C) processor model
strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
break;
case 3: // Model = 3: Pentium overdrive for 486 systems processor model
strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 4: // Model = 4: Pentium MMX processor model
strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 7: // Model = 7: Pentium processor model (don't know difference to Model=2)
strcpy(CPUInfo.strModel, "Intel Pentium (P54C)"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 8: // Model = 8: Pentium MMX (0.25 micron) processor model
strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
default: // ...
strcpy(CPUInfo.strModel, "Unknown Intel Pentium"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
}
break;
case 6: // Pentium Pro (80686) processor family
switch (CPUInfo.uiModel)
{
case 0: // Model = 0: Pentium Pro (P6 A-Step) processor model
strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 1: // Model = 1: Pentium Pro
strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 3: // Model = 3: Pentium II (66 MHz FSB, I think) processor model
strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 5: // Model = 5: Pentium II/Xeon/Celeron (0.25 micron) processor model
strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 6: // Model = 6: Pentium II with internal L2 cache
strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 7: // Model = 7: Pentium III/Xeon (extern L2 cache) processor model
strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 8: // Model = 8: Pentium III/Xeon/Celeron (256 KB on-die L2 cache) processor model
strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/
// We want to know it exactly:
switch (CPUInfo.uiBrandID)
{
case 1: // Model = 8, Brand id = 1: Celeron (on-die L2 cache) processor model
strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 2: // Model = 8, Brand id = 2: Pentium III (on-die L2 cache) processor model (my current cpu :-))
strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 3: // Model = 8, Brand id = 3: Pentium III Xeon (on-die L2 cache) processor model
strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
}
break;
case 9: // Model = 9: Intel Pentium M processor, Intel Celeron M processor, model 9
strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 0xA: // Model = 0xA: Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model
strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/
// Exact detection:
switch (CPUInfo.uiBrandID)
{
case 1: // Model = 0xA, Brand id = 1: Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model
strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 2: // Model = 0xA, Brand id = 2: Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model
strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 3: // Model = 0xA, Brand id = 3: Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model
strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
default: // Getting bored of this............
strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
}
break;
case 0xB: // Model = 0xB: Pentium III/Xeon/Celeron (Tualatin core, on-die cache) processor model
strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron"); /*Flawfinder: ignore*/
// Omniscient: ;-)
switch (CPUInfo.uiBrandID)
{
case 3: // Model = 0xB, Brand id = 3: Celeron (Tualatin core) processor model
strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 4: // Model = 0xB, Brand id = 4: Pentium III (Tualatin core) processor model
strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 7: // Model = 0xB, Brand id = 7: Celeron mobile (Tualatin core) processor model
strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
default: // *bored*
strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
}
break;
case 0xD: // Model = 0xD: Intel Pentium M processor, Intel Celeron M processor, model D
strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
Bryan O'Sullivan
committed
case 0xE: // Model = 0xE: Intel Core Duo processor, Intel Core Solo processor, model E
strcpy(CPUInfo.strModel, "Intel Core Series Processor"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
Bryan O'Sullivan
committed
break;
case 0xF: // Model = 0xF: Intel Core 2 Duo processor, model F
strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
Bryan O'Sullivan
committed
break;
Bryan O'Sullivan
committed
strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
break;
}
break;
case 15: // Extended processor family
// Masking the extended model
CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF;
switch (CPUInfo.uiModel)
{
case 0: // Model = 0: Pentium 4 Willamette (A-Step) core
if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette
{
strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)"); /*Flawfinder: ignore*/
strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
}
else // else Xeon
{
strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
}
break;
case 1: // Model = 1: Pentium 4 Willamette core
if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette
{
strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
}
else // else Xeon
{
strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
}
break;
case 2: // Model = 2: Pentium 4 Northwood core
if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA)) // P4 Willamette
{
strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
}
else // Xeon
{
strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
}
break;
default: // Silly stupid never used failsave option
strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
break;
}
break;
default: // *grmpf*
strcpy(CPUInfo.strModel, "Unknown Intel model"); /* Flawfinder: ignore */
strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
break;
}
// After the long processor model block we now come to the processors serial
// number.
// First of all we check if the processor supports the serial number
if (CPUInfo.MaxSupportedLevel >= 3)
{
// If it supports the serial number CPUID level 0x00000003 we read the data
unsigned long sig1, sig2, sig3;
__asm
{
mov eax, 1
cpuid
mov sig1, eax
mov eax, 3
cpuid
mov sig2, ecx
mov sig3, edx
}
// Then we convert the data to a readable string
Aaron Brashears
committed
snprintf( /* Flawfinder: ignore */
CPUInfo.strProcessorSerial,
sizeof(CPUInfo.strProcessorSerial),
"%04lX-%04lX-%04lX-%04lX-%04lX-%04lX",
sig1 >> 16,
sig1 & 0xFFFF,
sig3 >> 16,
sig3 & 0xFFFF,
Aaron Brashears
committed
sig2 >> 16, sig2 & 0xFFFF);
}
else
{
// If there's no serial number support we just put "No serial number"
CPUInfo.strProcessorSerial,
sizeof(CPUInfo.strProcessorSerial),
Aaron Brashears
committed
"No Processor Serial Number");
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
}
// Now we get the standard processor extensions
GetStandardProcessorExtensions();
// And finally the processor configuration (caches, TLBs, ...) and translate
// the data to readable strings
GetStandardProcessorConfiguration();
TranslateProcessorConfiguration();
// At last...
return true;
#else
return FALSE;
#endif
}
// bool CProcessor::AnalyzeAMDProcessor()
// ======================================
// Private class function for analyzing an AMD processor
////////////////////////////////////////////////////////
bool CProcessor::AnalyzeAMDProcessor()
{
#if LL_WINDOWS
unsigned long eaxreg, ebxreg, ecxreg, edxreg;
// First of all we check if the CPUID command is available
if (!CheckCPUIDPresence())
return 0;
// Now we get the CPUID standard level 0x00000001
__asm
{
mov eax, 1
cpuid
mov eaxreg, eax
mov ebxreg, ebx
mov edxreg, edx
}
// Then we mask the model, family, stepping and type (AMD does not support brand id)
CPUInfo.uiStepping = eaxreg & 0xF;
CPUInfo.uiModel = (eaxreg >> 4) & 0xF;
CPUInfo.uiFamily = (eaxreg >> 8) & 0xF;
CPUInfo.uiType = (eaxreg >> 12) & 0x3;
// Now we check if the processor supports the brand id string extended CPUID level
if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004)
{
// If it supports the extended CPUID level 0x80000004 we read the data
char tmp[52]; /* Flawfinder: ignore */
memset(tmp, 0, sizeof(tmp));
__asm
{
mov eax, 0x80000002
cpuid
mov dword ptr [tmp], eax
mov dword ptr [tmp+4], ebx
mov dword ptr [tmp+8], ecx
mov dword ptr [tmp+12], edx
mov eax, 0x80000003
cpuid
mov dword ptr [tmp+16], eax
mov dword ptr [tmp+20], ebx
mov dword ptr [tmp+24], ecx
mov dword ptr [tmp+28], edx
mov eax, 0x80000004
cpuid
mov dword ptr [tmp+32], eax
mov dword ptr [tmp+36], ebx
mov dword ptr [tmp+40], ecx
mov dword ptr [tmp+44], edx
}
// And copy it to the brand id string
strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1);
CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
}
else
{
// Or just tell there is no brand id string support
Josh Bell
committed
strcpy(CPUInfo.strBrandID, ""); /* Flawfinder: ignore */
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
}
// After that we translate the processor family
switch(CPUInfo.uiFamily)
{
case 4: // Family = 4: 486 (80486) or 5x86 (80486) processor family
switch (CPUInfo.uiModel)
{
case 3: // Thanks to AMD for this nice form of family
case 7: // detection.... *grmpf*
case 8:
case 9:
strcpy(CPUInfo.strFamily, "AMD 80486"); /* Flawfinder: ignore */
break;
case 0xE:
case 0xF:
strcpy(CPUInfo.strFamily, "AMD 5x86"); /* Flawfinder: ignore */
break;
default:
strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */
break;
}
break;
case 5: // Family = 5: K5 or K6 processor family
switch (CPUInfo.uiModel)
{
case 0:
case 1:
case 2:
case 3:
strcpy(CPUInfo.strFamily, "AMD K5"); /* Flawfinder: ignore */
break;
case 6:
case 7:
case 8:
case 9:
strcpy(CPUInfo.strFamily, "AMD K6"); /* Flawfinder: ignore */
break;
default:
strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */
break;
}
break;
case 6: // Family = 6: K7 (Athlon, ...) processor family
strcpy(CPUInfo.strFamily, "AMD K7"); /* Flawfinder: ignore */
break;
default: // For security
strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */
break;
}
// After the family detection we come to the specific processor model
// detection
switch (CPUInfo.uiFamily)
{
case 4: // Family = 4: 486 (80486) or 5x85 (80486) processor family
switch (CPUInfo.uiModel)
{
case 3: // Model = 3: 80486 DX2
strcpy(CPUInfo.strModel, "AMD 80486 DX2"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 7: // Model = 7: 80486 write-back enhanced DX2
strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 8: // Model = 8: 80486 DX4
strcpy(CPUInfo.strModel, "AMD 80486 DX4"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 9: // Model = 9: 80486 write-back enhanced DX4
strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 0xE: // Model = 0xE: 5x86
strcpy(CPUInfo.strModel, "AMD 5x86"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 0xF: // Model = 0xF: 5x86 write-back enhanced (oh my god.....)
strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
default: // ...
strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
}
break;
case 5: // Family = 5: K5 / K6 processor family
switch (CPUInfo.uiModel)
{
Tofu Linden
committed
case 0: // Model = 0: K5 SSA 5 (Pentium Rating *ggg* 75, 90 and 100 MHz)
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 1: // Model = 1: K5 5k86 (PR 120 and 133 MHz)
strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 2: // Model = 2: K5 5k86 (PR 166 MHz)
strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 3: // Model = 3: K5 5k86 (PR 200 MHz)
strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 6: // Model = 6: K6
strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 7: // Model = 7: K6 (0.25 micron)
strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 8: // Model = 8: K6-2
strcpy(CPUInfo.strModel, "AMD K6-2"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 9: // Model = 9: K6-III
strcpy(CPUInfo.strModel, "AMD K6-III"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 0xD: // Model = 0xD: K6-2+ / K6-III+
strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)"); /* Flawfinder: ignore */
Aaron Brashears
committed
strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
break;
default: // ...
strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
}
break;
case 6: // Family = 6: K7 processor family (AMDs first good processors)
switch (CPUInfo.uiModel)
{
case 1: // Athlon
strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 2: // Athlon (0.18 micron)
strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 3: // Duron (Spitfire core)
strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 4: // Athlon (Thunderbird core)
strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 6: // Athlon MP / Mobile Athlon (Palomino core)
strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
case 7: // Mobile Duron (Morgan core)
strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
default: // ...
strcpy(CPUInfo.strModel, "Unknown AMD K7 model"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
}
break;
default: // ...
strcpy(CPUInfo.strModel, "Unknown AMD model"); /* Flawfinder: ignore */
strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
break;
}
// Now we read the standard processor extension that are stored in the same
// way the Intel standard extensions are
GetStandardProcessorExtensions();
// Then we check if theres an extended CPUID level support
if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001)
{
// If we can access the extended CPUID level 0x80000001 we get the
// edx register
__asm
{
mov eax, 0x80000001
cpuid
mov edxreg, edx
}
// Now we can mask some AMD specific cpu extensions
CPUInfo._Ext.EMMX_MultimediaExtensions = CheckBit(edxreg, 22);
CPUInfo._Ext.AA64_AMD64BitArchitecture = CheckBit(edxreg, 29);
CPUInfo._Ext._E3DNOW_InstructionExtensions = CheckBit(edxreg, 30);
CPUInfo._Ext._3DNOW_InstructionExtensions = CheckBit(edxreg, 31);
}
// After that we check if the processor supports the ext. CPUID level
// 0x80000006
if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006)
{
// If it's present, we read it out
__asm
{
mov eax, 0x80000005
cpuid
mov eaxreg, eax
mov ebxreg, ebx
mov ecxreg, ecx
mov edxreg, edx
}
// Then we mask the L1 Data TLB information
if ((ebxreg >> 16) && (eaxreg >> 16))
{
CPUInfo._Data.bPresent = true;
strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/
CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
}
else if (eaxreg >> 16)
{
CPUInfo._Data.bPresent = true;
strcpy(CPUInfo._Data.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/
CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
}
else if (ebxreg >> 16)
{
CPUInfo._Data.bPresent = true;
strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/
CPUInfo._Data.uiAssociativeWays = (ebxreg >> 24) & 0xFF;
CPUInfo._Data.uiEntries = (ebxreg >> 16) & 0xFF;
}
if (CPUInfo._Data.uiAssociativeWays == 0xFF)
CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
// Now the L1 Instruction/Code TLB information
if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF))
{
CPUInfo._Instruction.bPresent = true;
strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/
CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
}
else if (eaxreg & 0xFFFF)
{
CPUInfo._Instruction.bPresent = true;
strcpy(CPUInfo._Instruction.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/
CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
}
else if (ebxreg & 0xFFFF)
{
CPUInfo._Instruction.bPresent = true;
strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/
CPUInfo._Instruction.uiAssociativeWays = (ebxreg >> 8) & 0xFF;
CPUInfo._Instruction.uiEntries = ebxreg & 0xFF;
}
if (CPUInfo._Instruction.uiAssociativeWays == 0xFF)
CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
// Then we read the L1 data cache information
if ((ecxreg >> 24) > 0)
{
CPUInfo._L1.Data.bPresent = true;
snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", ecxreg >> 24); /* Flawfinder: ignore */
CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF;
CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF;
}
// After that we read the L2 instruction/code cache information
if ((edxreg >> 24) > 0)
{
CPUInfo._L1.Instruction.bPresent = true;
snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", edxreg >> 24); /* Flawfinder: ignore */
CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF;
CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF;
}
// Note: I'm not absolutely sure that the L1 page size code (the
// 'if/else if/else if' structs above) really detects the real page
// size for the TLB. Somebody should check it....
// Now we read the ext. CPUID level 0x80000006
__asm
{
mov eax, 0x80000006
cpuid
mov eaxreg, eax
mov ebxreg, ebx
mov ecxreg, ecx
}
// We only mask the unified L2 cache masks (never heard of an
// L2 cache that is divided in data and code parts)
if (((ecxreg >> 12) & 0xF) > 0)
{
CPUInfo._L2.bPresent = true;
snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16); /* Flawfinder: ignore */