Created
July 13, 2017 16:15
-
-
Save wen-long/5804ab9c1abc4e081344d7f35202b9ac to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#ifdef _WIN32 | |
/* MSVC, x86-only. Stupid compiler doesn't allow __asm on x86_64. */ | |
bool cpuid(unsigned *_eax, unsigned *_ebx, unsigned *_ecx, unsigned *_edx) | |
{ | |
#ifdef TARGET_CPU_X86 | |
static bool cpuid_support = FALSE; | |
if (!cpuid_support) { | |
unsigned pre_change, post_change; | |
const unsigned id_flag = 0x200000; | |
/* This is pretty much the standard way to detect whether the CPUID | |
* instruction is supported: try to change the ID bit in the EFLAGS | |
* register. If we can change it, then the CPUID instruction is | |
* implemented. */ | |
__asm { | |
mov edx, id_flag; | |
pushfd; /* Save %eflags to restore later. */ | |
pushfd; /* Push second copy, for manipulation. */ | |
pop ebx; /* Pop it into post_change. */ | |
mov eax, ebx; /* Save copy in pre_change. */ | |
xor ebx, edx; /* Tweak bit in post_change. */ | |
push ebx; /* Push tweaked copy... */ | |
popfd; /* ... and pop it into eflags. */ | |
pushfd; /* Did it change? Push new %eflags... */ | |
pop ebx; /* ... and pop it into post_change. */ | |
popfd; /* Restore original value. */ | |
mov pre_change, eax; | |
mov post_change, ebx; | |
} | |
if (((pre_change ^ post_change) & id_flag) == 0) | |
return FALSE; | |
else | |
cpuid_support = TRUE; | |
} | |
#endif | |
__asm { | |
mov esi, _eax; | |
mov edi, _ecx; | |
mov eax, DWORD PTR [esi]; | |
mov ecx, DWORD PTR [edi]; | |
cpuid; | |
mov DWORD PTR [esi], eax; | |
mov DWORD PTR [edi], ecx; | |
mov esi, _ebx; | |
mov edi, _edx; | |
mov DWORD PTR [esi], ebx; | |
mov DWORD PTR [edi], edx; | |
} | |
return true; | |
} | |
#else | |
bool cpuid(unsigned int *eax, unsigned int *ebx, | |
unsigned int *ecx, unsigned int *edx) | |
{ | |
asm volatile("cpuid" | |
: "=a" (*eax), | |
"=b" (*ebx), | |
"=c" (*ecx), | |
"=d" (*edx) | |
: "0" (*eax), "2" (*ecx)); | |
return true; | |
} | |
#endif | |
int main(int argc, char **argv) | |
{ | |
unsigned eax, ebx = 0, ecx = 0, edx = 0; | |
eax = 0x40000000; /* processor serial number */ | |
cpuid(&eax, &ebx, &ecx, &edx); | |
char buf[13] = {0}; | |
*(unsigned *)(&buf[0]) = ebx; | |
*(unsigned *)(&buf[4]) = ecx; | |
*(unsigned *)(&buf[8]) = edx; | |
printf("Hypervisor vendor string: %s\n", buf); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment