Skip to content

Instantly share code, notes, and snippets.

@wen-long
Created July 13, 2017 16:15
Show Gist options
  • Save wen-long/5804ab9c1abc4e081344d7f35202b9ac to your computer and use it in GitHub Desktop.
Save wen-long/5804ab9c1abc4e081344d7f35202b9ac to your computer and use it in GitHub Desktop.
#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