Back to index

lshw  02.16
cpuinfo.cc
Go to the documentation of this file.
00001 #include "version.h"
00002 #include "cpuinfo.h"
00003 #include "osutils.h"
00004 #include <sys/types.h>
00005 #include <sys/stat.h>
00006 #include <fcntl.h>
00007 #include <unistd.h>
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <vector>
00011 
00012 __ID("@(#) $Id: cpuinfo.cc 2433 2012-01-10 22:01:30Z lyonel $");
00013 
00014 static int currentcpu = 0;
00015 
00016 static hwNode *getcpu(hwNode & node,
00017 int n = 0)
00018 {
00019   char cpubusinfo[10];
00020   hwNode *cpu = NULL;
00021 
00022   if (n < 0)
00023     n = 0;
00024 
00025   snprintf(cpubusinfo, sizeof(cpubusinfo), "cpu@%d", n);
00026   cpu = node.findChildByBusInfo(cpubusinfo);
00027 
00028   if (cpu)
00029   {
00030     cpu->addHint("icon", string("cpu"));
00031     cpu->claim(true);                             // claim the cpu and all its children
00032     cpu->enable();                                // enable it
00033     return cpu;
00034   }
00035 
00036   hwNode *core = node.getChild("core");
00037 
00038   if (core)
00039   {
00040     hwNode newcpu("cpu", hw::processor);
00041 
00042     newcpu.setBusInfo(cpubusinfo);
00043     newcpu.claim();
00044     return core->addChild(newcpu);
00045   }
00046   else
00047     return NULL;
00048 }
00049 
00050 
00051 #ifdef __powerpc__
00052 static void cpuinfo_ppc(hwNode & node,
00053 string id,
00054 string value)
00055 {
00056   if (id == "processor")
00057     currentcpu++;
00058 
00059   hwNode *cpu = getcpu(node, currentcpu);
00060 
00061   if (cpu)
00062   {
00063     cpu->addHint("logo", string("powerpc"));
00064     cpu->claim(true);
00065     if (id == "revision")
00066       cpu->setVersion(value);
00067     if (id == "cpu")
00068       cpu->setProduct(value);
00069   }
00070 }
00071 #endif
00072 
00073 #ifdef __ia64__
00074 static void cpuinfo_ia64(hwNode & node,
00075 string id,
00076 string value)
00077 {
00078   unsigned long long frequency = 0;
00079   int i;
00080 
00081   if (id == "processor")
00082     currentcpu++;
00083 
00084   hwNode *cpu = getcpu(node, currentcpu);
00085 
00086   if (cpu)
00087   {
00088     cpu->claim(true);
00089 
00090     if (id == "cpu number")
00091     {
00092       int physicalcpu = 0;
00093 
00094       physicalcpu = atoi(value.c_str());
00095 
00096       if (physicalcpu != currentcpu)
00097       {
00098         cpu->addCapability("emulated");
00099         cpu->addCapability("hyperthreading");
00100       }
00101     }
00102 
00103     if (id == "vendor")
00104     {
00105       if (value == "GenuineIntel")
00106         value = "Intel Corp.";
00107       cpu->setVendor(value);
00108     }
00109 
00110     if (id == "revision")
00111       cpu->setVersion(value);
00112 
00113     if (id == "family")
00114       cpu->setProduct(value);
00115 
00116     if (id == "cpu MHz" && cpu->getSize() == 0)
00117     {
00118       double frequency = 0.0;
00119 
00120       frequency = atof(value.c_str());
00121       cpu->setSize((unsigned long long) (frequency * 1E6));
00122     }
00123   }
00124 }
00125 #endif
00126 
00127 #ifdef __hppa__
00128 static void cpuinfo_hppa(hwNode & node,
00129 string id,
00130 string value)
00131 {
00132   if (id == "processor")
00133     currentcpu++;
00134 
00135   hwNode *cpu = getcpu(node, currentcpu);
00136 
00137   if (id == "model" && node.getProduct() == "")
00138     node.setProduct(value);
00139   if (id == "model name" && node.getDescription() == "")
00140     node.setDescription(value);
00141   if (id == "software id" && node.getSerial() == "")
00142     node.setSerial(value);
00143 
00144   if (cpu)
00145   {
00146     cpu->claim(true);
00147 
00148     if (id == "cpu family" && cpu->getVersion() == "")
00149       cpu->setVersion(value);
00150     if (id == "cpu" && cpu->getProduct() == "")
00151       cpu->setProduct(value);
00152     if (id == "cpu MHz" && cpu->getSize() == 0)
00153     {
00154       double frequency = 0.0;
00155 
00156       frequency = atof(value.c_str());
00157       cpu->setSize((unsigned long long) (frequency * 1E6));
00158     }
00159   }
00160 }
00161 #endif
00162 
00163 #ifdef __alpha__
00164 static void cpuinfo_alpha(hwNode & node,
00165 string id,
00166 string value)
00167 {
00168   static int cpusdetected = 0;
00169   static int cpusactive = 0;
00170   unsigned long long frequency = 0;
00171   int i;
00172 
00173   hwNode *cpu = getcpu(node, 0);
00174 
00175   if (id == "platform string" && node.getProduct() == "")
00176     node.setProduct(value);
00177   if (id == "system serial number" && node.getSerial() == "")
00178     node.setSerial(value);
00179   if (id == "system type")
00180     node.setVersion(node.getVersion() + " " + value);
00181   if (id == "system variation")
00182     node.setVersion(node.getVersion() + " " + value);
00183   if (id == "system revision")
00184     node.setVersion(node.getVersion() + " " + value);
00185 
00186   if (id == "cpus detected")
00187     cpusdetected = atoi(value.c_str());
00188   if (id == "cpus active")
00189     cpusactive = atoi(value.c_str());
00190   if (id == "cycle frequency [Hz]")
00191     frequency = atoll(value.c_str());
00192 
00193   if (cpu)
00194   {
00195     cpu->claim(true);
00196 
00197     if (frequency)
00198       cpu->setSize(frequency);
00199   }
00200 
00201   for (i = 1; i < cpusdetected; i++)
00202   {
00203     hwNode *mycpu = getcpu(node, i);
00204 
00205     if (mycpu)
00206     {
00207       mycpu->disable();
00208 
00209       if (cpu)
00210         mycpu->setSize(cpu->getSize());
00211     }
00212   }
00213   for (i = 1; i < cpusactive; i++)
00214   {
00215     hwNode *mycpu = getcpu(node, i);
00216 
00217     if (mycpu)
00218       mycpu->enable();
00219   }
00220 }
00221 #endif
00222 
00223 #if defined(__i386__) || defined(__x86_64__)
00224 static void cpuinfo_x86(hwNode & node,
00225 string id,
00226 string value)
00227 {
00228   static int siblings = -1;
00229 
00230   if(currentcpu < 0) siblings = -1;
00231 
00232   if ((siblings<0) && (id == "siblings"))
00233   {
00234     siblings = atoi(value.c_str());
00235     siblings--;
00236   }
00237 
00238   if (id == "processor")
00239   {
00240     siblings--;
00241 
00242     if(siblings >= 0)
00243       return;
00244     else
00245       currentcpu++;
00246   }
00247 
00248   hwNode *cpu = getcpu(node, currentcpu);
00249 
00250   if (cpu)
00251   {
00252 
00253 // x86 CPUs are assumed to be 32 bits per default
00254     if(cpu->getWidth()==0) cpu->setWidth(32);
00255 
00256     cpu->claim(true);
00257     if (id == "vendor_id")
00258     {
00259       if (value == "AuthenticAMD")
00260         value = "Advanced Micro Devices [AMD]";
00261       if (value == "GenuineIntel")
00262         value = "Intel Corp.";
00263       cpu->setVendor(value);
00264     }
00265     if (id == "model name")
00266       cpu->setProduct(value);
00267 //if ((id == "cpu MHz") && (cpu->getSize() == 0))
00268 //{
00269 //cpu->setSize((long long) (1000000L * atof(value.c_str())));
00270 //}
00271     if (id == "Physical processor ID")
00272       cpu->setSerial(value);
00273     if ((id == "fdiv_bug") && (value == "yes"))
00274       cpu->addCapability("fdiv_bug");
00275     if ((id == "hlt_bug") && (value == "yes"))
00276       cpu->addCapability("hlt_bug");
00277     if ((id == "f00f_bug") && (value == "yes"))
00278       cpu->addCapability("f00f_bug");
00279     if ((id == "coma_bug") && (value == "yes"))
00280       cpu->addCapability("coma_bug");
00281     if ((id == "fpu") && (value == "yes"))
00282       cpu->addCapability("fpu");
00283     if ((id == "wp") && (value == "yes"))
00284       cpu->addCapability("wp");
00285     if ((id == "fpu_exception") && (value == "yes"))
00286       cpu->addCapability("fpu_exception", "FPU exceptions reporting");
00287     if (id == "flags")
00288       while (value.length() > 0)
00289     {
00290       size_t pos = value.find(' ');
00291       string capability = (pos==string::npos)?value:value.substr(0, pos);
00292 
00293       if(capability == "lm") capability = "x86-64";
00294 
00295       cpu->addCapability(capability);
00296 
00297       if (pos == string::npos)
00298         value = "";
00299       else
00300         value = hw::strip(value.substr(pos));
00301     }
00302 
00303     cpu->describeCapability("fpu", "mathematical co-processor");
00304     cpu->describeCapability("vme", "virtual mode extensions");
00305     cpu->describeCapability("de", "debugging extensions");
00306     cpu->describeCapability("pse", "page size extensions");
00307     cpu->describeCapability("tsc", "time stamp counter");
00308     cpu->describeCapability("msr", "model-specific registers");
00309     cpu->describeCapability("mce", "machine check exceptions");
00310     cpu->describeCapability("cx8", "compare and exchange 8-byte");
00311     cpu->describeCapability("apic", "on-chip advanced programmable interrupt controller (APIC)");
00312     cpu->describeCapability("sep", "fast system calls");
00313     cpu->describeCapability("mtrr", "memory type range registers");
00314     cpu->describeCapability("pge", "page global enable");
00315     cpu->describeCapability("mca", "machine check architecture");
00316     cpu->describeCapability("cmov", "conditional move instruction");
00317     cpu->describeCapability("pat", "page attribute table");
00318     cpu->describeCapability("pse36", "36-bit page size extensions");
00319     cpu->describeCapability("pn", "processor serial number");
00320     cpu->describeCapability("psn", "processor serial number");
00321 //cpu->describeCapability("clflush", "");
00322     cpu->describeCapability("dts", "debug trace and EMON store MSRs");
00323     cpu->describeCapability("acpi", "thermal control (ACPI)");
00324     cpu->describeCapability("fxsr", "fast floating point save/restore");
00325     cpu->describeCapability("sse", "streaming SIMD extensions (SSE)");
00326     cpu->describeCapability("sse2", "streaming SIMD extensions (SSE2)");
00327     cpu->describeCapability("ss", "self-snoop");
00328     cpu->describeCapability("tm", "thermal interrupt and status");
00329     cpu->describeCapability("ia64", "IA-64 (64-bit Intel CPU)");
00330     cpu->describeCapability("pbe", "pending break event");
00331     cpu->describeCapability("syscall", "fast system calls");
00332     cpu->describeCapability("mp", "multi-processor capable");
00333     cpu->describeCapability("nx", "no-execute bit (NX)");
00334     cpu->describeCapability("mmxext", "multimedia extensions (MMXExt)");
00335     cpu->describeCapability("3dnowext", "multimedia extensions (3DNow!Ext)");
00336     cpu->describeCapability("3dnow", "multimedia extensions (3DNow!)");
00337 //cpu->describeCapability("recovery", "");
00338     cpu->describeCapability("longrun", "LongRun Dynamic Power/Thermal Management");
00339     cpu->describeCapability("lrti", "LongRun Table Interface");
00340     cpu->describeCapability("cxmmx", "multimedia extensions (Cyrix MMX)");
00341     cpu->describeCapability("k6_mtrr", "AMD K6 MTRRs");
00342 //cpu->describeCapability("cyrix_arr", "");
00343 //cpu->describeCapability("centaur_mcr", "");
00344 //cpu->describeCapability("pni", "");
00345 //cpu->describeCapability("monitor", "");
00346 //cpu->describeCapability("ds_cpl", "");
00347 //cpu->describeCapability("est", "");
00348 //cpu->describeCapability("tm2", "");
00349 //cpu->describeCapability("cid", "");
00350 //cpu->describeCapability("xtpr", "");
00351     cpu->describeCapability("rng", "random number generator");
00352     cpu->describeCapability("rng_en", "random number generator (enhanced)");
00353     cpu->describeCapability("ace", "advanced cryptography engine");
00354     cpu->describeCapability("ace_en", "advanced cryptography engine (enhanced)");
00355     cpu->describeCapability("ht", "HyperThreading");
00356     cpu->describeCapability("lm", "64bits extensions (x86-64)");
00357     cpu->describeCapability("x86-64", "64bits extensions (x86-64)");
00358     cpu->describeCapability("mmx", "multimedia extensions (MMX)");
00359     cpu->describeCapability("pae", "4GB+ memory addressing (Physical Address Extension)");
00360 
00361     if(cpu->isCapable("ia64") || cpu->isCapable("lm") || cpu->isCapable("x86-64"))
00362       cpu->setWidth(64);
00363 
00364     if(node.getWidth()==0) node.setWidth(cpu->getWidth());
00365   }
00366 }
00367 #endif
00368 
00369 bool scan_cpuinfo(hwNode & n)
00370 {
00371   hwNode *core = n.getChild("core");
00372   int cpuinfo = open("/proc/cpuinfo", O_RDONLY);
00373 
00374   if (cpuinfo < 0)
00375     return false;
00376 
00377   if (!core)
00378   {
00379     n.addChild(hwNode("core", hw::bus));
00380     core = n.getChild("core");
00381   }
00382 
00383   if (core)
00384   {
00385     char buffer[1024];
00386     size_t count;
00387     string cpuinfo_str = "";
00388 
00389     while ((count = read(cpuinfo, buffer, sizeof(buffer))) > 0)
00390     {
00391       cpuinfo_str += string(buffer, count);
00392     }
00393     close(cpuinfo);
00394 
00395     vector < string > cpuinfo_lines;
00396     splitlines(cpuinfo_str, cpuinfo_lines);
00397     cpuinfo_str = "";                             // free memory
00398     currentcpu = -1;
00399 
00400     for (unsigned int i = 0; i < cpuinfo_lines.size(); i++)
00401     {
00402       string id = "";
00403       string value = "";
00404       size_t pos = 0;
00405 
00406       pos = cpuinfo_lines[i].find(':');
00407 
00408       if (pos != string::npos)
00409       {
00410         id = hw::strip(cpuinfo_lines[i].substr(0, pos));
00411         value = hw::strip(cpuinfo_lines[i].substr(pos + 1));
00412 
00413 #if defined(__i386__) || defined(__x86_64__)
00414         cpuinfo_x86(n, id, value);
00415 #endif
00416 #ifdef __powerpc__
00417         cpuinfo_ppc(n, id, value);
00418 #endif
00419 #ifdef __hppa__
00420         cpuinfo_hppa(n, id, value);
00421 #endif
00422 #ifdef __alpha__
00423         cpuinfo_alpha(n, id, value);
00424 #endif
00425 #ifdef __ia64__
00426         cpuinfo_ia64(n, id, value);
00427 #endif
00428       }
00429     }
00430   }
00431   else
00432   {
00433     close(cpuinfo);
00434     return false;
00435   }
00436 
00437   hwNode *cpu = getcpu(n, 0);
00438   if(cpu && (n.getWidth()==0))
00439     n.setWidth(cpu->getWidth());
00440 
00441   return true;
00442 }