summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2011-01-24 11:03:42 +0000
committerRichard W.M. Jones <rjones@redhat.com>2011-01-24 11:03:42 +0000
commit300c5168ca007ed5fbd49189efbe66ae0dbd9ad1 (patch)
tree9b9b7a6cc09a3a8a7136be606ad98722c2b74d24
parent4216f66a14702bf1a430a70be1be46d27b8b67c9 (diff)
downloadvirt-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.c60
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;
}