diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2011-01-24 11:03:42 +0000 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2011-01-24 11:03:42 +0000 |
commit | 300c5168ca007ed5fbd49189efbe66ae0dbd9ad1 (patch) | |
tree | 9b9b7a6cc09a3a8a7136be606ad98722c2b74d24 | |
parent | 4216f66a14702bf1a430a70be1be46d27b8b67c9 (diff) | |
download | virt-what-300c5168ca007ed5fbd49189efbe66ae0dbd9ad1.tar.gz virt-what-300c5168ca007ed5fbd49189efbe66ae0dbd9ad1.tar.xz virt-what-300c5168ca007ed5fbd49189efbe66ae0dbd9ad1.zip |
cpuid: Find other leaf entries (RHBZ#671510).
-rw-r--r-- | virt-what-cpuid-helper.c | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/virt-what-cpuid-helper.c b/virt-what-cpuid-helper.c index 3024c37..8b81be3 100644 --- a/virt-what-cpuid-helper.c +++ b/virt-what-cpuid-helper.c @@ -24,40 +24,60 @@ #include <string.h> #if defined(__i386__) || defined(__x86_64__) -void -cpu_sig (char *sig) + +static unsigned int +cpuid (unsigned int eax, char *sig) { - unsigned int eax = 0x40000000; - unsigned int *sig32 = (unsigned int *)sig; + unsigned int *sig32 = (unsigned int *) sig; + asm volatile ( "xor %%ebx, %%ebx; cpuid" : "=a" (eax), "=b" (sig32[0]), "=c" (sig32[1]), "=d" (sig32[2]) : "0" (eax)); sig[12] = 0; + + return eax; } -#else -void -cpu_sig (char *sig) -{ - /* nothing for other architectures */ -} -#endif -int -main() +static void +cpu_sig (void) { char sig[13]; + unsigned int base = 0x40000000, leaf = base; + unsigned int max_entries; memset (sig, 0, sizeof sig); - - cpu_sig (sig); - + max_entries = cpuid (leaf, sig); puts (sig); - /* Possible values: - * KVMKVMKVM KVM guest - * XenVMMXenVMM Xen HVM guest - * VMwareVMware VMware guest + + /* Most hypervisors only have information in leaf 0x40000000, but + * upstream Xen contains further leaf entries (in particular when + * used with Viridian [HyperV] extensions). CPUID is supposed to + * return the maximum leaf offset in %eax, so that's what we use, + * but only if it looks sensible. */ + if (max_entries > 3 && max_entries < 0x10000) { + for (leaf = base + 0x100; leaf <= base + max_entries; leaf += 0x100) { + memset (sig, 0, sizeof sig); + cpuid (leaf, sig); + puts (sig); + } + } +} + +#else /* !i386, !x86_64 */ + +static void +cpu_sig (void) +{ + /* nothing for other architectures */ +} +#endif + +int +main() +{ + cpu_sig (); return 0; } |