00001
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00049
00050 #include "linden_common.h"
00051
00052 #include "processor.h"
00053
00054 #include <memory>
00055
00056 #if LL_WINDOWS
00057 # define WIN32_LEAN_AND_MEAN
00058 # include <winsock2.h>
00059 # include <windows.h>
00060 #endif
00061
00062 #if !LL_DARWIN && !LL_SOLARIS
00063
00064 #ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
00065
00066 #define FORCEINLINE __forceinline
00067 #else
00068 #define FORCEINLINE
00069 #endif
00070
00071
00072
00074 #define CheckBit(var, bit) ((var & (1 << bit)) ? true : false)
00075
00076 #ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
00077
00078 static void _Delay(unsigned int ms)
00079 {
00080 LARGE_INTEGER freq, c1, c2;
00081 __int64 x;
00082
00083
00084 if (!QueryPerformanceFrequency(&freq))
00085 return;
00086
00087
00088 x = freq.QuadPart/1000*ms;
00089
00090
00091 QueryPerformanceCounter(&c1);
00092 do
00093 {
00094
00095 QueryPerformanceCounter(&c2);
00096 }while(c2.QuadPart-c1.QuadPart < x);
00097
00098 }
00099 #endif
00100
00101
00102
00103
00105 CProcessor::CProcessor()
00106 {
00107 uqwFrequency = 0;
00108 strCPUName[0] = 0;
00109 memset(&CPUInfo, 0, sizeof(CPUInfo));
00110 }
00111
00112
00113
00114
00116 F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
00117 {
00118 #ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
00119 return 0;
00120 #else
00121
00122
00123 if (uiMeasureMSecs < 1)
00124 {
00125
00126 if (uqwFrequency > 0)
00127 return uqwFrequency;
00128 else
00129 return 0;
00130 }
00131
00132
00133 if (!CheckCPUIDPresence())
00134 return 0;
00135
00136
00137 unsigned long reg;
00138 __asm
00139 {
00140 mov eax, 1
00141 cpuid
00142 mov reg, edx
00143 }
00144
00145
00146
00147 if (!(reg & (1 << 4)))
00148 return 0;
00149
00150
00151
00152
00153 __int64 starttime, endtime, timedif, freq, start, end, dif;
00154 if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq))
00155 return 0;
00156
00157
00158
00159
00160 HANDLE hProcess = GetCurrentProcess();
00161 HANDLE hThread = GetCurrentThread();
00162 unsigned long dwCurPriorityClass = GetPriorityClass(hProcess);
00163 int iCurThreadPriority = GetThreadPriority(hThread);
00164 unsigned long dwProcessMask, dwSystemMask, dwNewMask = 1;
00165 GetProcessAffinityMask(hProcess, &dwProcessMask, &dwSystemMask);
00166
00167 SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
00168 SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
00169 SetProcessAffinityMask(hProcess, dwNewMask);
00170
00171
00172
00173 __asm cpuid
00174
00175
00176 QueryPerformanceCounter((LARGE_INTEGER *) &starttime);
00177
00178
00179 __asm
00180 {
00181 rdtsc
00182 mov dword ptr [start+4], edx
00183 mov dword ptr [start], eax
00184 }
00185
00186
00187 _Delay(uiMeasureMSecs);
00188
00189
00190
00191 QueryPerformanceCounter((LARGE_INTEGER *) &endtime);
00192
00193
00194 __asm
00195 {
00196 rdtsc
00197 mov dword ptr [end+4], edx
00198 mov dword ptr [end], eax
00199 }
00200
00201
00202 SetProcessAffinityMask(hProcess, dwProcessMask);
00203 SetThreadPriority(hThread, iCurThreadPriority);
00204 SetPriorityClass(hProcess, dwCurPriorityClass);
00205
00206
00207 dif = end - start;
00208 timedif = endtime - starttime;
00209
00210
00211
00212 uqwFrequency = (F64)dif / (((F64)timedif) / freq);
00213
00214
00215
00216 return uqwFrequency;
00217 #endif
00218 }
00219
00220
00221
00222
00224 bool CProcessor::AnalyzeIntelProcessor()
00225 {
00226 #if LL_WINDOWS
00227 unsigned long eaxreg, ebxreg, edxreg;
00228
00229
00230 if (!CheckCPUIDPresence())
00231 return false;
00232
00233
00234 __asm
00235 {
00236 mov eax, 1
00237 cpuid
00238 mov eaxreg, eax
00239 mov ebxreg, ebx
00240 mov edxreg, edx
00241 }
00242
00243
00244
00245 CPUInfo.uiStepping = eaxreg & 0xF;
00246 CPUInfo.uiModel = (eaxreg >> 4) & 0xF;
00247 CPUInfo.uiFamily = (eaxreg >> 8) & 0xF;
00248 CPUInfo.uiType = (eaxreg >> 12) & 0x3;
00249 CPUInfo.uiBrandID = ebxreg & 0xF;
00250
00251 static const char* INTEL_BRAND[] =
00252 {
00253 "",
00254 "0.18 micron Intel Celeron",
00255 "0.18 micron Intel Pentium III",
00256 "0.13 micron Intel Celeron",
00257 "0.13 micron Intel Pentium III",
00258 "",
00259 "0.13 micron Intel Pentium III Mobile",
00260 "0.13 micron Intel Celeron Mobile",
00261 "0.18 micron Intel Pentium 4",
00262 "0.13 micron Intel Pentium 4",
00263 "0.13 micron Intel Celeron",
00264 "0.13 micron Intel Pentium 4 Xeon",
00265 "Intel Xeon MP",
00266 "",
00267 "0.18 micron Intel Pentium 4 Xeon",
00268 "Mobile Intel Celeron",
00269 "",
00270 "Mobile Genuine Intel",
00271 "Intel Celeron M",
00272 "Mobile Intel Celeron",
00273 "Intel Celeron",
00274 "Mobile Genuine Intel",
00275 "Intel Pentium M",
00276 "Mobile Intel Celeron",
00277 };
00278
00279
00280
00281 if (CPUInfo.uiBrandID < (sizeof(INTEL_BRAND)/sizeof(INTEL_BRAND[0])))
00282 {
00283 strcpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID]);
00284
00285 if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6)
00286 {
00287 strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon");
00288 }
00289 }
00290
00291
00292 switch (CPUInfo.uiFamily)
00293 {
00294 case 3:
00295 strcpy(CPUInfo.strFamily, "Intel i386");
00296 break;
00297 case 4:
00298 strcpy(CPUInfo.strFamily, "Intel i486");
00299 break;
00300 case 5:
00301 strcpy(CPUInfo.strFamily, "Intel Pentium");
00302 break;
00303 case 6:
00304 strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core");
00305 break;
00306 case 15:
00307
00308 CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF;
00309 switch (CPUInfo.uiExtendedFamily)
00310 {
00311 case 0:
00312 strcpy(CPUInfo.strFamily, "Intel Pentium 4");
00313 break;
00314 case 1:
00315 strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)");
00316 break;
00317 default:
00318 strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+");
00319 break;
00320 }
00321 break;
00322 default:
00323 strcpy(CPUInfo.strFamily, "Unknown");
00324 break;
00325 }
00326
00327
00328 switch (CPUInfo.uiFamily)
00329 {
00330 case 3:
00331 strcpy(CPUInfo.strModel, "Unknown Intel i386");
00332 strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1);
00333 break;
00334 case 4:
00335 switch (CPUInfo.uiModel)
00336 {
00337 case 0:
00338 strcpy(CPUInfo.strModel, "Intel i486 DX-25/33");
00339 strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1);
00340 break;
00341 case 1:
00342 strcpy(CPUInfo.strModel, "Intel i486 DX-50");
00343 strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1);
00344 break;
00345 case 2:
00346 strcpy(CPUInfo.strModel, "Intel i486 SX");
00347 strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1);
00348 break;
00349 case 3:
00350 strcpy(CPUInfo.strModel, "Intel i486 487/DX2");
00351 strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1);
00352 break;
00353 case 4:
00354 strcpy(CPUInfo.strModel, "Intel i486 SL");
00355 strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1);
00356 break;
00357 case 5:
00358 strcpy(CPUInfo.strModel, "Intel i486 SX2");
00359 strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1);
00360 break;
00361 case 7:
00362 strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2");
00363 strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1);
00364 break;
00365 case 8:
00366 strcpy(CPUInfo.strModel, "Intel i486 DX4");
00367 strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1);
00368 break;
00369 case 9:
00370 strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4");
00371 strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1);
00372 break;
00373 default:
00374 strcpy(CPUInfo.strModel, "Unknown Intel i486");
00375 strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1);
00376 break;
00377 }
00378 break;
00379 case 5:
00380 switch (CPUInfo.uiModel)
00381 {
00382 case 0:
00383 strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)");
00384 strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1);
00385 break;
00386 case 1:
00387 strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)");
00388 strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1);
00389 break;
00390 case 2:
00391 strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)");
00392 strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1);
00393 break;
00394 case 3:
00395 strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)");
00396 strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00397 break;
00398 case 4:
00399 strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)");
00400 strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00401 break;
00402 case 7:
00403 strcpy(CPUInfo.strModel, "Intel Pentium (P54C)");
00404 strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00405 break;
00406 case 8:
00407 strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron");
00408 strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1));
00409 break;
00410 default:
00411 strcpy(CPUInfo.strModel, "Unknown Intel Pentium");
00412 strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00413 break;
00414 }
00415 break;
00416 case 6:
00417 switch (CPUInfo.uiModel)
00418 {
00419 case 0:
00420 strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)");
00421 strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00422 break;
00423 case 1:
00424 strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)");
00425 strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00426 break;
00427 case 3:
00428 strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron");
00429 strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00430 break;
00431 case 5:
00432 strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron");
00433 strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00434 break;
00435 case 6:
00436 strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache");
00437 strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00438 break;
00439 case 7:
00440 strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron");
00441 strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00442 break;
00443 case 8:
00444 strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");
00445
00446 switch (CPUInfo.uiBrandID)
00447 {
00448 case 1:
00449 strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00450 break;
00451 case 2:
00452 strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00453 break;
00454 case 3:
00455 strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00456 break;
00457 default:
00458 strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00459 break;
00460 }
00461 break;
00462 case 9:
00463 strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");
00464 strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1));
00465 break;
00466 case 0xA:
00467 strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");
00468
00469 switch (CPUInfo.uiBrandID)
00470 {
00471 case 1:
00472 strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00473 break;
00474 case 2:
00475 strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00476 break;
00477 case 3:
00478 strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00479 break;
00480 default:
00481 strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00482 break;
00483 }
00484 break;
00485 case 0xB:
00486 strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron");
00487
00488 switch (CPUInfo.uiBrandID)
00489 {
00490 case 3:
00491 strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00492 break;
00493 case 4:
00494 strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00495 break;
00496 case 7:
00497 strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00498 break;
00499 default:
00500 strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1));
00501 break;
00502 }
00503 break;
00504 case 0xD:
00505 strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");
00506 strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1));
00507 break;
00508 case 0xE:
00509 strcpy(CPUInfo.strModel, "Intel Core Series Processor");
00510 strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1));
00511 break;
00512 case 0xF:
00513 strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor");
00514 strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1));
00515 break;
00516 default:
00517 strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core");
00518 strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00519 break;
00520 }
00521 break;
00522 case 15:
00523
00524 CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF;
00525 switch (CPUInfo.uiModel)
00526 {
00527 case 0:
00528 if ((CPUInfo.uiBrandID) == 8)
00529 {
00530 strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)");
00531 strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1));
00532 }
00533 else
00534 {
00535 strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)");
00536 strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1);
00537 }
00538 break;
00539 case 1:
00540 if ((CPUInfo.uiBrandID) == 8)
00541 {
00542 strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette");
00543 strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1);
00544 }
00545 else
00546 {
00547 strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon");
00548 strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1);
00549 }
00550 break;
00551 case 2:
00552 if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA))
00553 {
00554 strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood");
00555 strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1);
00556 }
00557 else
00558 {
00559 strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon");
00560 strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1);
00561 }
00562 break;
00563 default:
00564 strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4");
00565 strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1);
00566 break;
00567 }
00568 break;
00569 default:
00570 strcpy(CPUInfo.strModel, "Unknown Intel model");
00571 strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1);
00572 break;
00573 }
00574
00575
00576
00577
00578 if (CPUInfo.MaxSupportedLevel >= 3)
00579 {
00580
00581 unsigned long sig1, sig2, sig3;
00582 __asm
00583 {
00584 mov eax, 1
00585 cpuid
00586 mov sig1, eax
00587 mov eax, 3
00588 cpuid
00589 mov sig2, ecx
00590 mov sig3, edx
00591 }
00592
00593 snprintf(
00594 CPUInfo.strProcessorSerial,
00595 sizeof(CPUInfo.strProcessorSerial),
00596 "%04lX-%04lX-%04lX-%04lX-%04lX-%04lX",
00597 sig1 >> 16,
00598 sig1 & 0xFFFF,
00599 sig3 >> 16,
00600 sig3 & 0xFFFF,
00601 sig2 >> 16, sig2 & 0xFFFF);
00602 }
00603 else
00604 {
00605
00606 snprintf(
00607 CPUInfo.strProcessorSerial,
00608 sizeof(CPUInfo.strProcessorSerial),
00609 "No Processor Serial Number");
00610 }
00611
00612
00613 GetStandardProcessorExtensions();
00614
00615
00616
00617 GetStandardProcessorConfiguration();
00618 TranslateProcessorConfiguration();
00619
00620
00621 return true;
00622 #else
00623 return FALSE;
00624 #endif
00625 }
00626
00627
00628
00629
00631 bool CProcessor::AnalyzeAMDProcessor()
00632 {
00633 #if LL_WINDOWS
00634 unsigned long eaxreg, ebxreg, ecxreg, edxreg;
00635
00636
00637 if (!CheckCPUIDPresence())
00638 return 0;
00639
00640
00641 __asm
00642 {
00643 mov eax, 1
00644 cpuid
00645 mov eaxreg, eax
00646 mov ebxreg, ebx
00647 mov edxreg, edx
00648 }
00649
00650
00651 CPUInfo.uiStepping = eaxreg & 0xF;
00652 CPUInfo.uiModel = (eaxreg >> 4) & 0xF;
00653 CPUInfo.uiFamily = (eaxreg >> 8) & 0xF;
00654 CPUInfo.uiType = (eaxreg >> 12) & 0x3;
00655
00656
00657 if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004)
00658 {
00659
00660 char tmp[52];
00661 memset(tmp, 0, sizeof(tmp));
00662 __asm
00663 {
00664 mov eax, 0x80000002
00665 cpuid
00666 mov dword ptr [tmp], eax
00667 mov dword ptr [tmp+4], ebx
00668 mov dword ptr [tmp+8], ecx
00669 mov dword ptr [tmp+12], edx
00670 mov eax, 0x80000003
00671 cpuid
00672 mov dword ptr [tmp+16], eax
00673 mov dword ptr [tmp+20], ebx
00674 mov dword ptr [tmp+24], ecx
00675 mov dword ptr [tmp+28], edx
00676 mov eax, 0x80000004
00677 cpuid
00678 mov dword ptr [tmp+32], eax
00679 mov dword ptr [tmp+36], ebx
00680 mov dword ptr [tmp+40], ecx
00681 mov dword ptr [tmp+44], edx
00682 }
00683
00684 strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1);
00685 CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
00686 }
00687 else
00688 {
00689
00690 strcpy(CPUInfo.strBrandID, "");
00691 }
00692
00693
00694 switch(CPUInfo.uiFamily)
00695 {
00696 case 4:
00697 switch (CPUInfo.uiModel)
00698 {
00699 case 3:
00700 case 7:
00701 case 8:
00702 case 9:
00703 strcpy(CPUInfo.strFamily, "AMD 80486");
00704 break;
00705 case 0xE:
00706 case 0xF:
00707 strcpy(CPUInfo.strFamily, "AMD 5x86");
00708 break;
00709 default:
00710 strcpy(CPUInfo.strFamily, "Unknown family");
00711 break;
00712 }
00713 break;
00714 case 5:
00715 switch (CPUInfo.uiModel)
00716 {
00717 case 0:
00718 case 1:
00719 case 2:
00720 case 3:
00721 strcpy(CPUInfo.strFamily, "AMD K5");
00722 break;
00723 case 6:
00724 case 7:
00725 case 8:
00726 case 9:
00727 strcpy(CPUInfo.strFamily, "AMD K6");
00728 break;
00729 default:
00730 strcpy(CPUInfo.strFamily, "Unknown family");
00731 break;
00732 }
00733 break;
00734 case 6:
00735 strcpy(CPUInfo.strFamily, "AMD K7");
00736 break;
00737 default:
00738 strcpy(CPUInfo.strFamily, "Unknown family");
00739 break;
00740 }
00741
00742
00743
00744 switch (CPUInfo.uiFamily)
00745 {
00746 case 4:
00747 switch (CPUInfo.uiModel)
00748 {
00749 case 3:
00750 strcpy(CPUInfo.strModel, "AMD 80486 DX2");
00751 strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1);
00752 break;
00753 case 7:
00754 strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2");
00755 strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1);
00756 break;
00757 case 8:
00758 strcpy(CPUInfo.strModel, "AMD 80486 DX4");
00759 strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1);
00760 break;
00761 case 9:
00762 strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4");
00763 strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1);
00764 break;
00765 case 0xE:
00766 strcpy(CPUInfo.strModel, "AMD 5x86");
00767 strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1);
00768 break;
00769 case 0xF:
00770 strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced");
00771 strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1);
00772 break;
00773 default:
00774 strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model");
00775 strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);
00776 break;
00777 }
00778 break;
00779 case 5:
00780 switch (CPUInfo.uiModel)
00781 {
00782 case 0:
00783 strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)");
00784 strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1);
00785 break;
00786 case 1:
00787 strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)");
00788 strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1);
00789 break;
00790 case 2:
00791 strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)");
00792 strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1);
00793 break;
00794 case 3:
00795 strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)");
00796 strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1);
00797 break;
00798 case 6:
00799 strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)");
00800 strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);
00801 break;
00802 case 7:
00803 strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)");
00804 strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);
00805 break;
00806 case 8:
00807 strcpy(CPUInfo.strModel, "AMD K6-2");
00808 strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1);
00809 break;
00810 case 9:
00811 strcpy(CPUInfo.strModel, "AMD K6-III");
00812 strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1);
00813 break;
00814 case 0xD:
00815 strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)");
00816 strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);
00817 break;
00818 default:
00819 strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model");
00820 strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);
00821 break;
00822 }
00823 break;
00824 case 6:
00825 switch (CPUInfo.uiModel)
00826 {
00827 case 1:
00828 strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)");
00829 strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);
00830 break;
00831 case 2:
00832 strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)");
00833 strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);
00834 break;
00835 case 3:
00836 strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)");
00837 strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1);
00838 break;
00839 case 4:
00840 strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)");
00841 strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1);
00842 break;
00843 case 6:
00844 strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)");
00845 strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1);
00846 break;
00847 case 7:
00848 strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)");
00849 strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1);
00850 break;
00851 default:
00852 strcpy(CPUInfo.strModel, "Unknown AMD K7 model");
00853 strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);
00854 break;
00855 }
00856 break;
00857 default:
00858 strcpy(CPUInfo.strModel, "Unknown AMD model");
00859 strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);
00860 break;
00861 }
00862
00863
00864
00865 GetStandardProcessorExtensions();
00866
00867
00868 if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001)
00869 {
00870
00871
00872 __asm
00873 {
00874 mov eax, 0x80000001
00875 cpuid
00876 mov edxreg, edx
00877 }
00878
00879
00880 CPUInfo._Ext.EMMX_MultimediaExtensions = CheckBit(edxreg, 22);
00881 CPUInfo._Ext.AA64_AMD64BitArchitecture = CheckBit(edxreg, 29);
00882 CPUInfo._Ext._E3DNOW_InstructionExtensions = CheckBit(edxreg, 30);
00883 CPUInfo._Ext._3DNOW_InstructionExtensions = CheckBit(edxreg, 31);
00884 }
00885
00886
00887
00888 if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006)
00889 {
00890
00891 __asm
00892 {
00893 mov eax, 0x80000005
00894 cpuid
00895 mov eaxreg, eax
00896 mov ebxreg, ebx
00897 mov ecxreg, ecx
00898 mov edxreg, edx
00899 }
00900
00901
00902 if ((ebxreg >> 16) && (eaxreg >> 16))
00903 {
00904 CPUInfo._Data.bPresent = true;
00905 strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB");
00906 CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
00907 CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
00908 }
00909 else if (eaxreg >> 16)
00910 {
00911 CPUInfo._Data.bPresent = true;
00912 strcpy(CPUInfo._Data.strPageSize, "2 MB / 4MB");
00913 CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
00914 CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
00915 }
00916 else if (ebxreg >> 16)
00917 {
00918 CPUInfo._Data.bPresent = true;
00919 strcpy(CPUInfo._Data.strPageSize, "4 KB");
00920 CPUInfo._Data.uiAssociativeWays = (ebxreg >> 24) & 0xFF;
00921 CPUInfo._Data.uiEntries = (ebxreg >> 16) & 0xFF;
00922 }
00923 if (CPUInfo._Data.uiAssociativeWays == 0xFF)
00924 CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
00925
00926
00927 if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF))
00928 {
00929 CPUInfo._Instruction.bPresent = true;
00930 strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB");
00931 CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
00932 CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
00933 }
00934 else if (eaxreg & 0xFFFF)
00935 {
00936 CPUInfo._Instruction.bPresent = true;
00937 strcpy(CPUInfo._Instruction.strPageSize, "2 MB / 4MB");
00938 CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
00939 CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
00940 }
00941 else if (ebxreg & 0xFFFF)
00942 {
00943 CPUInfo._Instruction.bPresent = true;
00944 strcpy(CPUInfo._Instruction.strPageSize, "4 KB");
00945 CPUInfo._Instruction.uiAssociativeWays = (ebxreg >> 8) & 0xFF;
00946 CPUInfo._Instruction.uiEntries = ebxreg & 0xFF;
00947 }
00948 if (CPUInfo._Instruction.uiAssociativeWays == 0xFF)
00949 CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
00950
00951
00952 if ((ecxreg >> 24) > 0)
00953 {
00954 CPUInfo._L1.Data.bPresent = true;
00955 snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", ecxreg >> 24);
00956 CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF;
00957 CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF;
00958 }
00959
00960 if ((edxreg >> 24) > 0)
00961 {
00962 CPUInfo._L1.Instruction.bPresent = true;
00963 snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", edxreg >> 24);
00964 CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF;
00965 CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF;
00966 }
00967
00968
00969
00970
00971
00972
00973 __asm
00974 {
00975 mov eax, 0x80000006
00976 cpuid
00977 mov eaxreg, eax
00978 mov ebxreg, ebx
00979 mov ecxreg, ecx
00980 }
00981
00982
00983
00984 if (((ecxreg >> 12) & 0xF) > 0)
00985 {
00986 CPUInfo._L2.bPresent = true;
00987 snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16);
00988 switch ((ecxreg >> 12) & 0xF)
00989 {
00990 case 1:
00991 CPUInfo._L2.uiAssociativeWays = 1;
00992 break;
00993 case 2:
00994 CPUInfo._L2.uiAssociativeWays = 2;
00995 break;
00996 case 4:
00997 CPUInfo._L2.uiAssociativeWays = 4;
00998 break;
00999 case 6:
01000 CPUInfo._L2.uiAssociativeWays = 8;
01001 break;
01002 case 8:
01003 CPUInfo._L2.uiAssociativeWays = 16;
01004 break;
01005 case 0xF:
01006 CPUInfo._L2.uiAssociativeWays = (unsigned int) -1;
01007 break;
01008 default:
01009 CPUInfo._L2.uiAssociativeWays = 0;
01010 break;
01011 }
01012 CPUInfo._L2.uiLineSize = ecxreg & 0xFF;
01013 }
01014 }
01015 else
01016 {
01017
01018
01019 GetStandardProcessorConfiguration();
01020 }
01021
01022 TranslateProcessorConfiguration();
01023
01024
01025 return true;
01026 #else
01027 return FALSE;
01028 #endif
01029 }
01030
01031
01032
01033
01035 bool CProcessor::AnalyzeUnknownProcessor()
01036 {
01037 #if LL_WINDOWS
01038 unsigned long eaxreg, ebxreg;
01039
01040
01041 if (!CheckCPUIDPresence())
01042 return false;
01043
01044
01045
01046 __asm
01047 {
01048 mov eax, 1
01049 cpuid
01050 mov eaxreg, eax
01051 mov ebxreg, ebx
01052 }
01053
01054 CPUInfo.uiStepping = eaxreg & 0xF;
01055 CPUInfo.uiModel = (eaxreg >> 4) & 0xF;
01056 CPUInfo.uiFamily = (eaxreg >> 8) & 0xF;
01057 CPUInfo.uiType = (eaxreg >> 12) & 0x3;
01058
01059
01060 CPUInfo.uiBrandID = ebxreg & 0xF;
01061
01062
01063 GetStandardProcessorExtensions();
01064
01065
01066 strcpy(strCPUName, "Unknown");
01067
01068 strcpy(CPUInfo._Data.strTLB, "Unknown");
01069 strcpy(CPUInfo._Instruction.strTLB, "Unknown");
01070
01071 strcpy(CPUInfo._Trace.strCache, "Unknown");
01072 strcpy(CPUInfo._L1.Data.strCache, "Unknown");
01073 strcpy(CPUInfo._L1.Instruction.strCache, "Unknown");
01074 strcpy(CPUInfo._L2.strCache, "Unknown");
01075 strcpy(CPUInfo._L3.strCache, "Unknown");
01076
01077 strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported");
01078
01079
01080 snprintf(CPUInfo.strBrandID, sizeof(CPUInfo.strBrandID), "Brand-ID number %d", CPUInfo.uiBrandID);
01081 snprintf(CPUInfo.strFamily, sizeof(CPUInfo.strFamily), "Family number %d", CPUInfo.uiFamily);
01082 snprintf(CPUInfo.strModel, sizeof(CPUInfo.strModel), "Model number %d", CPUInfo.uiModel);
01083
01084
01085 return true;
01086 #else
01087 return FALSE;
01088 #endif
01089 }
01090
01091
01092
01093
01094
01096 bool CProcessor::CheckCPUIDPresence()
01097 {
01098 #if LL_WINDOWS
01099 unsigned long BitChanged;
01100
01101
01102
01103 __asm
01104 {
01105 pushfd
01106 pop eax
01107 mov ebx, eax
01108 xor eax, 0x00200000
01109 push eax
01110 popfd
01111 pushfd
01112 pop eax
01113 xor eax,ebx
01114 mov BitChanged, eax
01115 }
01116
01117 return ((BitChanged) ? true : false);
01118 #else
01119 return FALSE;
01120 #endif
01121 }
01122
01123
01124
01125
01126
01128 void CProcessor::DecodeProcessorConfiguration(unsigned int cfg)
01129 {
01130
01131 cfg &= 0xFF;
01132
01133
01134 switch(cfg)
01135 {
01136 case 0:
01137 break;
01138 case 0x1:
01139 CPUInfo._Instruction.bPresent = true;
01140 strcpy(CPUInfo._Instruction.strPageSize, "4 KB");
01141 CPUInfo._Instruction.uiAssociativeWays = 4;
01142 CPUInfo._Instruction.uiEntries = 32;
01143 break;
01144 case 0x2:
01145 CPUInfo._Instruction.bPresent = true;
01146 strcpy(CPUInfo._Instruction.strPageSize, "4 MB");
01147 CPUInfo._Instruction.uiAssociativeWays = 4;
01148 CPUInfo._Instruction.uiEntries = 2;
01149 break;
01150 case 0x3:
01151 CPUInfo._Data.bPresent = true;
01152 strcpy(CPUInfo._Data.strPageSize, "4 KB");
01153 CPUInfo._Data.uiAssociativeWays = 4;
01154 CPUInfo._Data.uiEntries = 64;
01155 break;
01156 case 0x4:
01157 CPUInfo._Data.bPresent = true;
01158 strcpy(CPUInfo._Data.strPageSize, "4 MB");
01159 CPUInfo._Data.uiAssociativeWays = 4;
01160 CPUInfo._Data.uiEntries = 8;
01161 break;
01162 case 0x6:
01163 CPUInfo._L1.Instruction.bPresent = true;
01164 strcpy(CPUInfo._L1.Instruction.strSize, "8 KB");
01165 CPUInfo._L1.Instruction.uiAssociativeWays = 4;
01166 CPUInfo._L1.Instruction.uiLineSize = 32;
01167 break;
01168 case 0x8:
01169 CPUInfo._L1.Instruction.bPresent = true;
01170 strcpy(CPUInfo._L1.Instruction.strSize, "16 KB");
01171 CPUInfo._L1.Instruction.uiAssociativeWays = 4;
01172 CPUInfo._L1.Instruction.uiLineSize = 32;
01173 break;
01174 case 0xA:
01175 CPUInfo._L1.Data.bPresent = true;
01176 strcpy(CPUInfo._L1.Data.strSize, "8 KB");
01177 CPUInfo._L1.Data.uiAssociativeWays = 2;
01178 CPUInfo._L1.Data.uiLineSize = 32;
01179 break;
01180 case 0xC:
01181 CPUInfo._L1.Data.bPresent = true;
01182 strcpy(CPUInfo._L1.Data.strSize, "16 KB");
01183 CPUInfo._L1.Data.uiAssociativeWays = 4;
01184 CPUInfo._L1.Data.uiLineSize = 32;
01185 break;
01186 case 0x22:
01187 CPUInfo._L3.bPresent = true;
01188 strcpy(CPUInfo._L3.strSize, "512 KB");
01189 CPUInfo._L3.uiAssociativeWays = 4;
01190 CPUInfo._L3.uiLineSize = 64;
01191 CPUInfo._L3.bSectored = true;
01192 break;
01193 case 0x23:
01194 CPUInfo._L3.bPresent = true;
01195 strcpy(CPUInfo._L3.strSize, "1024 KB");
01196 CPUInfo._L3.uiAssociativeWays = 8;
01197 CPUInfo._L3.uiLineSize = 64;
01198 CPUInfo._L3.bSectored = true;
01199 break;
01200 case 0x25:
01201 CPUInfo._L3.bPresent = true;
01202 strcpy(CPUInfo._L3.strSize, "2048 KB");
01203 CPUInfo._L3.uiAssociativeWays = 8;
01204 CPUInfo._L3.uiLineSize = 64;
01205 CPUInfo._L3.bSectored = true;
01206 break;
01207 case 0x29:
01208 CPUInfo._L3.bPresent = true;
01209 strcpy(CPUInfo._L3.strSize, "4096 KB");
01210 CPUInfo._L3.uiAssociativeWays = 8;
01211 CPUInfo._L3.uiLineSize = 64;
01212 CPUInfo._L3.bSectored = true;
01213 break;
01214 case 0x40:
01215 break;
01216 case 0x41:
01217 CPUInfo._L2.bPresent = true;
01218 strcpy(CPUInfo._L2.strSize, "128 KB");
01219 CPUInfo._L2.uiAssociativeWays = 4;
01220 CPUInfo._L2.uiLineSize = 32;
01221 break;
01222 case 0x42:
01223 CPUInfo._L2.bPresent = true;
01224 strcpy(CPUInfo._L2.strSize, "256 KB");
01225 CPUInfo._L2.uiAssociativeWays = 4;
01226 CPUInfo._L2.uiLineSize = 32;
01227 break;
01228 case 0x43:
01229 CPUInfo._L2.bPresent = true;
01230 strcpy(CPUInfo._L2.strSize, "512 KB");
01231 CPUInfo._L2.uiAssociativeWays = 4;
01232 CPUInfo._L2.uiLineSize = 32;
01233 break;
01234 case 0x44:
01235 CPUInfo._L2.bPresent = true;
01236 strcpy(CPUInfo._L2.strSize, "1 MB");
01237 CPUInfo._L2.uiAssociativeWays = 4;
01238 CPUInfo._L2.uiLineSize = 32;
01239 break;
01240 case 0x45:
01241 CPUInfo._L2.bPresent = true;
01242 strcpy(CPUInfo._L2.strSize, "2 MB");
01243 CPUInfo._L2.uiAssociativeWays = 4;
01244 CPUInfo._L2.uiLineSize = 32;
01245 break;
01246 case 0x50:
01247 CPUInfo._Instruction.bPresent = true;
01248 strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB");
01249 CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
01250 CPUInfo._Instruction.uiEntries = 64;
01251 break;
01252 case 0x51:
01253 CPUInfo._Instruction.bPresent = true;
01254 strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB");
01255 CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
01256 CPUInfo._Instruction.uiEntries = 128;
01257 break;
01258 case 0x52:
01259 CPUInfo._Instruction.bPresent = true;
01260 strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB");
01261 CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
01262 CPUInfo._Instruction.uiEntries = 256;
01263 break;
01264 case 0x5B:
01265 CPUInfo._Data.bPresent = true;
01266 strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");
01267 CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
01268 CPUInfo._Data.uiEntries = 64;
01269 break;
01270 case 0x5C:
01271 CPUInfo._Data.bPresent = true;
01272 strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");
01273 CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
01274 CPUInfo._Data.uiEntries = 128;
01275 break;
01276 case 0x5d:
01277 CPUInfo._Data.bPresent = true;
01278 strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");
01279 CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
01280 CPUInfo._Data.uiEntries = 256;
01281 break;
01282 case 0x66:
01283 CPUInfo._L1.Data.bPresent = true;
01284 strcpy(CPUInfo._L1.Data.strSize, "8 KB");
01285 CPUInfo._L1.Data.uiAssociativeWays = 4;
01286 CPUInfo._L1.Data.uiLineSize = 64;
01287 break;
01288 case 0x67:
01289 CPUInfo._L1.Data.bPresent = true;
01290 strcpy(CPUInfo._L1.Data.strSize, "16 KB");
01291 CPUInfo._L1.Data.uiAssociativeWays = 4;
01292 CPUInfo._L1.Data.uiLineSize = 64;
01293 break;
01294 case 0x68:
01295 CPUInfo._L1.Data.bPresent = true;
01296 strcpy(CPUInfo._L1.Data.strSize, "32 KB");
01297 CPUInfo._L1.Data.uiAssociativeWays = 4;
01298 CPUInfo._L1.Data.uiLineSize = 64;
01299 break;
01300 case 0x70:
01301 CPUInfo._Trace.bPresent = true;
01302 strcpy(CPUInfo._Trace.strSize, "12 K-micro-ops");
01303 CPUInfo._Trace.uiAssociativeWays = 4;
01304 break;
01305 case 0x71:
01306 CPUInfo._Trace.bPresent = true;
01307 strcpy(CPUInfo._Trace.strSize, "16 K-micro-ops");
01308 CPUInfo._Trace.uiAssociativeWays = 4;
01309 break;
01310 case 0x72:
01311 CPUInfo._Trace.bPresent = true;
01312 strcpy(CPUInfo._Trace.strSize, "32 K-micro-ops");
01313 CPUInfo._Trace.uiAssociativeWays = 4;
01314 break;
01315 case 0x79:
01316 CPUInfo._L2.bPresent = true;
01317 strcpy(CPUInfo._L2.strSize, "128 KB");
01318 CPUInfo._L2.uiAssociativeWays = 8;
01319 CPUInfo._L2.uiLineSize = 64;
01320 CPUInfo._L2.bSectored = true;
01321 break;
01322 case 0x7A:
01323 CPUInfo._L2.bPresent = true;
01324 strcpy(CPUInfo._L2.strSize, "256 KB");
01325 CPUInfo._L2.uiAssociativeWays = 8;
01326 CPUInfo._L2.uiLineSize = 64;
01327 CPUInfo._L2.bSectored = true;
01328 break;
01329 case 0x7B:
01330 CPUInfo._L2.bPresent = true;
01331 strcpy(CPUInfo._L2.strSize, "512 KB");
01332 CPUInfo._L2.uiAssociativeWays = 8;
01333 CPUInfo._L2.uiLineSize = 64;
01334 CPUInfo._L2.bSectored = true;
01335 break;
01336 case 0x7C:
01337 CPUInfo._L2.bPresent = true;
01338 strcpy(CPUInfo._L2.strSize, "1 MB");
01339 CPUInfo._L2.uiAssociativeWays = 8;
01340 CPUInfo._L2.uiLineSize = 64;
01341 CPUInfo._L2.bSectored = true;
01342 break;
01343 case 0x81:
01344 CPUInfo._L2.bPresent = true;
01345 strcpy(CPUInfo._L2.strSize, "128 KB");
01346 CPUInfo._L2.uiAssociativeWays = 8;
01347 CPUInfo._L2.uiLineSize = 32;
01348 break;
01349 case 0x82:
01350 CPUInfo._L2.bPresent = true;
01351 strcpy(CPUInfo._L2.strSize, "256 KB");
01352 CPUInfo._L2.uiAssociativeWays = 8;
01353 CPUInfo._L2.uiLineSize = 32;
01354 break;
01355 case 0x83:
01356 CPUInfo._L2.bPresent = true;
01357 strcpy(CPUInfo._L2.strSize, "512 KB");
01358 CPUInfo._L2.uiAssociativeWays = 8;
01359 CPUInfo._L2.uiLineSize = 32;
01360 break;
01361 case 0x84:
01362 CPUInfo._L2.bPresent = true;
01363 strcpy(CPUInfo._L2.strSize, "1 MB");
01364 CPUInfo._L2.uiAssociativeWays = 8;
01365 CPUInfo._L2.uiLineSize = 32;
01366 break;
01367 case 0x85:
01368 CPUInfo._L2.bPresent = true;
01369 strcpy(CPUInfo._L2.strSize, "2 MB");
01370 CPUInfo._L2.uiAssociativeWays = 8;
01371 CPUInfo._L2.uiLineSize = 32;
01372 break;
01373 }
01374 }
01375
01376 FORCEINLINE static char *TranslateAssociativeWays(unsigned int uiWays, char *buf)
01377 {
01378
01379 if (uiWays == ((unsigned int) -1))
01380 strcpy(buf, "fully associative");
01381 else
01382 {
01383 if (uiWays == 1)
01384 strcpy(buf, "direct mapped");
01385 else if (uiWays == 0)
01386 strcpy(buf, "unknown associative ways");
01387 else
01388 sprintf(buf, "%d ways associative", uiWays);
01389 }
01390
01391 return buf;
01392 }
01393 FORCEINLINE static void TranslateTLB(ProcessorTLB *tlb)
01394 {
01395 char buf[64];
01396
01397
01398 if (tlb->bPresent)
01399 snprintf(tlb->strTLB,sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries);
01400 else
01401 strcpy(tlb->strTLB, "Not present");
01402 }
01403 FORCEINLINE static void TranslateCache(ProcessorCache *cache)
01404 {
01405 char buf[64];
01406
01407
01408 if (cache->bPresent)
01409 {
01410
01411 snprintf(cache->strCache, sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize);
01412 if (cache->bSectored)
01413 strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1);
01414 }
01415 else
01416 {
01417
01418 strcpy(cache->strCache, "Not present");
01419 }
01420 }
01421
01422
01423
01424
01425
01427 void CProcessor::TranslateProcessorConfiguration()
01428 {
01429
01430 TranslateTLB(&CPUInfo._Data);
01431 TranslateTLB(&CPUInfo._Instruction);
01432
01433 TranslateCache(&CPUInfo._Trace);
01434
01435 TranslateCache(&CPUInfo._L1.Instruction);
01436 TranslateCache(&CPUInfo._L1.Data);
01437 TranslateCache(&CPUInfo._L2);
01438 TranslateCache(&CPUInfo._L3);
01439 }
01440
01441
01442
01443
01445 void CProcessor::GetStandardProcessorConfiguration()
01446 {
01447 #if LL_WINDOWS
01448 unsigned long eaxreg, ebxreg, ecxreg, edxreg;
01449
01450
01451 if (!CheckCPUIDPresence())
01452 return;
01453
01454
01455
01456 if (CPUInfo.MaxSupportedLevel >= 2)
01457 {
01458
01459 unsigned long count, num = 255;
01460 for (count = 0; count < num; count++)
01461 {
01462 __asm
01463 {
01464 mov eax, 2
01465 cpuid
01466 mov eaxreg, eax
01467 mov ebxreg, ebx
01468 mov ecxreg, ecx
01469 mov edxreg, edx
01470 }
01471
01472 num = eaxreg & 0xFF;
01473
01474
01475 DecodeProcessorConfiguration(eaxreg >> 8);
01476 DecodeProcessorConfiguration(eaxreg >> 16);
01477 DecodeProcessorConfiguration(eaxreg >> 24);
01478
01479
01480 if ((ebxreg & 0x80000000) == 0)
01481 {
01482 DecodeProcessorConfiguration(ebxreg);
01483 DecodeProcessorConfiguration(ebxreg >> 8);
01484 DecodeProcessorConfiguration(ebxreg >> 16);
01485 DecodeProcessorConfiguration(ebxreg >> 24);
01486 }
01487
01488 if ((ecxreg & 0x80000000) == 0)
01489 {
01490 DecodeProcessorConfiguration(ecxreg);
01491 DecodeProcessorConfiguration(ecxreg >> 8);
01492 DecodeProcessorConfiguration(ecxreg >> 16);
01493 DecodeProcessorConfiguration(ecxreg >> 24);
01494 }
01495
01496 if ((edxreg & 0x80000000) == 0)
01497 {
01498 DecodeProcessorConfiguration(edxreg);
01499 DecodeProcessorConfiguration(edxreg >> 8);
01500 DecodeProcessorConfiguration(edxreg >> 16);
01501 DecodeProcessorConfiguration(edxreg >> 24);
01502 }
01503 }
01504 }
01505 #endif
01506 }
01507
01508
01509
01510
01512 void CProcessor::GetStandardProcessorExtensions()
01513 {
01514 #if LL_WINDOWS
01515 unsigned long ebxreg, edxreg;
01516
01517
01518 if (!CheckCPUIDPresence())
01519 return;
01520
01521
01522 __asm
01523 {
01524 mov eax, 1
01525 cpuid
01526 mov ebxreg, ebx
01527 mov edxreg, edx
01528 }
01529
01530
01531 CPUInfo._Ext.FPU_FloatingPointUnit = CheckBit(edxreg, 0);
01532 CPUInfo._Ext.VME_Virtual8086ModeEnhancements = CheckBit(edxreg, 1);
01533 CPUInfo._Ext.DE_DebuggingExtensions = CheckBit(edxreg, 2);
01534 CPUInfo._Ext.PSE_PageSizeExtensions = CheckBit(edxreg, 3);
01535 CPUInfo._Ext.TSC_TimeStampCounter = CheckBit(edxreg, 4);
01536 CPUInfo._Ext.MSR_ModelSpecificRegisters = CheckBit(edxreg, 5);
01537 CPUInfo._Ext.PAE_PhysicalAddressExtension = CheckBit(edxreg, 6);
01538 CPUInfo._Ext.MCE_MachineCheckException = CheckBit(edxreg, 7);
01539 CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = CheckBit(edxreg, 8);
01540 CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController = CheckBit(edxreg, 9);
01541 CPUInfo._Ext.APIC_ID = (ebxreg >> 24) & 0xFF;
01542 CPUInfo._Ext.SEP_FastSystemCall = CheckBit(edxreg, 11);
01543 CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters = CheckBit(edxreg, 12);
01544 CPUInfo._Ext.PGE_PTE_GlobalFlag = CheckBit(edxreg, 13);
01545 CPUInfo._Ext.MCA_MachineCheckArchitecture = CheckBit(edxreg, 14);
01546 CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions = CheckBit(edxreg, 15);
01547 CPUInfo._Ext.FGPAT_PageAttributeTable = CheckBit(edxreg, 16);
01548 CPUInfo._Ext.PSE36_36bitPageSizeExtension = CheckBit(edxreg, 17);
01549 CPUInfo._Ext.PN_ProcessorSerialNumber = CheckBit(edxreg, 18);
01550 CPUInfo._Ext.CLFSH_CFLUSH_Instruction = CheckBit(edxreg, 19);
01551 CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize = (ebxreg >> 8) & 0xFF;
01552 CPUInfo._Ext.DS_DebugStore = CheckBit(edxreg, 21);
01553 CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl = CheckBit(edxreg, 22);
01554 CPUInfo._Ext.MMX_MultimediaExtensions = CheckBit(edxreg, 23);
01555 CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = CheckBit(edxreg, 24);
01556 CPUInfo._Ext.SSE_StreamingSIMD_Extensions = CheckBit(edxreg, 25);
01557 CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = CheckBit(edxreg, 26);
01558 CPUInfo._Ext.Altivec_Extensions = false;
01559 CPUInfo._Ext.SS_SelfSnoop = CheckBit(edxreg, 27);
01560 CPUInfo._Ext.HT_HyperThreading = CheckBit(edxreg, 28);
01561 CPUInfo._Ext.HT_HyterThreadingSiblings = (ebxreg >> 16) & 0xFF;
01562 CPUInfo._Ext.TM_ThermalMonitor = CheckBit(edxreg, 29);
01563 CPUInfo._Ext.IA64_Intel64BitArchitecture = CheckBit(edxreg, 30);
01564 #endif
01565 }
01566
01567
01568
01569
01570
01572 const ProcessorInfo *CProcessor::GetCPUInfo()
01573 {
01574 #if LL_WINDOWS
01575 unsigned long eaxreg, ebxreg, ecxreg, edxreg;
01576
01577
01578 if (!CheckCPUIDPresence())
01579 return NULL;
01580
01581
01582
01583 __asm
01584 {
01585 mov eax, 0
01586 cpuid
01587 mov eaxreg, eax
01588 mov ebxreg, ebx
01589 mov edxreg, edx
01590 mov ecxreg, ecx
01591 }
01592
01593 *((unsigned long *) CPUInfo.strVendor) = ebxreg;
01594 *((unsigned long *) (CPUInfo.strVendor+4)) = edxreg;
01595 *((unsigned long *) (CPUInfo.strVendor+8)) = ecxreg;
01596
01597 CPUInfo.strVendor[12] = 0;
01598
01599
01600 CPUInfo.MaxSupportedLevel = eaxreg & 0xFFFF;
01601
01602
01603 __asm
01604 {
01605 mov eax, 0x80000000
01606 cpuid
01607 mov eaxreg, eax
01608 }
01609
01610 CPUInfo.MaxSupportedExtendedLevel = eaxreg;
01611
01612
01613
01614 if (!strcmp(CPUInfo.strVendor, "GenuineIntel"))
01615 {
01616 AnalyzeIntelProcessor();
01617 }
01618 else if (!strcmp(CPUInfo.strVendor, "AuthenticAMD"))
01619 {
01620 AnalyzeAMDProcessor();
01621 }
01622 else if (!strcmp(CPUInfo.strVendor, "UMC UMC UMC"))
01623 {
01624 AnalyzeUnknownProcessor();
01625 }
01626 else if (!strcmp(CPUInfo.strVendor, "CyrixInstead"))
01627 {
01628 AnalyzeUnknownProcessor();
01629 }
01630 else if (!strcmp(CPUInfo.strVendor, "NexGenDriven"))
01631 {
01632 AnalyzeUnknownProcessor();
01633 }
01634 else if (!strcmp(CPUInfo.strVendor, "CentaurHauls"))
01635 {
01636 AnalyzeUnknownProcessor();
01637 }
01638 else if (!strcmp(CPUInfo.strVendor, "RiseRiseRise"))
01639 {
01640 AnalyzeUnknownProcessor();
01641 }
01642 else if (!strcmp(CPUInfo.strVendor, "SiS SiS SiS"))
01643 {
01644 AnalyzeUnknownProcessor();
01645 }
01646 else if (!strcmp(CPUInfo.strVendor, "GenuineTMx86"))
01647 {
01648
01649 AnalyzeUnknownProcessor();
01650 }
01651 else if (!strcmp(CPUInfo.strVendor, "Geode by NSC"))
01652 {
01653 AnalyzeUnknownProcessor();
01654 }
01655 else
01656 {
01657 AnalyzeUnknownProcessor();
01658 }
01659 #endif
01660
01661 return (&CPUInfo);
01662 }
01663
01664 #elif LL_SOLARIS
01665 #include <kstat.h>
01666
01667
01668
01670 CProcessor::CProcessor()
01671 {
01672 uqwFrequency = 0;
01673 strCPUName[0] = 0;
01674 memset(&CPUInfo, 0, sizeof(CPUInfo));
01675 }
01676
01677
01678
01679
01681 F64 CProcessor::GetCPUFrequency(unsigned int )
01682 {
01683 if(uqwFrequency == 0){
01684 GetCPUInfo();
01685 }
01686
01687 return uqwFrequency;
01688 }
01689
01690
01691
01692
01693
01695 const ProcessorInfo *CProcessor::GetCPUInfo()
01696 {
01697
01698
01699
01700 int ncpus=0, i;
01701 kstat_ctl_t *kc;
01702 kstat_t *ks;
01703 kstat_named_t *ksinfo, *ksi;
01704 kstat_t *CPU_stats_list;
01705
01706 kc = kstat_open();
01707
01708 if((int)kc == -1){
01709 llwarns << "kstat_open(0 failed!" << llendl;
01710 return (&CPUInfo);
01711 }
01712
01713 for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) {
01714 if (strncmp(ks->ks_module, "cpu_info", 8) == 0 &&
01715 strncmp(ks->ks_name, "cpu_info", 8) == 0)
01716 ncpus++;
01717 }
01718
01719 if(ncpus < 1){
01720 llwarns << "No cpus found in kstats!" << llendl;
01721 return (&CPUInfo);
01722 }
01723
01724 for (ks = kc->kc_chain; ks; ks = ks->ks_next) {
01725 if (strncmp(ks->ks_module, "cpu_info", 8) == 0
01726 && strncmp(ks->ks_name, "cpu_info", 8) == 0
01727 && kstat_read(kc, ks, NULL) != -1){
01728 CPU_stats_list = ks;
01729
01730 break;
01731 }
01732 }
01733
01734 if(ncpus > 1)
01735 snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpus);
01736
01737 kstat_read(kc, CPU_stats_list, NULL);
01738 ksinfo = (kstat_named_t *)CPU_stats_list->ks_data;
01739 for(i=0; i < (int)(CPU_stats_list->ks_ndata); ++i){
01740 ksi = ksinfo++;
01741 if(!strcmp(ksi->name, "brand")){
01742 strncat(strCPUName, (char *)KSTAT_NAMED_STR_PTR(ksi),
01743 sizeof(strCPUName)-strlen(strCPUName)-1);
01744 strncat(CPUInfo.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi),
01745 sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
01746 strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1);
01747 CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
01748
01749 continue;
01750 }
01751
01752 if(!strcmp(ksi->name, "clock_MHz")){
01753 #if defined(__sparc)
01754 llinfos << "Raw kstat clock rate is: " << ksi->value.l << llendl;
01755 uqwFrequency = (F64)(ksi->value.l * 1000000);
01756 #else
01757 uqwFrequency = (F64)(ksi->value.i64 * 1000000);
01758 #endif
01759
01760 continue;
01761 }
01762
01763 #if defined(__i386)
01764 if(!strcmp(ksi->name, "vendor_id")){
01765 strncpy(CPUInfo.strVendor, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(CPUInfo.strVendor)-1);
01766
01767 continue;
01768 }
01769 #endif
01770 }
01771
01772 kstat_close(kc);
01773
01774 #if defined(__sparc) // SPARC does not define a vendor string in kstat
01775 strncpy(CPUInfo.strVendor, "Sun Microsystems, Inc.", sizeof(CPUInfo.strVendor)-1);
01776 #endif
01777
01778
01779
01780 return (&CPUInfo);
01781 }
01782
01783 #else
01784
01785
01786 #include <mach/machine.h>
01787 #include <sys/sysctl.h>
01788
01789 static char *TranslateAssociativeWays(unsigned int uiWays, char *buf)
01790 {
01791
01792 if (uiWays == ((unsigned int) -1))
01793 strcpy(buf, "fully associative");
01794 else
01795 {
01796 if (uiWays == 1)
01797 strcpy(buf, "direct mapped");
01798 else if (uiWays == 0)
01799 strcpy(buf, "unknown associative ways");
01800 else
01801 sprintf(buf, "%d ways associative", uiWays);
01802 }
01803
01804 return buf;
01805 }
01806 static void TranslateTLB(ProcessorTLB *tlb)
01807 {
01808 char buf[64];
01809
01810
01811 if (tlb->bPresent)
01812 snprintf(tlb->strTLB, sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries);
01813 else
01814 strcpy(tlb->strTLB, "Not present");
01815 }
01816 static void TranslateCache(ProcessorCache *cache)
01817 {
01818 char buf[64];
01819
01820
01821 if (cache->bPresent)
01822 {
01823
01824 snprintf(cache->strCache,sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize);
01825 if (cache->bSectored)
01826 strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1);
01827 }
01828 else
01829 {
01830
01831 strcpy(cache->strCache, "Not present");
01832 }
01833 }
01834
01835
01836
01837
01838
01840 void CProcessor::TranslateProcessorConfiguration()
01841 {
01842
01843 TranslateTLB(&CPUInfo._Data);
01844 TranslateTLB(&CPUInfo._Instruction);
01845
01846 TranslateCache(&CPUInfo._Trace);
01847
01848 TranslateCache(&CPUInfo._L1.Instruction);
01849 TranslateCache(&CPUInfo._L1.Data);
01850 TranslateCache(&CPUInfo._L2);
01851 TranslateCache(&CPUInfo._L3);
01852 }
01853
01854
01855
01856
01858 CProcessor::CProcessor()
01859 {
01860 uqwFrequency = 0;
01861 strCPUName[0] = 0;
01862 memset(&CPUInfo, 0, sizeof(CPUInfo));
01863 }
01864
01865
01866
01867
01869 F64 CProcessor::GetCPUFrequency(unsigned int )
01870 {
01871 U64 frequency = 0;
01872 size_t len = sizeof(frequency);
01873
01874 if(sysctlbyname("hw.cpufrequency", &frequency, &len, NULL, 0) == 0)
01875 {
01876 uqwFrequency = (F64)frequency;
01877 }
01878
01879 return uqwFrequency;
01880 }
01881
01882 static bool hasFeature(const char *name)
01883 {
01884 bool result = false;
01885 int val = 0;
01886 size_t len = sizeof(val);
01887
01888 if(sysctlbyname(name, &val, &len, NULL, 0) == 0)
01889 {
01890 if(val != 0)
01891 result = true;
01892 }
01893
01894 return result;
01895 }
01896
01897
01898
01899
01900
01902 const ProcessorInfo *CProcessor::GetCPUInfo()
01903 {
01904 int pagesize = 0;
01905 int cachelinesize = 0;
01906 int l1icachesize = 0;
01907 int l1dcachesize = 0;
01908 int l2settings = 0;
01909 int l2cachesize = 0;
01910 int l3settings = 0;
01911 int l3cachesize = 0;
01912 int ncpu = 0;
01913 int cpusubtype = 0;
01914
01915
01916 int mib[2];
01917 size_t len;
01918 mib[0] = CTL_HW;
01919
01920 mib[1] = HW_PAGESIZE;
01921 len = sizeof(pagesize);
01922 sysctl(mib, 2, &pagesize, &len, NULL, 0);
01923
01924 mib[1] = HW_CACHELINE;
01925 len = sizeof(cachelinesize);
01926 sysctl(mib, 2, &cachelinesize, &len, NULL, 0);
01927
01928 mib[1] = HW_L1ICACHESIZE;
01929 len = sizeof(l1icachesize);
01930 sysctl(mib, 2, &l1icachesize, &len, NULL, 0);
01931
01932 mib[1] = HW_L1DCACHESIZE;
01933 len = sizeof(l1dcachesize);
01934 sysctl(mib, 2, &l1dcachesize, &len, NULL, 0);
01935
01936 mib[1] = HW_L2SETTINGS;
01937 len = sizeof(l2settings);
01938 sysctl(mib, 2, &l2settings, &len, NULL, 0);
01939
01940 mib[1] = HW_L2CACHESIZE;
01941 len = sizeof(l2cachesize);
01942 sysctl(mib, 2, &l2cachesize, &len, NULL, 0);
01943
01944 mib[1] = HW_L3SETTINGS;
01945 len = sizeof(l3settings);
01946 sysctl(mib, 2, &l3settings, &len, NULL, 0);
01947
01948 mib[1] = HW_L3CACHESIZE;
01949 len = sizeof(l3cachesize);
01950 sysctl(mib, 2, &l3cachesize, &len, NULL, 0);
01951
01952 mib[1] = HW_NCPU;
01953 len = sizeof(ncpu);
01954 sysctl(mib, 2, &ncpu, &len, NULL, 0);
01955
01956 sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0);
01957
01958 strCPUName[0] = 0;
01959
01960 if((ncpu == 0) || (ncpu == 1))
01961 {
01962
01963 }
01964 else if(ncpu == 2)
01965 {
01966 strncat(strCPUName, "Dual ", sizeof(strCPUName)-strlen(strCPUName)-1);
01967 }
01968 else
01969 {
01970 snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpu);
01971 }
01972
01973 #if __ppc__
01974 switch(cpusubtype)
01975 {
01976 case CPU_SUBTYPE_POWERPC_601:
01977 strncat(strCPUName, "PowerPC 601", sizeof(strCPUName)-strlen(strCPUName)-1);
01978 strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
01979
01980 break;
01981 case CPU_SUBTYPE_POWERPC_602:
01982 strncat(strCPUName, "PowerPC 602", sizeof(strCPUName)-strlen(strCPUName)-1);
01983 strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
01984 break;
01985 case CPU_SUBTYPE_POWERPC_603:
01986 strncat(strCPUName, "PowerPC 603", sizeof(strCPUName)-strlen(strCPUName)-1);
01987 strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
01988 break;
01989 case CPU_SUBTYPE_POWERPC_603e:
01990 strncat(strCPUName, "PowerPC 603e", sizeof(strCPUName)-strlen(strCPUName)-1);
01991 strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
01992 break;
01993 case CPU_SUBTYPE_POWERPC_603ev:
01994 strncat(strCPUName, "PowerPC 603ev", sizeof(strCPUName)-strlen(strCPUName)-1);
01995 strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
01996 break;
01997 case CPU_SUBTYPE_POWERPC_604:
01998 strncat(strCPUName, "PowerPC 604", sizeof(strCPUName)-strlen(strCPUName)-1);
01999 strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
02000 break;
02001 case CPU_SUBTYPE_POWERPC_604e:
02002 strncat(strCPUName, "PowerPC 604e", sizeof(strCPUName)-strlen(strCPUName)-1);
02003 strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
02004 break;
02005 case CPU_SUBTYPE_POWERPC_620:
02006 strncat(strCPUName, "PowerPC 620", sizeof(strCPUName)-strlen(strCPUName)-1);
02007 strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
02008 break;
02009 case CPU_SUBTYPE_POWERPC_750:
02010 strncat(strCPUName, "PowerPC 750", sizeof(strCPUName)-strlen(strCPUName)-1);
02011 strncat(CPUInfo.strFamily, "PowerPC G3", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
02012 break;
02013 case CPU_SUBTYPE_POWERPC_7400:
02014 strncat(strCPUName, "PowerPC 7400", sizeof(strCPUName)-strlen(strCPUName)-1);
02015 strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
02016 break;
02017 case CPU_SUBTYPE_POWERPC_7450:
02018 strncat(strCPUName, "PowerPC 7450", sizeof(strCPUName)-strlen(strCPUName)-1);
02019 strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
02020 break;
02021 case CPU_SUBTYPE_POWERPC_970:
02022 strncat(strCPUName, "PowerPC 970", sizeof(strCPUName)-strlen(strCPUName)-1);
02023 strncat(CPUInfo.strFamily, "PowerPC G5", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
02024 break;
02025
02026 default:
02027 strncat(strCPUName, "PowerPC (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1);
02028 break;
02029 }
02030
02031 CPUInfo._Ext.EMMX_MultimediaExtensions =
02032 CPUInfo._Ext.MMX_MultimediaExtensions =
02033 CPUInfo._Ext.SSE_StreamingSIMD_Extensions =
02034 CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = false;
02035
02036 CPUInfo._Ext.Altivec_Extensions = hasFeature("hw.optional.altivec");
02037
02038 #endif
02039
02040 #if __i386__
02041
02042 switch(cpusubtype)
02043 {
02044 default:
02045 strncat(strCPUName, "i386 (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1);
02046 break;
02047 }
02048
02049 CPUInfo._Ext.EMMX_MultimediaExtensions = hasFeature("hw.optional.mmx");
02050 CPUInfo._Ext.MMX_MultimediaExtensions = hasFeature("hw.optional.mmx");
02051 CPUInfo._Ext.SSE_StreamingSIMD_Extensions = hasFeature("hw.optional.sse");
02052 CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.sse2");
02053 CPUInfo._Ext.Altivec_Extensions = false;
02054 CPUInfo._Ext.AA64_AMD64BitArchitecture = hasFeature("hw.optional.x86_64");
02055
02056 #endif
02057
02058
02059 strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1);
02060 CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
02061
02062
02063
02064 if(l1dcachesize != 0)
02065 {
02066 CPUInfo._L1.Data.bPresent = true;
02067 snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", l1dcachesize / 1024);
02068
02069 CPUInfo._L1.Data.uiLineSize = cachelinesize;
02070 }
02071
02072 if(l1icachesize != 0)
02073 {
02074 CPUInfo._L1.Instruction.bPresent = true;
02075 snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", l1icachesize / 1024);
02076
02077 CPUInfo._L1.Instruction.uiLineSize = cachelinesize;
02078 }
02079
02080 if(l2cachesize != 0)
02081 {
02082 CPUInfo._L2.bPresent = true;
02083 snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l2cachesize / 1024);
02084
02085 CPUInfo._L2.uiLineSize = cachelinesize;
02086 }
02087
02088 if(l3cachesize != 0)
02089 {
02090 CPUInfo._L2.bPresent = true;
02091 snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l3cachesize / 1024);
02092
02093 CPUInfo._L2.uiLineSize = cachelinesize;
02094 }
02095
02096 CPUInfo._Ext.FPU_FloatingPointUnit = hasFeature("hw.optional.floatingpoint");
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108 TranslateProcessorConfiguration();
02109
02110
02111 return (&CPUInfo);
02112 }
02113
02114 #endif // LL_DARWIN
02115
02116
02117
02118
02120 bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
02121 {
02122 #define LENCHECK len = (unsigned int) strlen(buf); if (len >= uiMaxLen) return false; strcpy(strBuffer, buf); strBuffer += len;
02123 #define COPYADD(str) strcpy(buf, str); LENCHECK;
02124 #define FORMATADD(format, var) sprintf(buf, format, var); LENCHECK;
02125 #define BOOLADD(str, boolvar) COPYADD(str); if (boolvar) { COPYADD(" Yes\n"); } else { COPYADD(" No\n"); }
02126
02127 char buf[1024];
02128 unsigned int len;
02129
02130
02131 GetCPUFrequency(50);
02132
02133
02134 GetCPUInfo();
02135
02136
02137 strBuffer[0] = 0;
02138
02139 COPYADD("// CPU General Information\n//////////////////////////\n");
02140 FORMATADD("Processor name: %s\n", strCPUName);
02141 FORMATADD("Frequency: %.2f MHz\n\n", (float) uqwFrequency / 1000000.0f);
02142 FORMATADD("Vendor: %s\n", CPUInfo.strVendor);
02143 FORMATADD("Family: %s\n", CPUInfo.strFamily);
02144 FORMATADD("Extended family: %d\n", CPUInfo.uiExtendedFamily);
02145 FORMATADD("Model: %s\n", CPUInfo.strModel);
02146 FORMATADD("Extended model: %d\n", CPUInfo.uiExtendedModel);
02147 FORMATADD("Type: %s\n", CPUInfo.strType);
02148 FORMATADD("Brand ID: %s\n", CPUInfo.strBrandID);
02149 if (CPUInfo._Ext.PN_ProcessorSerialNumber)
02150 {
02151 FORMATADD("Processor Serial: %s\n", CPUInfo.strProcessorSerial);
02152 }
02153 else
02154 {
02155 COPYADD("Processor Serial: Disabled\n");
02156 }
02157 #if !LL_SOLARIS // NOTE: Why bother printing all this when it's irrelavent
02158
02159 COPYADD("\n\n// CPU Configuration\n////////////////////\n");
02160 FORMATADD("L1 instruction cache: %s\n", CPUInfo._L1.Instruction.strCache);
02161 FORMATADD("L1 data cache: %s\n", CPUInfo._L1.Data.strCache);
02162 FORMATADD("L2 cache: %s\n", CPUInfo._L2.strCache);
02163 FORMATADD("L3 cache: %s\n", CPUInfo._L3.strCache);
02164 FORMATADD("Trace cache: %s\n", CPUInfo._Trace.strCache);
02165 FORMATADD("Instruction TLB: %s\n", CPUInfo._Instruction.strTLB);
02166 FORMATADD("Data TLB: %s\n", CPUInfo._Data.strTLB);
02167 FORMATADD("Max Supported CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedLevel);
02168 FORMATADD("Max Supported Ext. CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedExtendedLevel);
02169
02170 COPYADD("\n\n// CPU Extensions\n/////////////////\n");
02171 BOOLADD("AA64 AMD 64-bit Architecture: ", CPUInfo._Ext.AA64_AMD64BitArchitecture);
02172 BOOLADD("ACPI Thermal Monitor And Clock Control: ", CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl);
02173 BOOLADD("APIC Advanced Programmable Interrupt Controller: ", CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController);
02174 FORMATADD(" APIC-ID: %d\n", CPUInfo._Ext.APIC_ID);
02175 BOOLADD("CLFSH CLFLUSH Instruction Presence: ", CPUInfo._Ext.CLFSH_CFLUSH_Instruction);
02176 FORMATADD(" CLFLUSH Instruction Cache Line Size: %d\n", CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize);
02177 BOOLADD("CMOV Conditional Move And Compare Instructions: ", CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions);
02178 BOOLADD("CX8 COMPXCHG8B Instruction: ", CPUInfo._Ext.CX8_COMPXCHG8B_Instruction);
02179 BOOLADD("DE Debugging Extensions: ", CPUInfo._Ext.DE_DebuggingExtensions);
02180 BOOLADD("DS Debug Store: ", CPUInfo._Ext.DS_DebugStore);
02181 BOOLADD("FGPAT Page Attribute Table: ", CPUInfo._Ext.FGPAT_PageAttributeTable);
02182 BOOLADD("FPU Floating Point Unit: ", CPUInfo._Ext.FPU_FloatingPointUnit);
02183 BOOLADD("FXSR Fast Streaming SIMD Extensions Save/Restore:", CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore);
02184 BOOLADD("HT Hyper Threading: ", CPUInfo._Ext.HT_HyperThreading);
02185 BOOLADD("IA64 Intel 64-Bit Architecture: ", CPUInfo._Ext.IA64_Intel64BitArchitecture);
02186 BOOLADD("MCA Machine Check Architecture: ", CPUInfo._Ext.MCA_MachineCheckArchitecture);
02187 BOOLADD("MCE Machine Check Exception: ", CPUInfo._Ext.MCE_MachineCheckException);
02188 BOOLADD("MMX Multimedia Extensions: ", CPUInfo._Ext.MMX_MultimediaExtensions);
02189 BOOLADD("MMX+ Multimedia Extensions: ", CPUInfo._Ext.EMMX_MultimediaExtensions);
02190 BOOLADD("MSR Model Specific Registers: ", CPUInfo._Ext.MSR_ModelSpecificRegisters);
02191 BOOLADD("MTRR Memory Type Range Registers: ", CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters);
02192 BOOLADD("PAE Physical Address Extension: ", CPUInfo._Ext.PAE_PhysicalAddressExtension);
02193 BOOLADD("PGE PTE Global Flag: ", CPUInfo._Ext.PGE_PTE_GlobalFlag);
02194 if (CPUInfo._Ext.PN_ProcessorSerialNumber)
02195 {
02196 FORMATADD("PN Processor Serial Number: %s\n", CPUInfo.strProcessorSerial);
02197 }
02198 else
02199 {
02200 COPYADD("PN Processor Serial Number: Disabled\n");
02201 }
02202 BOOLADD("PSE Page Size Extensions: ", CPUInfo._Ext.PSE_PageSizeExtensions);
02203 BOOLADD("PSE36 36-bit Page Size Extension: ", CPUInfo._Ext.PSE36_36bitPageSizeExtension);
02204 BOOLADD("SEP Fast System Call: ", CPUInfo._Ext.SEP_FastSystemCall);
02205 BOOLADD("SS Self Snoop: ", CPUInfo._Ext.SS_SelfSnoop);
02206 BOOLADD("SSE Streaming SIMD Extensions: ", CPUInfo._Ext.SSE_StreamingSIMD_Extensions);
02207 BOOLADD("SSE2 Streaming SIMD 2 Extensions: ", CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions);
02208 BOOLADD("ALTVEC Altivec Extensions: ", CPUInfo._Ext.Altivec_Extensions);
02209 BOOLADD("TM Thermal Monitor: ", CPUInfo._Ext.TM_ThermalMonitor);
02210 BOOLADD("TSC Time Stamp Counter: ", CPUInfo._Ext.TSC_TimeStampCounter);
02211 BOOLADD("VME Virtual 8086 Mode Enhancements: ", CPUInfo._Ext.VME_Virtual8086ModeEnhancements);
02212 BOOLADD("3DNow! Instructions: ", CPUInfo._Ext._3DNOW_InstructionExtensions);
02213 BOOLADD("Enhanced 3DNow! Instructions: ", CPUInfo._Ext._E3DNOW_InstructionExtensions);
02214 #endif
02215
02216 return true;
02217 }
02218
02219
02220
02221
02222
02224 bool CProcessor::WriteInfoTextFile(const char *strFilename)
02225 {
02226 char buf[16384];
02227
02228
02229 if (!CPUInfoToText(buf, 16383))
02230 return false;
02231
02232
02233 FILE *file = LLFile::fopen(strFilename, "w");
02234 if (!file)
02235 return false;
02236
02237
02238 unsigned long dwBytesToWrite, dwBytesWritten;
02239 dwBytesToWrite = (unsigned long) strlen(buf);
02240 dwBytesWritten = (unsigned long) fwrite(buf, 1, dwBytesToWrite, file);
02241 fclose(file);
02242 if (dwBytesToWrite != dwBytesWritten)
02243 return false;
02244
02245
02246 return true;
02247 }