How do I call "cpuid" in Linux?

19,105

Solution 1

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.

Solution 2

for (a =0; a < 5; ++a;)

There should only be two semicolons there. You've got three.

This is basic C/C++ syntax; the CPUID is a red herring.

Share:
19,105
TheBlueCat
Author by

TheBlueCat

printf("Hello, World!"); return 0;

Updated on July 21, 2022

Comments

  • TheBlueCat
    TheBlueCat almost 2 years

    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 code " << a << " gives " << b << std::endl;
      }
    
      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?

    Compiler errors:

    lewis@lewis-desktop:~/Desktop/prog$ g++ -Wall CPUInfo.cpp
    CPUInfo.cpp: In function ‘int main()’:
    CPUInfo.cpp:10:22: error: expected ‘)’ before ‘;’ token
    CPUInfo.cpp:10:23: error: expected primary-expression before ‘)’ token
    CPUInfo.cpp:10:23: error: expected ‘;’ before ‘)’ token
    CPUInfo.cpp:8:8: warning: unused variable ‘b’ [-Wunused-variable]
    CPUInfo.cpp:12:8: error: expected ‘}’ at end of input
    
  • TheBlueCat
    TheBlueCat over 11 years
    typo. I fixed it before I posted, for some reason it got back into there. I changed branches on Git, that's probably the reason. But yes, I do know this 'basic syntax'.
  • Mysticial
    Mysticial over 11 years
    +1 Didn't know that header existed. I've always done it with a bit of inline assembly.
  • Marbal
    Marbal over 11 years
    But the errors you posted are caused by this typo. If you've fixed that and are still having problems, please update the list of errors.
  • TheBlueCat
    TheBlueCat over 11 years
    Sure. I managed to get the piece to compile anyway. Notwithstanding, why should I not re-implement this? Besides time-saving?
  • David Heffernan
    David Heffernan over 11 years
    @Mysticial This is where my total ignorance of GCC and Linux comes in handy. I had to google for the answer!
  • David Heffernan
    David Heffernan over 11 years
    Basic rule of development is to re-use rather than re-implement. Do you write your own printf? Or your own strcmp? Do you write your own std::string?
  • Mysticial
    Mysticial over 11 years
    @DavidHeffernan Yet another reason why "ignorance" fuels new ideas... ahaha
  • UpAndAdam
    UpAndAdam about 10 years
    Can you provide / include an example usage? And potentially add the return types as well :-P
  • David Heffernan
    David Heffernan about 10 years
    @UpAndAdam Fair comment, esp. the return values. I've added these. I also included the comments from the header file that document how to call them. I don't have a suitable compiler at hand so don't want to try my hand at a usage example and get it wrong.
  • UpAndAdam
    UpAndAdam about 10 years
    No problem, much appreciated! I saw those comments as well in the header file and was hoping they made slightly more sense to someone else :-p I'll just have to keep on reading some more
  • David Heffernan
    David Heffernan about 10 years
    @UpAndAdam I think you need to read the Intel docs for CPUID to make sense of them.
  • UpAndAdam
    UpAndAdam about 10 years
    I have been trying to of course, there's just lots of it and each reads a little differently than the last :-P Thanks again for the help!
  • David Heffernan
    David Heffernan about 10 years
    There's only one official Intel doc.
  • itsnevertoobadtoaskforhelp
    itsnevertoobadtoaskforhelp over 7 years
    hello for level 1, eax=1 my ebx register keeps outputting random values, is there anyway I can check if for a level the register is relevant or not.
  • Peter Cordes
    Peter Cordes about 2 years
    @user9876: I fixed the question to remove the old error messages; the current code in the question compiles without any warnings. (godbolt.org/z/ezzTW7c1a). It's clunky and only produces the EAX output, but that's why it makes sense to ask for something better. Anyway, you can finally delete this answer now that it's fully irrelevant to the current question.