llprocessor.cpp

Go to the documentation of this file.
00001 
00032 // Filename: Processor.cpp
00033 // =======================
00034 // Author: Benjamin Jurke
00035 // File history: 27.02.2002  - File created. Support for Intel and AMD processors
00036 //               05.03.2002  - Fixed the CPUID bug: On Pre-Pentium CPUs the CPUID
00037 //                             command is not available
00038 //                           - The CProcessor::WriteInfoTextFile function do not 
00039 //                             longer use Win32 file functions (-> os independend)
00040 //                           - Optional include of the windows.h header which is
00041 //                             still need for CProcessor::GetCPUFrequency.
00042 //               06.03.2002  - My birthday (18th :-))
00043 //                           - Replaced the '\r\n' line endings in function 
00044 //                             CProcessor::CPUInfoToText by '\n'
00045 //                           - Replaced unsigned __int64 by signed __int64 for
00046 //                             solving some compiler conversion problems
00047 //                           - Fixed a bug at family=6, model=6 (Celeron -> P2)
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 // We need the QueryPerformanceCounter and Sleep functions
00066 #define FORCEINLINE __forceinline
00067 #else
00068 #define FORCEINLINE 
00069 #endif
00070 
00071 
00072 // Some macros we often need
00074 #define CheckBit(var, bit)   ((var & (1 << bit)) ? true : false)
00075 
00076 #ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
00077 // Delays for the specified amount of milliseconds
00078 static  void    _Delay(unsigned int ms)
00079 {
00080    LARGE_INTEGER        freq, c1, c2;
00081         __int64         x;
00082 
00083    // Get High-Res Timer frequency
00084         if (!QueryPerformanceFrequency(&freq))  
00085                 return;
00086                 
00087         // Convert ms to High-Res Timer value
00088         x = freq.QuadPart/1000*ms;              
00089 
00090    // Get first snapshot of High-Res Timer value
00091         QueryPerformanceCounter(&c1);           
00092         do
00093         {
00094             // Get second snapshot
00095             QueryPerformanceCounter(&c2);       
00096         }while(c2.QuadPart-c1.QuadPart < x);
00097         // Loop while (second-first < x)        
00098 }
00099 #endif
00100 
00101 // CProcessor::CProcessor
00102 // ======================
00103 // Class constructor:
00105 CProcessor::CProcessor()
00106 {
00107         uqwFrequency = 0;
00108         strCPUName[0] = 0;
00109         memset(&CPUInfo, 0, sizeof(CPUInfo));
00110 }
00111 
00112 // unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
00113 // =========================================================================
00114 // Function to measure the current CPU frequency
00116 F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
00117 {
00118 #ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
00119         return 0;
00120 #else
00121         // If there are invalid measure time parameters, zero msecs for example,
00122         // we've to exit the function
00123         if (uiMeasureMSecs < 1)
00124         {
00125                 // If theres already a measured frequency available, we return it
00126         if (uqwFrequency > 0)
00127                         return uqwFrequency;
00128                 else
00129                         return 0;
00130         }
00131 
00132         // Now we check if the CPUID command is available
00133         if (!CheckCPUIDPresence())
00134                 return 0;
00135 
00136         // First we get the CPUID standard level 0x00000001
00137         unsigned long reg;
00138         __asm
00139         {
00140                 mov eax, 1
00141         cpuid
00142                 mov reg, edx
00143         }
00144 
00145         // Then we check, if the RDTSC (Real Date Time Stamp Counter) is available.
00146         // This function is necessary for our measure process.
00147         if (!(reg & (1 << 4)))
00148                 return 0;
00149 
00150         // After that we declare some vars and check the frequency of the high
00151         // resolution timer for the measure process.
00152         // If there's no high-res timer, we exit.
00153         __int64 starttime, endtime, timedif, freq, start, end, dif;
00154         if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq))
00155                 return 0;
00156 
00157         // Now we can init the measure process. We set the process and thread priority
00158         // to the highest available level (Realtime priority). Also we focus the
00159         // first processor in the multiprocessor system.
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         // Now we call a CPUID to ensure, that all other prior called functions are
00172         // completed now (serialization)
00173         __asm cpuid
00174 
00175         // We ask the high-res timer for the start time
00176         QueryPerformanceCounter((LARGE_INTEGER *) &starttime);
00177 
00178         // Then we get the current cpu clock and store it
00179         __asm 
00180         {
00181                 rdtsc
00182                 mov dword ptr [start+4], edx
00183                 mov dword ptr [start], eax
00184         }
00185 
00186         // Now we wart for some msecs
00187         _Delay(uiMeasureMSecs);
00188 //      Sleep(uiMeasureMSecs);
00189 
00190         // We ask for the end time
00191         QueryPerformanceCounter((LARGE_INTEGER *) &endtime);
00192 
00193         // And also for the end cpu clock
00194         __asm 
00195         {
00196                 rdtsc
00197                 mov dword ptr [end+4], edx
00198                 mov dword ptr [end], eax
00199         }
00200 
00201         // Now we can restore the default process and thread priorities
00202         SetProcessAffinityMask(hProcess, dwProcessMask);
00203         SetThreadPriority(hThread, iCurThreadPriority);
00204         SetPriorityClass(hProcess, dwCurPriorityClass);
00205 
00206         // Then we calculate the time and clock differences
00207         dif = end - start;
00208         timedif = endtime - starttime;
00209 
00210         // And finally the frequency is the clock difference divided by the time
00211         // difference. 
00212         uqwFrequency = (F64)dif / (((F64)timedif) / freq);
00213 
00214         // At last we just return the frequency that is also stored in the call
00215         // member var uqwFrequency
00216         return uqwFrequency;
00217 #endif
00218 }
00219 
00220 // bool CProcessor::AnalyzeIntelProcessor()
00221 // ========================================
00222 // Private class function for analyzing an Intel processor
00224 bool CProcessor::AnalyzeIntelProcessor()
00225 {
00226 #if LL_WINDOWS
00227         unsigned long eaxreg, ebxreg, edxreg;
00228 
00229         // First we check if the CPUID command is available
00230         if (!CheckCPUIDPresence())
00231                 return false;
00232 
00233         // Now we get the CPUID standard level 0x00000001
00234         __asm
00235         {
00236                 mov eax, 1
00237                 cpuid
00238                 mov eaxreg, eax
00239                 mov ebxreg, ebx
00240                 mov edxreg, edx
00241         }
00242     
00243         // Then get the cpu model, family, type, stepping and brand id by masking
00244         // the eax and ebx register
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                 /* 0x00 */ "",
00254                 /* 0x01 */ "0.18 micron Intel Celeron",
00255                 /* 0x02 */ "0.18 micron Intel Pentium III",
00256                 /* 0x03 */ "0.13 micron Intel Celeron",
00257                 /* 0x04 */ "0.13 micron Intel Pentium III",
00258                 /* 0x05 */ "",
00259                 /* 0x06 */ "0.13 micron Intel Pentium III Mobile",
00260                 /* 0x07 */ "0.13 micron Intel Celeron Mobile",
00261                 /* 0x08 */ "0.18 micron Intel Pentium 4",
00262                 /* 0x09 */ "0.13 micron Intel Pentium 4",
00263                 /* 0x0A */ "0.13 micron Intel Celeron",
00264                 /* 0x0B */ "0.13 micron Intel Pentium 4 Xeon",
00265                 /* 0x0C */ "Intel Xeon MP",
00266                 /* 0x0D */ "",
00267                 /* 0x0E */ "0.18 micron Intel Pentium 4 Xeon",
00268                 /* 0x0F */ "Mobile Intel Celeron",
00269                 /* 0x10 */ "",
00270                 /* 0x11 */ "Mobile Genuine Intel",
00271                 /* 0x12 */ "Intel Celeron M",
00272                 /* 0x13 */ "Mobile Intel Celeron",
00273                 /* 0x14 */ "Intel Celeron",
00274                 /* 0x15 */ "Mobile Genuine Intel",
00275                 /* 0x16 */ "Intel Pentium M",
00276                 /* 0x17 */ "Mobile Intel Celeron",
00277         };
00278 
00279         // Only override the brand if we have it in the lookup table.  We should
00280         // already have a string here from GetCPUInfo().  JC
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         // Then we translate the cpu family
00292     switch (CPUInfo.uiFamily)
00293         {
00294                 case 3:                 // Family = 3:  i386 (80386) processor family
00295                         strcpy(CPUInfo.strFamily, "Intel i386");        /* Flawfinder: ignore */        
00296                         break;
00297                 case 4:                 // Family = 4:  i486 (80486) processor family
00298                         strcpy(CPUInfo.strFamily, "Intel i486");        /* Flawfinder: ignore */        
00299                         break;
00300                 case 5:                 // Family = 5:  Pentium (80586) processor family
00301                         strcpy(CPUInfo.strFamily, "Intel Pentium");     /* Flawfinder: ignore */        
00302                         break;
00303                 case 6:                 // Family = 6:  Pentium Pro (80686) processor family
00304                         strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core");       /* Flawfinder: ignore */        
00305                         break;
00306                 case 15:                // Family = 15:  Extended family specific
00307                         // Masking the extended family
00308                         CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF;
00309                         switch (CPUInfo.uiExtendedFamily)
00310                         {
00311                                 case 0:                 // Family = 15, Ext. Family = 0:  Pentium 4 (80786 ??) processor family
00312                                         strcpy(CPUInfo.strFamily, "Intel Pentium 4");   /* Flawfinder: ignore */        
00313                                         break;
00314                                 case 1:                 // Family = 15, Ext. Family = 1:  McKinley (64-bit) processor family
00315                                         strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)");    /* Flawfinder: ignore */        
00316                                         break;
00317                                 default:                // Sure is sure
00318                                         strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+");  /* Flawfinder: ignore */        
00319                                         break;
00320                         }
00321                         break;
00322                 default:                // Failsave
00323                         strcpy(CPUInfo.strFamily, "Unknown");   /* Flawfinder: ignore */
00324                         break;
00325     }
00326 
00327         // Now we come to the big deal, the exact model name
00328         switch (CPUInfo.uiFamily)
00329         {
00330                 case 3:                 // i386 (80386) processor family
00331                         strcpy(CPUInfo.strModel, "Unknown Intel i386"); /* Flawfinder: ignore */
00332                         strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1);     /* Flawfinder: ignore */                
00333                         break;
00334                 case 4:                 // i486 (80486) processor family
00335                         switch (CPUInfo.uiModel)
00336                         {
00337                                 case 0:                 // Model = 0:  i486 DX-25/33 processor model
00338                                         strcpy(CPUInfo.strModel, "Intel i486 DX-25/33");        /* Flawfinder: ignore */                        
00339                                         strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1);    /* Flawfinder: ignore */                
00340                                         break;
00341                                 case 1:                 // Model = 1:  i486 DX-50 processor model
00342                                         strcpy(CPUInfo.strModel, "Intel i486 DX-50");   /* Flawfinder: ignore */                
00343                                         strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1);       /* Flawfinder: ignore */                
00344                                         break;
00345                                 case 2:                 // Model = 2:  i486 SX processor model
00346                                         strcpy(CPUInfo.strModel, "Intel i486 SX");      /* Flawfinder: ignore */                
00347                                         strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1);  /* Flawfinder: ignore */                
00348                                         break;
00349                                 case 3:                 // Model = 3:  i486 DX2 (with i487 numeric coprocessor) processor model
00350                                         strcpy(CPUInfo.strModel, "Intel i486 487/DX2"); /* Flawfinder: ignore */                
00351                                         strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1);   /* Flawfinder: ignore */                
00352                                         break;
00353                                 case 4:                 // Model = 4:  i486 SL processor model (never heard ?!?)
00354                                         strcpy(CPUInfo.strModel, "Intel i486 SL");      /* Flawfinder: ignore */        
00355                                         strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1);  /* Flawfinder: ignore */        
00356                                         break;
00357                                 case 5:                 // Model = 5:  i486 SX2 processor model
00358                                         strcpy(CPUInfo.strModel, "Intel i486 SX2");     /* Flawfinder: ignore */        
00359                                         strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */        
00360                                         break;
00361                                 case 7:                 // Model = 7:  i486 write-back enhanced DX2 processor model
00362                                         strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2"); /* Flawfinder: ignore */        
00363                                         strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1);     /* Flawfinder: ignore */        
00364                                         break;
00365                                 case 8:                 // Model = 8:  i486 DX4 processor model
00366                                         strcpy(CPUInfo.strModel, "Intel i486 DX4");     /* Flawfinder: ignore */        
00367                                         strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */        
00368                                         break;
00369                                 case 9:                 // Model = 9:  i486 write-back enhanced DX4 processor model
00370                                         strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4"); /* Flawfinder: ignore */        
00371                                         strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */        
00372                                         break;
00373                                 default:                // ...
00374                                         strcpy(CPUInfo.strModel, "Unknown Intel i486"); /* Flawfinder: ignore */        
00375                                         strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1);     /* Flawfinder: ignore */        
00376                                         break;
00377                         }
00378                         break;
00379                 case 5:                 // Pentium (80586) processor family
00380                         switch (CPUInfo.uiModel)
00381                         {
00382                                 case 0:                 // Model = 0:  Pentium (P5 A-Step) processor model
00383                                         strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)");  /* Flawfinder: ignore */        
00384                                         strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */        
00385                                         break;          // Famous for the DIV bug, as far as I know
00386                                 case 1:                 // Model = 1:  Pentium 60/66 processor model
00387                                         strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)");   /* Flawfinder: ignore */        
00388                                         strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1);  /* Flawfinder: ignore */        
00389                                         break;
00390                                 case 2:                 // Model = 2:  Pentium 75-200 (P54C) processor model
00391                                         strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)");        /* Flawfinder: ignore */        
00392                                         strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1);       /* Flawfinder: ignore */        
00393                                         break;
00394                                 case 3:                 // Model = 3:  Pentium overdrive for 486 systems processor model
00395                                         strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)");      /* Flawfinder: ignore */        
00396                                         strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00397                                         break;
00398                                 case 4:                 // Model = 4:  Pentium MMX processor model
00399                                         strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)");   /*Flawfinder: ignore*/
00400                                         strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00401                                         break;
00402                                 case 7:                 // Model = 7:  Pentium processor model (don't know difference to Model=2)
00403                                         strcpy(CPUInfo.strModel, "Intel Pentium (P54C)");               /*Flawfinder: ignore*/
00404                                         strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00405                                         break;
00406                                 case 8:                 // Model = 8:  Pentium MMX (0.25 micron) processor model
00407                                         strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron");              /*Flawfinder: ignore*/
00408                                         strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00409                                         break;
00410                                 default:                // ...
00411                                         strcpy(CPUInfo.strModel, "Unknown Intel Pentium");      /*Flawfinder: ignore*/
00412                                         strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00413                                         break;
00414                         }
00415                         break;
00416                 case 6:                 // Pentium Pro (80686) processor family
00417                         switch (CPUInfo.uiModel)
00418                         {
00419                                 case 0:                 // Model = 0:  Pentium Pro (P6 A-Step) processor model
00420                                         strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)");              /*Flawfinder: ignore*/
00421                                         strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00422                                         break;
00423                                 case 1:                 // Model = 1:  Pentium Pro
00424                                         strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)");             /*Flawfinder: ignore*/
00425                                         strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00426                                         break;
00427                                 case 3:                 // Model = 3:  Pentium II (66 MHz FSB, I think) processor model
00428                                         strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron");              /*Flawfinder: ignore*/
00429                                         strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00430                                         break;
00431                                 case 5:                 // Model = 5:  Pentium II/Xeon/Celeron (0.25 micron) processor model
00432                                         strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron");         /*Flawfinder: ignore*/
00433                                         strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00434                                         break;
00435                                 case 6:                 // Model = 6:  Pentium II with internal L2 cache
00436                                         strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache");       /*Flawfinder: ignore*/
00437                                         strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00438                                         break;
00439                                 case 7:                 // Model = 7:  Pentium III/Xeon (extern L2 cache) processor model
00440                                         strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron");                 /*Flawfinder: ignore*/
00441                                         strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00442                                         break;
00443                                 case 8:                 // Model = 8:  Pentium III/Xeon/Celeron (256 KB on-die L2 cache) processor model
00444                                         strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");         /*Flawfinder: ignore*/
00445                                         // We want to know it exactly:
00446                                         switch (CPUInfo.uiBrandID)
00447                                         {
00448                                                 case 1:                 // Model = 8, Brand id = 1:  Celeron (on-die L2 cache) processor model
00449                                                         strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00450                                                         break;
00451                         case 2:                 // Model = 8, Brand id = 2:  Pentium III (on-die L2 cache) processor model (my current cpu :-))
00452                                                         strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00453                                                         break;
00454                                                 case 3:                 // Model = 8, Brand id = 3:  Pentium III Xeon (on-die L2 cache) processor model
00455                             strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
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)); /*Flawfinder: ignore*/
00459                                                         break;
00460                                         }
00461                                         break;
00462                                 case 9:         // Model = 9:  Intel Pentium M processor, Intel Celeron M processor, model 9
00463                                         strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");    /*Flawfinder: ignore*/
00464                                         strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00465                                         break;
00466                                 case 0xA:               // Model = 0xA:  Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model
00467                                         strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");         /*Flawfinder: ignore*/
00468                                         // Exact detection:
00469                                         switch (CPUInfo.uiBrandID)
00470                                         {
00471                                                 case 1:                 // Model = 0xA, Brand id = 1:  Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model
00472                                                         strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00473                                                         break;
00474                         case 2:                 // Model = 0xA, Brand id = 2:  Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model
00475                                                         strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00476                                                         break;
00477                                                 case 3:                 // Model = 0xA, Brand id = 3:  Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model
00478                             strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00479                                                         break;
00480                                                 default:                // Getting bored of this............
00481                                                         strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00482                                                         break;
00483                                         }
00484                                         break;
00485                                 case 0xB:               // Model = 0xB: Pentium III/Xeon/Celeron (Tualatin core, on-die cache) processor model
00486                                         strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron");         /*Flawfinder: ignore*/
00487                                         // Omniscient: ;-)
00488                                         switch (CPUInfo.uiBrandID)
00489                                         {
00490                                                 case 3:                 // Model = 0xB, Brand id = 3:  Celeron (Tualatin core) processor model
00491                                                         strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00492                                                         break;
00493                         case 4:                 // Model = 0xB, Brand id = 4:  Pentium III (Tualatin core) processor model
00494                                                         strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00495                                                         break;
00496                                                 case 7:                 // Model = 0xB, Brand id = 7:  Celeron mobile (Tualatin core) processor model
00497                             strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00498                                                         break;
00499                                                 default:                // *bored*
00500                                                         strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00501                                                         break;
00502                                         }
00503                                         break;
00504                                 case 0xD:               // Model = 0xD:  Intel Pentium M processor, Intel Celeron M processor, model D
00505                                         strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");    /*Flawfinder: ignore*/
00506                                         strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00507                                         break;
00508                                 case 0xE:               // Model = 0xE:  Intel Core Duo processor, Intel Core Solo processor, model E
00509                                         strcpy(CPUInfo.strModel, "Intel Core Series Processor");         /*Flawfinder: ignore*/
00510                                         strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00511                                         break;  
00512                                 case 0xF:               // Model = 0xF:  Intel Core 2 Duo processor, model F
00513                                         strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor");       /*Flawfinder: ignore*/
00514                                         strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00515                                         break;  
00516                                 default:                // *more bored*
00517                                         strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/
00518                                         strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00519                                         break;
00520                         }
00521                         break;
00522                 case 15:                // Extended processor family
00523                         // Masking the extended model
00524                         CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF;
00525                         switch (CPUInfo.uiModel)
00526                         {
00527                                 case 0:                 // Model = 0:  Pentium 4 Willamette (A-Step) core
00528                                         if ((CPUInfo.uiBrandID) == 8)   // Brand id = 8:  P4 Willamette
00529                                         {
00530                                                 strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)"); /*Flawfinder: ignore*/
00531                                                 strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
00532                                         }
00533                                         else                                                    // else Xeon
00534                                         {
00535                                                 strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)");           /* Flawfinder: ignore */
00536                                                 strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1);           /* Flawfinder: ignore */        
00537                                         }
00538                                         break;
00539                                 case 1:                 // Model = 1:  Pentium 4 Willamette core
00540                                         if ((CPUInfo.uiBrandID) == 8)   // Brand id = 8:  P4 Willamette
00541                                         {
00542                                                 strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette");         /* Flawfinder: ignore */
00543                                                 strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1);         /* Flawfinder: ignore */
00544                                         }
00545                                         else                                                    // else Xeon
00546                                         {
00547                                                 strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon");            /* Flawfinder: ignore */
00548                                                 strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1);            /* Flawfinder: ignore */
00549                                         }
00550                                         break;
00551                                 case 2:                 // Model = 2:  Pentium 4 Northwood core
00552                                         if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA))         // P4 Willamette
00553                                         {
00554                                                 strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood");          /* Flawfinder: ignore */
00555                                                 strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1);          /* Flawfinder: ignore */
00556                                         }
00557                                         else                                                    // Xeon
00558                                         {
00559                                                 strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon");             /* Flawfinder: ignore */
00560                                                 strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1);             /* Flawfinder: ignore */
00561                                         }
00562                                         break;
00563                                 default:                // Silly stupid never used failsave option
00564                                         strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4");            /* Flawfinder: ignore */
00565                                         strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1);            /* Flawfinder: ignore */
00566                                         break;
00567                         }
00568                         break;
00569                 default:                // *grmpf*
00570                         strcpy(CPUInfo.strModel, "Unknown Intel model");                /* Flawfinder: ignore */
00571                         strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1);              /* Flawfinder: ignore */
00572                         break;
00573     }
00574 
00575         // After the long processor model block we now come to the processors serial
00576         // number.
00577         // First of all we check if the processor supports the serial number
00578         if (CPUInfo.MaxSupportedLevel >= 3)
00579         {
00580                 // If it supports the serial number CPUID level 0x00000003 we read the data
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                 // Then we convert the data to a readable string
00593                 snprintf(       /* Flawfinder: ignore */
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                 // If there's no serial number support we just put "No serial number"
00606                 snprintf(       /* Flawfinder: ignore */
00607                         CPUInfo.strProcessorSerial,
00608                         sizeof(CPUInfo.strProcessorSerial),
00609                         "No Processor Serial Number");  
00610         }
00611 
00612         // Now we get the standard processor extensions
00613         GetStandardProcessorExtensions();
00614 
00615         // And finally the processor configuration (caches, TLBs, ...) and translate
00616         // the data to readable strings
00617         GetStandardProcessorConfiguration();
00618         TranslateProcessorConfiguration();
00619 
00620         // At last...
00621         return true;
00622 #else
00623         return FALSE;
00624 #endif
00625 }
00626 
00627 // bool CProcessor::AnalyzeAMDProcessor()
00628 // ======================================
00629 // Private class function for analyzing an AMD processor
00631 bool CProcessor::AnalyzeAMDProcessor()
00632 {
00633 #if LL_WINDOWS
00634         unsigned long eaxreg, ebxreg, ecxreg, edxreg;
00635 
00636         // First of all we check if the CPUID command is available
00637         if (!CheckCPUIDPresence())
00638                 return 0;
00639 
00640         // Now we get the CPUID standard level 0x00000001
00641         __asm
00642         {
00643                 mov eax, 1
00644                 cpuid
00645                 mov eaxreg, eax
00646                 mov ebxreg, ebx
00647                 mov edxreg, edx
00648         }
00649     
00650         // Then we mask the model, family, stepping and type (AMD does not support brand id)
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         // Now we check if the processor supports the brand id string extended CPUID level
00657         if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004)
00658         {
00659                 // If it supports the extended CPUID level 0x80000004 we read the data
00660                 char tmp[52];           /* Flawfinder: ignore */
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                 // And copy it to the brand id string
00684                 strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1);
00685                 CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
00686         }
00687         else
00688         {
00689                 // Or just tell there is no brand id string support
00690                 strcpy(CPUInfo.strBrandID, "");         /* Flawfinder: ignore */
00691         }
00692 
00693         // After that we translate the processor family
00694     switch(CPUInfo.uiFamily)
00695         {
00696                 case 4:                 // Family = 4:  486 (80486) or 5x86 (80486) processor family
00697                         switch (CPUInfo.uiModel)
00698                         {
00699                                 case 3:                 // Thanks to AMD for this nice form of family
00700                                 case 7:                 // detection.... *grmpf*
00701                                 case 8:
00702                                 case 9:
00703                                         strcpy(CPUInfo.strFamily, "AMD 80486");         /* Flawfinder: ignore */
00704                                         break;
00705                                 case 0xE:
00706                                 case 0xF:
00707                                         strcpy(CPUInfo.strFamily, "AMD 5x86");          /* Flawfinder: ignore */
00708                                         break;
00709                                 default:
00710                                         strcpy(CPUInfo.strFamily, "Unknown family");            /* Flawfinder: ignore */
00711                                         break;
00712                         }
00713                         break;
00714                 case 5:                 // Family = 5:  K5 or K6 processor family
00715                         switch (CPUInfo.uiModel)
00716                         {
00717                                 case 0:
00718                                 case 1:
00719                                 case 2:
00720                                 case 3:
00721                                         strcpy(CPUInfo.strFamily, "AMD K5");            /* Flawfinder: ignore */
00722                                         break;
00723                                 case 6:
00724                                 case 7:
00725                                 case 8:
00726                                 case 9:
00727                                         strcpy(CPUInfo.strFamily, "AMD K6");            /* Flawfinder: ignore */
00728                                         break;
00729                                 default:
00730                                         strcpy(CPUInfo.strFamily, "Unknown family");            /* Flawfinder: ignore */
00731                                         break;
00732                         }
00733                         break;
00734                 case 6:                 // Family = 6:  K7 (Athlon, ...) processor family
00735                         strcpy(CPUInfo.strFamily, "AMD K7");            /* Flawfinder: ignore */
00736                         break;
00737                 default:                // For security
00738                         strcpy(CPUInfo.strFamily, "Unknown family");            /* Flawfinder: ignore */
00739                         break;
00740         }
00741 
00742         // After the family detection we come to the specific processor model
00743         // detection
00744         switch (CPUInfo.uiFamily)
00745         {
00746                 case 4:                 // Family = 4:  486 (80486) or 5x85 (80486) processor family
00747                         switch (CPUInfo.uiModel)
00748                         {
00749                                 case 3:                 // Model = 3:  80486 DX2
00750                                         strcpy(CPUInfo.strModel, "AMD 80486 DX2");              /* Flawfinder: ignore */
00751                                         strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1);               /* Flawfinder: ignore */
00752                                         break;
00753                                 case 7:                 // Model = 7:  80486 write-back enhanced DX2
00754                                         strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2");          /* Flawfinder: ignore */
00755                                         strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1);           /* Flawfinder: ignore */
00756                                         break;
00757                                 case 8:                 // Model = 8:  80486 DX4
00758                                         strcpy(CPUInfo.strModel, "AMD 80486 DX4");              /* Flawfinder: ignore */
00759                                         strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1);               /* Flawfinder: ignore */
00760                                         break;
00761                                 case 9:                 // Model = 9:  80486 write-back enhanced DX4
00762                                         strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4");          /* Flawfinder: ignore */
00763                                         strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1);           /* Flawfinder: ignore */
00764                                         break;
00765                                 case 0xE:               // Model = 0xE:  5x86
00766                                         strcpy(CPUInfo.strModel, "AMD 5x86");           /* Flawfinder: ignore */
00767                                         strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1);            /* Flawfinder: ignore */
00768                                         break;
00769                                 case 0xF:               // Model = 0xF:  5x86 write-back enhanced (oh my god.....)
00770                                         strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced");               /* Flawfinder: ignore */
00771                                         strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1);                /* Flawfinder: ignore */
00772                                         break;
00773                                 default:                // ...
00774                                         strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model");            /* Flawfinder: ignore */
00775                                         strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);           /* Flawfinder: ignore */
00776                                         break;
00777                         }
00778                         break;
00779                 case 5:                 // Family = 5:  K5 / K6 processor family
00780                         switch (CPUInfo.uiModel)
00781                         {
00782                                 case 0:                 // Model = 0:  K5 SSA 5 (Pentium Rating *ggg* 75, 90 and 100 Mhz)
00783                                         strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)");            /* Flawfinder: ignore */
00784                                         strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1);             /* Flawfinder: ignore */
00785                                         break;
00786                                 case 1:                 // Model = 1:  K5 5k86 (PR 120 and 133 MHz)
00787                                         strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)");         /* Flawfinder: ignore */
00788                                         strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1);          /* Flawfinder: ignore */
00789                                         break;
00790                                 case 2:                 // Model = 2:  K5 5k86 (PR 166 MHz)
00791                                         strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)");                /* Flawfinder: ignore */
00792                                         strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1);         /* Flawfinder: ignore */
00793                                         break;
00794                                 case 3:                 // Model = 3:  K5 5k86 (PR 200 MHz)
00795                                         strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)");                /* Flawfinder: ignore */
00796                                         strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1);         /* Flawfinder: ignore */
00797                                         break;
00798                                 case 6:                 // Model = 6:  K6
00799                                         strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)");               /* Flawfinder: ignore */
00800                                         strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);                /* Flawfinder: ignore */
00801                                         break;
00802                                 case 7:                 // Model = 7:  K6 (0.25 micron)
00803                                         strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)");               /* Flawfinder: ignore */
00804                                         strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);                /* Flawfinder: ignore */
00805                                         break;
00806                                 case 8:                 // Model = 8:  K6-2
00807                                         strcpy(CPUInfo.strModel, "AMD K6-2");           /* Flawfinder: ignore */
00808                                         strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1);            /* Flawfinder: ignore */
00809                                         break;
00810                                 case 9:                 // Model = 9:  K6-III
00811                                         strcpy(CPUInfo.strModel, "AMD K6-III");         /* Flawfinder: ignore */
00812                                         strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1);          /* Flawfinder: ignore */
00813                                         break;
00814                                 case 0xD:               // Model = 0xD:  K6-2+ / K6-III+
00815                                         strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)");         /* Flawfinder: ignore */
00816                                         strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);  /* Flawfinder: ignore */
00817                                         break;
00818                                 default:                // ...
00819                                         strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model");         /* Flawfinder: ignore */
00820                                         strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);                /* Flawfinder: ignore */
00821                                         break;
00822                         }
00823                         break;
00824                 case 6:                 // Family = 6:  K7 processor family (AMDs first good processors)
00825                         switch (CPUInfo.uiModel)
00826                         {
00827                                 case 1:                 // Athlon
00828                                         strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)");           /* Flawfinder: ignore */
00829                                         strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);            /* Flawfinder: ignore */
00830                                         break;
00831                                 case 2:                 // Athlon (0.18 micron)
00832                                         strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)");           /* Flawfinder: ignore */
00833                                         strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);            /* Flawfinder: ignore */
00834                                         break;
00835                                 case 3:                 // Duron (Spitfire core)
00836                                         strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)");               /* Flawfinder: ignore */
00837                                         strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1);           /* Flawfinder: ignore */
00838                                         break;
00839                                 case 4:                 // Athlon (Thunderbird core)
00840                                         strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)");           /* Flawfinder: ignore */
00841                                         strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1);               /* Flawfinder: ignore */
00842                                         break;
00843                                 case 6:                 // Athlon MP / Mobile Athlon (Palomino core)
00844                                         strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)");             /* Flawfinder: ignore */
00845                                         strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1);         /* Flawfinder: ignore */
00846                                         break;
00847                                 case 7:                 // Mobile Duron (Morgan core)
00848                                         strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)");          /* Flawfinder: ignore */
00849                                         strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1);              /* Flawfinder: ignore */
00850                                         break;
00851                                 default:                // ...
00852                                         strcpy(CPUInfo.strModel, "Unknown AMD K7 model");               /* Flawfinder: ignore */
00853                                         strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);              /* Flawfinder: ignore */
00854                                         break;
00855                         }
00856                         break;
00857                 default:                // ...
00858                         strcpy(CPUInfo.strModel, "Unknown AMD model");          /* Flawfinder: ignore */
00859                         strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);         /* Flawfinder: ignore */
00860                         break;
00861     }
00862 
00863         // Now we read the standard processor extension that are stored in the same
00864         // way the Intel standard extensions are
00865         GetStandardProcessorExtensions();
00866 
00867         // Then we check if theres an extended CPUID level support
00868         if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001)
00869         {
00870                 // If we can access the extended CPUID level 0x80000001 we get the
00871                 // edx register
00872                 __asm
00873                 {
00874                         mov eax, 0x80000001
00875                         cpuid
00876                         mov edxreg, edx
00877                 }
00878 
00879                 // Now we can mask some AMD specific cpu extensions
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         // After that we check if the processor supports the ext. CPUID level
00887         // 0x80000006
00888         if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006)
00889         {
00890                 // If it's present, we read it out
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                 // Then we mask the L1 Data TLB information
00902                 if ((ebxreg >> 16) && (eaxreg >> 16))
00903                 {
00904                         CPUInfo._Data.bPresent = true;
00905                         strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB");         /*Flawfinder: ignore*/
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");                /*Flawfinder: ignore*/
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");              /*Flawfinder: ignore*/
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                 // Now the L1 Instruction/Code TLB information
00927                 if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF))
00928                 {
00929                         CPUInfo._Instruction.bPresent = true;
00930                         strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB");          /*Flawfinder: ignore*/
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");         /*Flawfinder: ignore*/
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");       /*Flawfinder: ignore*/
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                 // Then we read the L1 data cache information
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);            /* Flawfinder: ignore */
00956                         CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF;
00957                         CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF;
00958                 }
00959                 // After that we read the L2 instruction/code cache information
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);      /* Flawfinder: ignore */
00964                         CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF;
00965                         CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF;
00966                 }
00967 
00968                 // Note: I'm not absolutely sure that the L1 page size code (the
00969                 // 'if/else if/else if' structs above) really detects the real page
00970                 // size for the TLB. Somebody should check it....
00971 
00972                 // Now we read the ext. CPUID level 0x80000006
00973         __asm
00974                 {
00975                         mov eax, 0x80000006
00976                         cpuid
00977                         mov eaxreg, eax
00978                         mov ebxreg, ebx
00979                         mov ecxreg, ecx
00980                 }
00981 
00982                 // We only mask the unified L2 cache masks (never heard of an
00983                 // L2 cache that is divided in data and code parts)
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);              /* Flawfinder: ignore */
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                 // If we could not detect the ext. CPUID level 0x80000006 we
01018                 // try to read the standard processor configuration.
01019                 GetStandardProcessorConfiguration();
01020         }
01021         // After reading we translate the configuration to strings
01022         TranslateProcessorConfiguration();
01023 
01024         // And finally exit
01025         return true;
01026 #else
01027         return FALSE;
01028 #endif
01029 }
01030 
01031 // bool CProcessor::AnalyzeUnknownProcessor()
01032 // ==========================================
01033 // Private class function to analyze an unknown (No Intel or AMD) processor
01035 bool CProcessor::AnalyzeUnknownProcessor()
01036 {
01037 #if LL_WINDOWS
01038         unsigned long eaxreg, ebxreg;
01039 
01040         // We check if the CPUID command is available
01041         if (!CheckCPUIDPresence())
01042                 return false;
01043 
01044         // First of all we read the standard CPUID level 0x00000001
01045         // This level should be available on every x86-processor clone
01046         __asm
01047         {
01048         mov eax, 1
01049                 cpuid
01050                 mov eaxreg, eax
01051                 mov ebxreg, ebx
01052         }
01053         // Then we mask the processor model, family, type and stepping
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         // To have complete information we also mask the brand id
01060         CPUInfo.uiBrandID  = ebxreg & 0xF;
01061 
01062         // Then we get the standard processor extensions
01063         GetStandardProcessorExtensions();
01064 
01065         // Now we mark everything we do not know as unknown
01066         strcpy(strCPUName, "Unknown");          /*Flawfinder: ignore*/
01067 
01068         strcpy(CPUInfo._Data.strTLB, "Unknown");        /*Flawfinder: ignore*/
01069         strcpy(CPUInfo._Instruction.strTLB, "Unknown");         /*Flawfinder: ignore*/
01070         
01071         strcpy(CPUInfo._Trace.strCache, "Unknown");             /*Flawfinder: ignore*/
01072         strcpy(CPUInfo._L1.Data.strCache, "Unknown");           /*Flawfinder: ignore*/
01073         strcpy(CPUInfo._L1.Instruction.strCache, "Unknown");    /*Flawfinder: ignore*/
01074         strcpy(CPUInfo._L2.strCache, "Unknown");                /*Flawfinder: ignore*/
01075         strcpy(CPUInfo._L3.strCache, "Unknown");                /*Flawfinder: ignore*/
01076 
01077         strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported");  /*Flawfinder: ignore*/
01078 
01079         // For the family, model and brand id we can only print the numeric value
01080         snprintf(CPUInfo.strBrandID, sizeof(CPUInfo.strBrandID), "Brand-ID number %d", CPUInfo.uiBrandID);              /* Flawfinder: ignore */
01081         snprintf(CPUInfo.strFamily, sizeof(CPUInfo.strFamily), "Family number %d", CPUInfo.uiFamily);           /* Flawfinder: ignore */
01082         snprintf(CPUInfo.strModel, sizeof(CPUInfo.strModel), "Model number %d", CPUInfo.uiModel);               /* Flawfinder: ignore */
01083 
01084         // And thats it
01085         return true;
01086 #else
01087         return FALSE;
01088 #endif
01089 }
01090 
01091 // bool CProcessor::CheckCPUIDPresence()
01092 // =====================================
01093 // This function checks if the CPUID command is available on the current
01094 // processor
01096 bool CProcessor::CheckCPUIDPresence()
01097 {
01098 #if LL_WINDOWS
01099         unsigned long BitChanged;
01100         
01101         // We've to check if we can toggle the flag register bit 21
01102         // If we can't the processor does not support the CPUID command
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 // void CProcessor::DecodeProcessorConfiguration(unsigned int cfg)
01124 // ===============================================================
01125 // This function (or switch ?!) just translates a one-byte processor configuration
01126 // byte to understandable values
01128 void CProcessor::DecodeProcessorConfiguration(unsigned int cfg)
01129 {
01130         // First we ensure that there's only one single byte
01131         cfg &= 0xFF;
01132 
01133         // Then we do a big switch
01134         switch(cfg)
01135         {
01136                 case 0:                 // cfg = 0:  Unused
01137                         break;
01138                 case 0x1:               // cfg = 0x1:  code TLB present, 4 KB pages, 4 ways, 32 entries
01139                         CPUInfo._Instruction.bPresent = true;
01140                         strcpy(CPUInfo._Instruction.strPageSize, "4 KB");       /*Flawfinder: ignore*/
01141                         CPUInfo._Instruction.uiAssociativeWays = 4;
01142                         CPUInfo._Instruction.uiEntries = 32;
01143                         break;
01144                 case 0x2:               // cfg = 0x2:  code TLB present, 4 MB pages, fully associative, 2 entries
01145                         CPUInfo._Instruction.bPresent = true;
01146                         strcpy(CPUInfo._Instruction.strPageSize, "4 MB");       /*Flawfinder: ignore*/
01147                         CPUInfo._Instruction.uiAssociativeWays = 4;
01148                         CPUInfo._Instruction.uiEntries = 2;
01149                         break;
01150                 case 0x3:               // cfg = 0x3:  data TLB present, 4 KB pages, 4 ways, 64 entries
01151                         CPUInfo._Data.bPresent = true;
01152                         strcpy(CPUInfo._Data.strPageSize, "4 KB");              /*Flawfinder: ignore*/
01153                         CPUInfo._Data.uiAssociativeWays = 4;
01154                         CPUInfo._Data.uiEntries = 64;
01155                         break;
01156                 case 0x4:               // cfg = 0x4:  data TLB present, 4 MB pages, 4 ways, 8 entries
01157                         CPUInfo._Data.bPresent = true;
01158                         strcpy(CPUInfo._Data.strPageSize, "4 MB");      /*Flawfinder: ignore*/
01159                         CPUInfo._Data.uiAssociativeWays = 4;
01160                         CPUInfo._Data.uiEntries = 8;
01161                         break;
01162                 case 0x6:               // cfg = 0x6:  code L1 cache present, 8 KB, 4 ways, 32 byte lines
01163                         CPUInfo._L1.Instruction.bPresent = true;
01164                         strcpy(CPUInfo._L1.Instruction.strSize, "8 KB");        /*Flawfinder: ignore*/
01165                         CPUInfo._L1.Instruction.uiAssociativeWays = 4;
01166                         CPUInfo._L1.Instruction.uiLineSize = 32;
01167                         break;
01168                 case 0x8:               // cfg = 0x8:  code L1 cache present, 16 KB, 4 ways, 32 byte lines
01169                         CPUInfo._L1.Instruction.bPresent = true;
01170                         strcpy(CPUInfo._L1.Instruction.strSize, "16 KB");       /*Flawfinder: ignore*/
01171                         CPUInfo._L1.Instruction.uiAssociativeWays = 4;
01172                         CPUInfo._L1.Instruction.uiLineSize = 32;
01173                         break;
01174                 case 0xA:               // cfg = 0xA:  data L1 cache present, 8 KB, 2 ways, 32 byte lines
01175                         CPUInfo._L1.Data.bPresent = true;
01176                         strcpy(CPUInfo._L1.Data.strSize, "8 KB");       /*Flawfinder: ignore*/
01177                         CPUInfo._L1.Data.uiAssociativeWays = 2;
01178                         CPUInfo._L1.Data.uiLineSize = 32;
01179                         break;
01180                 case 0xC:               // cfg = 0xC:  data L1 cache present, 16 KB, 4 ways, 32 byte lines
01181                         CPUInfo._L1.Data.bPresent = true;
01182                         strcpy(CPUInfo._L1.Data.strSize, "16 KB");      /*Flawfinder: ignore*/
01183                         CPUInfo._L1.Data.uiAssociativeWays = 4;
01184                         CPUInfo._L1.Data.uiLineSize = 32;
01185                         break;
01186                 case 0x22:              // cfg = 0x22:  code and data L3 cache present, 512 KB, 4 ways, 64 byte lines, sectored
01187                         CPUInfo._L3.bPresent = true;
01188                         strcpy(CPUInfo._L3.strSize, "512 KB");  /*Flawfinder: ignore*/
01189                         CPUInfo._L3.uiAssociativeWays = 4;
01190                         CPUInfo._L3.uiLineSize = 64;
01191                         CPUInfo._L3.bSectored = true;
01192                         break;
01193                 case 0x23:              // cfg = 0x23:  code and data L3 cache present, 1024 KB, 8 ways, 64 byte lines, sectored
01194                         CPUInfo._L3.bPresent = true;
01195                         strcpy(CPUInfo._L3.strSize, "1024 KB"); /*Flawfinder: ignore*/
01196                         CPUInfo._L3.uiAssociativeWays = 8;
01197                         CPUInfo._L3.uiLineSize = 64;
01198                         CPUInfo._L3.bSectored = true;
01199                         break;
01200                 case 0x25:              // cfg = 0x25:  code and data L3 cache present, 2048 KB, 8 ways, 64 byte lines, sectored
01201                         CPUInfo._L3.bPresent = true;
01202                         strcpy(CPUInfo._L3.strSize, "2048 KB"); /*Flawfinder: ignore*/
01203                         CPUInfo._L3.uiAssociativeWays = 8;
01204                         CPUInfo._L3.uiLineSize = 64;
01205                         CPUInfo._L3.bSectored = true;
01206                         break;
01207                 case 0x29:              // cfg = 0x29:  code and data L3 cache present, 4096 KB, 8 ways, 64 byte lines, sectored
01208                         CPUInfo._L3.bPresent = true;
01209                         strcpy(CPUInfo._L3.strSize, "4096 KB"); /*Flawfinder: ignore*/
01210                         CPUInfo._L3.uiAssociativeWays = 8;
01211                         CPUInfo._L3.uiLineSize = 64;
01212                         CPUInfo._L3.bSectored = true;
01213                         break;
01214                 case 0x40:              // cfg = 0x40:  no integrated L2 cache (P6 core) or L3 cache (P4 core)
01215                         break;
01216                 case 0x41:              // cfg = 0x41:  code and data L2 cache present, 128 KB, 4 ways, 32 byte lines
01217                         CPUInfo._L2.bPresent = true;
01218                         strcpy(CPUInfo._L2.strSize, "128 KB");          /*Flawfinder: ignore*/
01219                         CPUInfo._L2.uiAssociativeWays = 4;
01220                         CPUInfo._L2.uiLineSize = 32;
01221                         break;
01222                 case 0x42:              // cfg = 0x42:  code and data L2 cache present, 256 KB, 4 ways, 32 byte lines
01223                         CPUInfo._L2.bPresent = true;
01224                         strcpy(CPUInfo._L2.strSize, "256 KB");          /*Flawfinder: ignore*/
01225                         CPUInfo._L2.uiAssociativeWays = 4;
01226                         CPUInfo._L2.uiLineSize = 32;
01227                         break;
01228                 case 0x43:              // cfg = 0x43:  code and data L2 cache present, 512 KB, 4 ways, 32 byte lines
01229                         CPUInfo._L2.bPresent = true;
01230                         strcpy(CPUInfo._L2.strSize, "512 KB");          /* Flawfinder: ignore */
01231                         CPUInfo._L2.uiAssociativeWays = 4;
01232                         CPUInfo._L2.uiLineSize = 32;
01233                         break;
01234                 case 0x44:              // cfg = 0x44:  code and data L2 cache present, 1024 KB, 4 ways, 32 byte lines
01235                         CPUInfo._L2.bPresent = true;
01236                         strcpy(CPUInfo._L2.strSize, "1 MB");    /* Flawfinder: ignore */
01237                         CPUInfo._L2.uiAssociativeWays = 4;
01238                         CPUInfo._L2.uiLineSize = 32;
01239                         break;
01240                 case 0x45:              // cfg = 0x45:  code and data L2 cache present, 2048 KB, 4 ways, 32 byte lines
01241                         CPUInfo._L2.bPresent = true;
01242                         strcpy(CPUInfo._L2.strSize, "2 MB");    /* Flawfinder: ignore */
01243                         CPUInfo._L2.uiAssociativeWays = 4;
01244                         CPUInfo._L2.uiLineSize = 32;
01245                         break;
01246                 case 0x50:              // cfg = 0x50:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 64 entries
01247                         CPUInfo._Instruction.bPresent = true;
01248                         strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */
01249                         CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
01250                         CPUInfo._Instruction.uiEntries = 64;
01251                         break;
01252                 case 0x51:              // cfg = 0x51:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 128 entries
01253                         CPUInfo._Instruction.bPresent = true;
01254                         strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */
01255                         CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
01256                         CPUInfo._Instruction.uiEntries = 128;
01257                         break;
01258                 case 0x52:              // cfg = 0x52:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 256 entries
01259                         CPUInfo._Instruction.bPresent = true;
01260                         strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */
01261                         CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
01262                         CPUInfo._Instruction.uiEntries = 256;
01263                         break;
01264                 case 0x5B:              // cfg = 0x5B:  data TLB present, 4 KB / 4 MB pages, fully associative, 64 entries
01265                         CPUInfo._Data.bPresent = true;
01266                         strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");       /* Flawfinder: ignore */
01267                         CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
01268                         CPUInfo._Data.uiEntries = 64;
01269                         break;
01270                 case 0x5C:              // cfg = 0x5C:  data TLB present, 4 KB / 4 MB pages, fully associative, 128 entries
01271                         CPUInfo._Data.bPresent = true;
01272                         strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");       /* Flawfinder: ignore */
01273                         CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
01274                         CPUInfo._Data.uiEntries = 128;
01275                         break;
01276                 case 0x5d:              // cfg = 0x5D:  data TLB present, 4 KB / 4 MB pages, fully associative, 256 entries
01277                         CPUInfo._Data.bPresent = true;
01278                         strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");       /* Flawfinder: ignore */
01279                         CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
01280                         CPUInfo._Data.uiEntries = 256;
01281                         break;
01282                 case 0x66:              // cfg = 0x66:  data L1 cache present, 8 KB, 4 ways, 64 byte lines, sectored
01283                         CPUInfo._L1.Data.bPresent = true;
01284                         strcpy(CPUInfo._L1.Data.strSize, "8 KB");       /* Flawfinder: ignore */
01285                         CPUInfo._L1.Data.uiAssociativeWays = 4;
01286                         CPUInfo._L1.Data.uiLineSize = 64;
01287                         break;
01288                 case 0x67:              // cfg = 0x67:  data L1 cache present, 16 KB, 4 ways, 64 byte lines, sectored
01289                         CPUInfo._L1.Data.bPresent = true;
01290                         strcpy(CPUInfo._L1.Data.strSize, "16 KB");      /* Flawfinder: ignore */
01291                         CPUInfo._L1.Data.uiAssociativeWays = 4;
01292                         CPUInfo._L1.Data.uiLineSize = 64;
01293                         break;
01294                 case 0x68:              // cfg = 0x68:  data L1 cache present, 32 KB, 4 ways, 64 byte lines, sectored
01295                         CPUInfo._L1.Data.bPresent = true;
01296                         strcpy(CPUInfo._L1.Data.strSize, "32 KB");      /* Flawfinder: ignore */
01297                         CPUInfo._L1.Data.uiAssociativeWays = 4;
01298                         CPUInfo._L1.Data.uiLineSize = 64;
01299                         break;
01300                 case 0x70:              // cfg = 0x70:  trace L1 cache present, 12 KuOPs, 4 ways
01301                         CPUInfo._Trace.bPresent = true;
01302                         strcpy(CPUInfo._Trace.strSize, "12 K-micro-ops");       /* Flawfinder: ignore */
01303                         CPUInfo._Trace.uiAssociativeWays = 4;
01304                         break;
01305                 case 0x71:              // cfg = 0x71:  trace L1 cache present, 16 KuOPs, 4 ways
01306                         CPUInfo._Trace.bPresent = true;
01307                         strcpy(CPUInfo._Trace.strSize, "16 K-micro-ops");       /* Flawfinder: ignore */
01308                         CPUInfo._Trace.uiAssociativeWays = 4;
01309                         break;
01310                 case 0x72:              // cfg = 0x72:  trace L1 cache present, 32 KuOPs, 4 ways
01311                         CPUInfo._Trace.bPresent = true;
01312                         strcpy(CPUInfo._Trace.strSize, "32 K-micro-ops");       /* Flawfinder: ignore */
01313                         CPUInfo._Trace.uiAssociativeWays = 4;
01314                         break;
01315                 case 0x79:              // cfg = 0x79:  code and data L2 cache present, 128 KB, 8 ways, 64 byte lines, sectored
01316                         CPUInfo._L2.bPresent = true;
01317                         strcpy(CPUInfo._L2.strSize, "128 KB");  /* Flawfinder: ignore */
01318                         CPUInfo._L2.uiAssociativeWays = 8;
01319                         CPUInfo._L2.uiLineSize = 64;
01320                         CPUInfo._L2.bSectored = true;
01321                         break;
01322                 case 0x7A:              // cfg = 0x7A:  code and data L2 cache present, 256 KB, 8 ways, 64 byte lines, sectored
01323                         CPUInfo._L2.bPresent = true;
01324                         strcpy(CPUInfo._L2.strSize, "256 KB");  /* Flawfinder: ignore */
01325                         CPUInfo._L2.uiAssociativeWays = 8;
01326                         CPUInfo._L2.uiLineSize = 64;
01327                         CPUInfo._L2.bSectored = true;
01328                         break;
01329                 case 0x7B:              // cfg = 0x7B:  code and data L2 cache present, 512 KB, 8 ways, 64 byte lines, sectored
01330                         CPUInfo._L2.bPresent = true;
01331                         strcpy(CPUInfo._L2.strSize, "512 KB");  /* Flawfinder: ignore */
01332                         CPUInfo._L2.uiAssociativeWays = 8;
01333                         CPUInfo._L2.uiLineSize = 64;
01334                         CPUInfo._L2.bSectored = true;
01335                         break;
01336                 case 0x7C:              // cfg = 0x7C:  code and data L2 cache present, 1024 KB, 8 ways, 64 byte lines, sectored
01337                         CPUInfo._L2.bPresent = true;
01338                         strcpy(CPUInfo._L2.strSize, "1 MB");    /* Flawfinder: ignore */
01339                         CPUInfo._L2.uiAssociativeWays = 8;
01340                         CPUInfo._L2.uiLineSize = 64;
01341                         CPUInfo._L2.bSectored = true;
01342                         break;
01343                 case 0x81:              // cfg = 0x81:  code and data L2 cache present, 128 KB, 8 ways, 32 byte lines
01344                         CPUInfo._L2.bPresent = true;
01345                         strcpy(CPUInfo._L2.strSize, "128 KB");  /* Flawfinder: ignore */
01346                         CPUInfo._L2.uiAssociativeWays = 8;
01347                         CPUInfo._L2.uiLineSize = 32;
01348                         break;
01349                 case 0x82:              // cfg = 0x82:  code and data L2 cache present, 256 KB, 8 ways, 32 byte lines
01350                         CPUInfo._L2.bPresent = true;
01351                         strcpy(CPUInfo._L2.strSize, "256 KB");  /* Flawfinder: ignore */
01352                         CPUInfo._L2.uiAssociativeWays = 8;
01353                         CPUInfo._L2.uiLineSize = 32;
01354                         break;
01355                 case 0x83:              // cfg = 0x83:  code and data L2 cache present, 512 KB, 8 ways, 32 byte lines
01356                         CPUInfo._L2.bPresent = true;
01357                         strcpy(CPUInfo._L2.strSize, "512 KB");  /* Flawfinder: ignore */
01358                         CPUInfo._L2.uiAssociativeWays = 8;
01359                         CPUInfo._L2.uiLineSize = 32;
01360                         break;
01361                 case 0x84:              // cfg = 0x84:  code and data L2 cache present, 1024 KB, 8 ways, 32 byte lines
01362                         CPUInfo._L2.bPresent = true;
01363                         strcpy(CPUInfo._L2.strSize, "1 MB");    /* Flawfinder: ignore */
01364                         CPUInfo._L2.uiAssociativeWays = 8;
01365                         CPUInfo._L2.uiLineSize = 32;
01366                         break;
01367                 case 0x85:              // cfg = 0x85:  code and data L2 cache present, 2048 KB, 8 ways, 32 byte lines
01368                         CPUInfo._L2.bPresent = true;
01369                         strcpy(CPUInfo._L2.strSize, "2 MB");    /* Flawfinder: ignore */
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         // We define 0xFFFFFFFF (= -1) as fully associative
01379     if (uiWays == ((unsigned int) -1))
01380                 strcpy(buf, "fully associative");       /* Flawfinder: ignore */
01381         else
01382         {
01383                 if (uiWays == 1)                        // A one way associative cache is just direct mapped
01384                         strcpy(buf, "direct mapped");   /* Flawfinder: ignore */
01385                 else if (uiWays == 0)           // This should not happen...
01386                         strcpy(buf, "unknown associative ways");        /* Flawfinder: ignore */
01387                 else                                            // The x-way associative cache
01388                         sprintf(buf, "%d ways associative", uiWays);    /* Flawfinder: ignore */
01389         }
01390         // To ease the function use we return the buffer
01391         return buf;
01392 }
01393 FORCEINLINE static void TranslateTLB(ProcessorTLB *tlb)
01394 {
01395         char buf[64];   /* Flawfinder: ignore */
01396 
01397         // We just check if the TLB is present
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);     /* Flawfinder: ignore */
01400         else
01401         strcpy(tlb->strTLB, "Not present");     /* Flawfinder: ignore */
01402 }
01403 FORCEINLINE static void TranslateCache(ProcessorCache *cache)
01404 {
01405         char buf[64];   /* Flawfinder: ignore */
01406 
01407         // We just check if the cache is present
01408     if (cache->bPresent)
01409         {
01410                 // If present we construct the string
01411                 snprintf(cache->strCache, sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize);        /* Flawfinder: ignore */
01412                 if (cache->bSectored)
01413                         strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1);      /* Flawfinder: ignore */
01414         }
01415         else
01416         {
01417                 // Else we just say "Not present"
01418                 strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */
01419         }
01420 }
01421 
01422 // void CProcessor::TranslateProcessorConfiguration()
01423 // ==================================================
01424 // Private class function to translate the processor configuration values
01425 // to strings
01427 void CProcessor::TranslateProcessorConfiguration()
01428 {
01429         // We just call the small functions defined above
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 // void CProcessor::GetStandardProcessorConfiguration()
01442 // ====================================================
01443 // Private class function to read the standard processor configuration
01445 void CProcessor::GetStandardProcessorConfiguration()
01446 {
01447 #if LL_WINDOWS
01448         unsigned long eaxreg, ebxreg, ecxreg, edxreg;
01449 
01450         // We check if the CPUID function is available
01451         if (!CheckCPUIDPresence())
01452                 return;
01453 
01454         // First we check if the processor supports the standard
01455         // CPUID level 0x00000002
01456         if (CPUInfo.MaxSupportedLevel >= 2)
01457         {
01458                 // Now we go read the std. CPUID level 0x00000002 the first time
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                         // We have to repeat this reading for 'num' times
01472                         num = eaxreg & 0xFF;
01473 
01474                         // Then we call the big decode switch function
01475                         DecodeProcessorConfiguration(eaxreg >> 8);
01476                         DecodeProcessorConfiguration(eaxreg >> 16);
01477                         DecodeProcessorConfiguration(eaxreg >> 24);
01478 
01479                         // If ebx contains additional data we also decode it
01480                         if ((ebxreg & 0x80000000) == 0)
01481                         {
01482                                 DecodeProcessorConfiguration(ebxreg);
01483                                 DecodeProcessorConfiguration(ebxreg >> 8);
01484                                 DecodeProcessorConfiguration(ebxreg >> 16);
01485                                 DecodeProcessorConfiguration(ebxreg >> 24);
01486                         }
01487                         // And also the ecx register
01488                         if ((ecxreg & 0x80000000) == 0)
01489                         {
01490                                 DecodeProcessorConfiguration(ecxreg);
01491                                 DecodeProcessorConfiguration(ecxreg >> 8);
01492                                 DecodeProcessorConfiguration(ecxreg >> 16);
01493                                 DecodeProcessorConfiguration(ecxreg >> 24);
01494                         }
01495                         // At last the edx processor register
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 // void CProcessor::GetStandardProcessorExtensions()
01509 // =================================================
01510 // Private class function to read the standard processor extensions
01512 void CProcessor::GetStandardProcessorExtensions()
01513 {
01514 #if LL_WINDOWS
01515         unsigned long ebxreg, edxreg;
01516 
01517         // We check if the CPUID command is available
01518         if (!CheckCPUIDPresence())
01519                 return;
01520         // We just get the standard CPUID level 0x00000001 which should be
01521         // available on every x86 processor
01522         __asm
01523         {
01524                 mov eax, 1
01525                 cpuid
01526                 mov ebxreg, ebx
01527                 mov edxreg, edx
01528         }
01529     
01530         // Then we mask some bits
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 // const ProcessorInfo *CProcessor::GetCPUInfo()
01568 // =============================================
01569 // Calls all the other detection function to create an detailed
01570 // processor information
01572 const ProcessorInfo *CProcessor::GetCPUInfo()
01573 {
01574 #if LL_WINDOWS
01575         unsigned long eaxreg, ebxreg, ecxreg, edxreg;
01576  
01577         // First of all we check if the CPUID command is available
01578         if (!CheckCPUIDPresence())
01579                 return NULL;
01580 
01581         // We read the standard CPUID level 0x00000000 which should
01582         // be available on every x86 processor
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         // Then we connect the single register values to the vendor string
01593         *((unsigned long *) CPUInfo.strVendor) = ebxreg;
01594         *((unsigned long *) (CPUInfo.strVendor+4)) = edxreg;
01595         *((unsigned long *) (CPUInfo.strVendor+8)) = ecxreg;
01596         // Null terminate for string comparisons below.
01597         CPUInfo.strVendor[12] = 0;
01598 
01599         // We can also read the max. supported standard CPUID level
01600         CPUInfo.MaxSupportedLevel = eaxreg & 0xFFFF;
01601 
01602         // Then we read the ext. CPUID level 0x80000000
01603         __asm
01604         {
01605         mov eax, 0x80000000
01606                 cpuid
01607                 mov eaxreg, eax
01608         }
01609         // ...to check the max. supportted extended CPUID level
01610         CPUInfo.MaxSupportedExtendedLevel = eaxreg;
01611 
01612         // Then we switch to the specific processor vendors
01613         // See http://www.sandpile.org/ia32/cpuid.htm
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                 // Transmeta
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         // After all we return the class CPUInfo member var
01661         return (&CPUInfo);
01662 }
01663 
01664 #elif LL_SOLARIS
01665 #include <kstat.h>
01666 
01667 // ======================
01668 // Class constructor:
01670 CProcessor::CProcessor()
01671 {
01672         uqwFrequency = 0;
01673         strCPUName[0] = 0;
01674         memset(&CPUInfo, 0, sizeof(CPUInfo));
01675 }
01676 
01677 // unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
01678 // =========================================================================
01679 // Function to query the current CPU frequency
01681 F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/)
01682 {
01683         if(uqwFrequency == 0){
01684                 GetCPUInfo();
01685         }
01686 
01687         return uqwFrequency;
01688 }
01689 
01690 // const ProcessorInfo *CProcessor::GetCPUInfo()
01691 // =============================================
01692 // Calls all the other detection function to create an detailed
01693 // processor information
01695 const ProcessorInfo *CProcessor::GetCPUInfo()
01696 {
01697                                         // In Solaris the CPU info is in the kstats
01698                                         // try "psrinfo" or "kstat cpu_info" to see all
01699                                         // that's available
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;    // only looking at the first CPU
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){ // Walk the kstats for this cpu gathering what we need
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                         // DEBUG llinfos << "CPU brand: " << strCPUName << llendl;
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                         //DEBUG llinfos << "CPU frequency: " << uqwFrequency << llendl;
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                         // DEBUG llinfos << "CPU vendor: " << CPUInfo.strVendor << llendl;
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         // DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " <<  uqwFrequency << "MHz." << llendl;
01779         
01780         return (&CPUInfo);
01781 }
01782 
01783 #else
01784 // LL_DARWIN
01785 
01786 #include <mach/machine.h>
01787 #include <sys/sysctl.h>
01788 
01789 static char *TranslateAssociativeWays(unsigned int uiWays, char *buf)
01790 {
01791         // We define 0xFFFFFFFF (= -1) as fully associative
01792     if (uiWays == ((unsigned int) -1))
01793                 strcpy(buf, "fully associative");       /* Flawfinder: ignore */
01794         else
01795         {
01796                 if (uiWays == 1)                        // A one way associative cache is just direct mapped
01797                         strcpy(buf, "direct mapped");   /* Flawfinder: ignore */
01798                 else if (uiWays == 0)           // This should not happen...
01799                         strcpy(buf, "unknown associative ways");        /* Flawfinder: ignore */
01800                 else                                            // The x-way associative cache
01801                         sprintf(buf, "%d ways associative", uiWays);    /* Flawfinder: ignore */
01802         }
01803         // To ease the function use we return the buffer
01804         return buf;
01805 }
01806 static void TranslateTLB(ProcessorTLB *tlb)
01807 {
01808         char buf[64];   /* Flawfinder: ignore */
01809 
01810         // We just check if the TLB is present
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);    /* Flawfinder: ignore */
01813         else
01814         strcpy(tlb->strTLB, "Not present");     /* Flawfinder: ignore */
01815 }
01816 static void TranslateCache(ProcessorCache *cache)
01817 {
01818         char buf[64];   /* Flawfinder: ignore */
01819 
01820         // We just check if the cache is present
01821     if (cache->bPresent)
01822         {
01823                 // If present we construct the string
01824                 snprintf(cache->strCache,sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */
01825                 if (cache->bSectored)
01826                         strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1);      /* Flawfinder: ignore */
01827         }
01828         else
01829         {
01830                 // Else we just say "Not present"
01831                 strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */
01832         }
01833 }
01834 
01835 // void CProcessor::TranslateProcessorConfiguration()
01836 // ==================================================
01837 // Private class function to translate the processor configuration values
01838 // to strings
01840 void CProcessor::TranslateProcessorConfiguration()
01841 {
01842         // We just call the small functions defined above
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 // CProcessor::CProcessor
01855 // ======================
01856 // Class constructor:
01858 CProcessor::CProcessor()
01859 {
01860         uqwFrequency = 0;
01861         strCPUName[0] = 0;
01862         memset(&CPUInfo, 0, sizeof(CPUInfo));
01863 }
01864 
01865 // unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
01866 // =========================================================================
01867 // Function to query the current CPU frequency
01869 F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/)
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 // const ProcessorInfo *CProcessor::GetCPUInfo()
01898 // =============================================
01899 // Calls all the other detection function to create an detailed
01900 // processor information
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         // sysctl knows all.
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                 // Uhhh...
01963         }
01964         else if(ncpu == 2)
01965         {
01966                 strncat(strCPUName, "Dual ", sizeof(strCPUName)-strlen(strCPUName)-1);  /* Flawfinder: ignore */
01967         }
01968         else
01969         {
01970                 snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpu);        /* Flawfinder: ignore */
01971         }
01972         
01973 #if __ppc__
01974         switch(cpusubtype)
01975         {
01976                 case CPU_SUBTYPE_POWERPC_601://         ((cpu_subtype_t) 1)
01977                         strncat(strCPUName, "PowerPC 601", sizeof(strCPUName)-strlen(strCPUName)-1);    /* Flawfinder: ignore */
01978                         strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);   /* Flawfinder: ignore */
01979                         
01980                 break;
01981                 case CPU_SUBTYPE_POWERPC_602://         ((cpu_subtype_t) 2)
01982                         strncat(strCPUName, "PowerPC 602", sizeof(strCPUName)-strlen(strCPUName)-1);    /* Flawfinder: ignore */
01983                         strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);   /* Flawfinder: ignore */
01984                 break;
01985                 case CPU_SUBTYPE_POWERPC_603://         ((cpu_subtype_t) 3)
01986                         strncat(strCPUName, "PowerPC 603", sizeof(strCPUName)-strlen(strCPUName)-1);    /* Flawfinder: ignore */
01987                         strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);   /* Flawfinder: ignore */
01988                 break;
01989                 case CPU_SUBTYPE_POWERPC_603e://        ((cpu_subtype_t) 4)
01990                         strncat(strCPUName, "PowerPC 603e", sizeof(strCPUName)-strlen(strCPUName)-1);   /* Flawfinder: ignore */
01991                         strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);   /* Flawfinder: ignore */
01992                 break;
01993                 case CPU_SUBTYPE_POWERPC_603ev://       ((cpu_subtype_t) 5)
01994                         strncat(strCPUName, "PowerPC 603ev", sizeof(strCPUName)-strlen(strCPUName)-1);  /* Flawfinder: ignore */
01995                         strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);   /* Flawfinder: ignore */
01996                 break;
01997                 case CPU_SUBTYPE_POWERPC_604://         ((cpu_subtype_t) 6)
01998                         strncat(strCPUName, "PowerPC 604", sizeof(strCPUName)-strlen(strCPUName)-1);    /* Flawfinder: ignore */
01999                         strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);   /* Flawfinder: ignore */
02000                 break;
02001                 case CPU_SUBTYPE_POWERPC_604e://        ((cpu_subtype_t) 7)
02002                         strncat(strCPUName, "PowerPC 604e", sizeof(strCPUName)-strlen(strCPUName)-1);   /* Flawfinder: ignore */
02003                         strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);   /* Flawfinder: ignore */
02004                 break;
02005                 case CPU_SUBTYPE_POWERPC_620://                 ((cpu_subtype_t) 8)
02006                         strncat(strCPUName, "PowerPC 620", sizeof(strCPUName)-strlen(strCPUName)-1);    /* Flawfinder: ignore */
02007                         strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);   /* Flawfinder: ignore */
02008                 break;
02009                 case CPU_SUBTYPE_POWERPC_750://         ((cpu_subtype_t) 9)
02010                         strncat(strCPUName, "PowerPC 750", sizeof(strCPUName)-strlen(strCPUName)-1);    /* Flawfinder: ignore */
02011                         strncat(CPUInfo.strFamily, "PowerPC G3", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);        /* Flawfinder: ignore */
02012                 break;
02013                 case CPU_SUBTYPE_POWERPC_7400://        ((cpu_subtype_t) 10)
02014                         strncat(strCPUName, "PowerPC 7400", sizeof(strCPUName)-strlen(strCPUName)-1);   /* Flawfinder: ignore */
02015                         strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);        /* Flawfinder: ignore */
02016                 break;
02017                 case CPU_SUBTYPE_POWERPC_7450://        ((cpu_subtype_t) 11)
02018                         strncat(strCPUName, "PowerPC 7450", sizeof(strCPUName)-strlen(strCPUName)-1);   /* Flawfinder: ignore */
02019                         strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);        /* Flawfinder: ignore */
02020                 break;
02021                 case CPU_SUBTYPE_POWERPC_970://         ((cpu_subtype_t) 100)
02022                         strncat(strCPUName, "PowerPC 970", sizeof(strCPUName)-strlen(strCPUName)-1);    /* Flawfinder: ignore */
02023                         strncat(CPUInfo.strFamily, "PowerPC G5", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);        /* Flawfinder: ignore */
02024                 break;
02025 
02026                 default:
02027                         strncat(strCPUName, "PowerPC (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1);      /* Flawfinder: ignore */
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         // MBW -- XXX -- TODO -- make this call AnalyzeIntelProcessor()?
02042         switch(cpusubtype)
02043         {
02044                 default:
02045                         strncat(strCPUName, "i386 (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */        
02046                 break;
02047         }
02048 
02049         CPUInfo._Ext.EMMX_MultimediaExtensions = hasFeature("hw.optional.mmx");  // MBW -- XXX -- this may be wrong...
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         // Terse CPU info uses this string...
02059         strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1);   /* Flawfinder: ignore */        
02060         CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
02061         
02062         // Fun cache config stuff...
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);     /* Flawfinder: ignore */
02068 //              CPUInfo._L1.Data.uiAssociativeWays = ???;
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);       /* Flawfinder: ignore */
02076 //              CPUInfo._L1.Instruction.uiAssociativeWays = ???;
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);        /* Flawfinder: ignore */
02084 //              CPUInfo._L2.uiAssociativeWays = ???;
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);        /* Flawfinder: ignore */
02092 //              CPUInfo._L2.uiAssociativeWays = ???;
02093                 CPUInfo._L2.uiLineSize = cachelinesize;
02094         }
02095         
02096         CPUInfo._Ext.FPU_FloatingPointUnit = hasFeature("hw.optional.floatingpoint");
02097 
02098 //      printf("pagesize = 0x%x\n", pagesize);
02099 //      printf("cachelinesize = 0x%x\n", cachelinesize);
02100 //      printf("l1icachesize = 0x%x\n", l1icachesize);
02101 //      printf("l1dcachesize = 0x%x\n", l1dcachesize);
02102 //      printf("l2settings = 0x%x\n", l2settings);
02103 //      printf("l2cachesize = 0x%x\n", l2cachesize);
02104 //      printf("l3settings = 0x%x\n", l3settings);
02105 //      printf("l3cachesize = 0x%x\n", l3cachesize);
02106         
02107         // After reading we translate the configuration to strings
02108         TranslateProcessorConfiguration();
02109 
02110         // After all we return the class CPUInfo member var
02111         return (&CPUInfo);
02112 }
02113 
02114 #endif // LL_DARWIN
02115 
02116 // bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
02117 // ======================================================================
02118 // Gets the frequency and processor information and writes it to a string
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;     /*Flawfinder: ignore*/
02123 #define COPYADD(str)            strcpy(buf, str); LENCHECK;    /* Flawfinder: ignore */
02124 #define FORMATADD(format, var)  sprintf(buf, format, var); LENCHECK;    /* Flawfinder: ignore */
02125 #define BOOLADD(str, boolvar)   COPYADD(str); if (boolvar) { COPYADD(" Yes\n"); } else { COPYADD(" No\n"); }
02126 
02127         char buf[1024]; /* Flawfinder: ignore */        
02128         unsigned int len;
02129 
02130         // First we have to get the frequency
02131     GetCPUFrequency(50);
02132 
02133         // Then we get the processor information
02134         GetCPUInfo();
02135 
02136     // Now we construct the string (see the macros at function beginning)
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         // Yippie!!!
02216         return true;
02217 }
02218 
02219 // bool CProcessor::WriteInfoTextFile(const char *strFilename)
02220 // ===========================================================
02221 // Takes use of CProcessor::CPUInfoToText and saves the string to a
02222 // file
02224 bool CProcessor::WriteInfoTextFile(const char *strFilename)
02225 {
02226         char buf[16384];        /* Flawfinder: ignore */        
02227 
02228         // First we get the string
02229         if (!CPUInfoToText(buf, 16383))
02230                 return false;
02231 
02232         // Then we create a new file (CREATE_ALWAYS)
02233         FILE *file = LLFile::fopen(strFilename, "w");   /* Flawfinder: ignore */        
02234         if (!file)
02235                 return false;
02236 
02237         // After that we write the string to the file
02238         unsigned long dwBytesToWrite, dwBytesWritten;
02239         dwBytesToWrite = (unsigned long) strlen(buf);    /*Flawfinder: ignore*/
02240         dwBytesWritten = (unsigned long) fwrite(buf, 1, dwBytesToWrite, file);
02241         fclose(file);
02242         if (dwBytesToWrite != dwBytesWritten)
02243                 return false;
02244 
02245         // Done
02246         return true;
02247 }

Generated on Thu Jul 1 06:09:03 2010 for Second Life Viewer by  doxygen 1.4.7