Search code examples
c++assemblygccx86cpuid

How do I call "cpuid" in Linux?


While writing new code for Windows, I stumbled upon _cpuinfo() from the Windows API. As I am mainly dealing with a Linux environment (GCC) I want to have access to the CPUInfo.

I have tried the following:

#include <iostream>
 
int main()
{
  int a, b;
 
  for (a = 0; a < 5; a++)
  {
    __asm ( "mov %1, %%eax; "            // a into eax
          "cpuid;"
          "mov %%eax, %0;"             // eax into b
          :"=r"(b)                     // output
          :"r"(a)                      // input
          :"%eax","%ebx","%ecx","%edx" // clobbered register
         );
    std::cout << "The CPUID level " << a << " gives EAX= " << b << '\n';
  }
 
  return 0;
}

This use assembly but I don't want to re-invent the wheel. Is there any other way to implement CPUInfo without assembly?


Solution

  • Since you are compiling with GCC then you can include cpuid.h which declares these functions:

    /* Return highest supported input value for cpuid instruction.  ext can
       be either 0x0 or 0x8000000 to return highest supported value for
       basic or extended cpuid information.  Function returns 0 if cpuid
       is not supported or whatever cpuid returns in eax register.  If sig
       pointer is non-null, then first four bytes of the signature
       (as found in ebx register) are returned in location pointed by sig.  */
    unsigned int __get_cpuid_max (unsigned int __ext, unsigned int *__sig)
    
    /* Return cpuid data for requested cpuid level, as found in returned
       eax, ebx, ecx and edx registers.  The function checks if cpuid is
       supported and returns 1 for valid cpuid information or 0 for
       unsupported cpuid level.  All pointers are required to be non-null.  */
    int __get_cpuid (unsigned int __level,
        unsigned int *__eax, unsigned int *__ebx,
        unsigned int *__ecx, unsigned int *__edx)
    

    You don't need to, and should not, re-implement this functionality.