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