cpuid: Find other leaf entries (RHBZ#671510).
authorRichard W.M. Jones <rjones@redhat.com>
Mon, 24 Jan 2011 11:03:42 +0000 (11:03 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Mon, 24 Jan 2011 11:03:42 +0000 (11:03 +0000)
virt-what-cpuid-helper.c

index 3024c37..8b81be3 100644 (file)
 #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;
 }