]> xenbits.xensource.com Git - people/royger/xen-test-framework.git/commitdiff
Utility for dumping the CPUID information visible to a guest
authorAndrew Cooper <andrew.cooper3@citrix.com>
Sun, 30 Aug 2015 21:43:17 +0000 (22:43 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Sun, 6 Mar 2016 19:42:33 +0000 (19:42 +0000)
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
build/common.mk
docs/all-tests.dox
include/arch/x86/lib.h
tests/cpuid/Makefile [new file with mode: 0644]
tests/cpuid/main.c [new file with mode: 0644]

index f9bf0c6a8382fe113d77776d911befd997a2f54d..a1d3eb8c38a1987667a043b46f396445ac58e2e3 100644 (file)
@@ -3,7 +3,7 @@ DESTDIR ?= $(ROOT)/dist
 PREFIX ?= $(ROOT)
 CC = gcc
 
-ALL_CATEGORIES     := special functional xsa
+ALL_CATEGORIES     := special functional xsa utility
 
 ALL_ENVIRONMENTS   := pv64 pv32pae hvm64 hvm32pae hvm32
 
index 149a46712c885684f623d3580399739b08c768ec..2f732632027a6dd73b528c2865f0e83d466e67bd 100644 (file)
@@ -23,4 +23,9 @@ Coveres XSA-106 and XSA-156.
 @section index-xsa XSA Proof-of-Concept tests
 
 @subpage test-xsa-167 - PV superpage sanity checks.
+
+
+@section index-utility Utilities
+
+@subpage test-cpuid - Print CPUID information.
 */
index 1bd016129806b5b9a89a3e6bd8e6a5a8a1b870e7..67af0ddc84d75e503b7cd56baa1577df2994ca99 100644 (file)
@@ -2,6 +2,7 @@
 #define XTF_X86_LIB_H
 
 #include <xtf/types.h>
+#include <xen/arch-x86/xen.h>
 
 static inline uint64_t rdmsr(uint32_t idx)
 {
@@ -28,6 +29,15 @@ static inline void cpuid(uint32_t leaf,
                   : "0" (leaf));
 }
 
+static inline void pv_cpuid(uint32_t leaf,
+                            uint32_t *eax, uint32_t *ebx,
+                            uint32_t *ecx, uint32_t *edx)
+{
+    asm volatile (_ASM_XEN_FEP "cpuid"
+                  : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
+                  : "0" (leaf));
+}
+
 static inline void cpuid_count(uint32_t leaf, uint32_t subleaf,
                                uint32_t *eax, uint32_t *ebx,
                                uint32_t *ecx, uint32_t *edx)
@@ -37,6 +47,15 @@ static inline void cpuid_count(uint32_t leaf, uint32_t subleaf,
                   : "0" (leaf), "2" (subleaf));
 }
 
+static inline void pv_cpuid_count(uint32_t leaf, uint32_t subleaf,
+                                  uint32_t *eax, uint32_t *ebx,
+                                  uint32_t *ecx, uint32_t *edx)
+{
+    asm volatile (_ASM_XEN_FEP "cpuid"
+                  : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
+                  : "0" (leaf), "2" (subleaf));
+}
+
 static inline uint8_t inb(uint16_t port)
 {
     uint8_t val;
diff --git a/tests/cpuid/Makefile b/tests/cpuid/Makefile
new file mode 100644 (file)
index 0000000..085af54
--- /dev/null
@@ -0,0 +1,11 @@
+ROOT := $(abspath $(CURDIR)/../..)
+
+include $(ROOT)/build/common.mk
+
+NAME      := cpuid
+CATEGORY  := utility
+TEST-ENVS := $(ALL_ENVIRONMENTS)
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/cpuid/main.c b/tests/cpuid/main.c
new file mode 100644 (file)
index 0000000..f89ad6c
--- /dev/null
@@ -0,0 +1,122 @@
+/**
+ * @file tests/cpuid/main.c
+ * @ref test-cpuid
+ *
+ * @page test-cpuid CPUID
+ *
+ * Prints all CPUID information visible to the guest.  PV guests dump both
+ * native and emulated CPUID.
+ *
+ * @sa tests/cpuid/main.c
+ */
+#include <xtf/lib.h>
+
+static void dump_leaves(
+    void (*cpuid_fn)(uint32_t leaf, uint32_t subleaf,
+                     uint32_t *eax, uint32_t *ebx,
+                     uint32_t *ecx, uint32_t *edx)
+    )
+{
+    uint32_t leaf = 0, subleaf = ~0U;
+
+    uint64_t valid_xstate_leaves = 0;
+    uint32_t max_leaf = 0, max_l7_subleaf = 0,
+        max_hv_leaf = 0, max_hv2_leaf = 0, max_extd_leaf = 0;
+
+    for ( ;; )
+    {
+        uint32_t eax, ebx, ecx, edx;
+
+        cpuid_fn(leaf, subleaf, &eax, &ebx, &ecx, &edx);
+
+        printk("  %08x:%08x -> %08x:%08x:%08x:%08x\n",
+               leaf, subleaf, eax, ebx, ecx, edx);
+
+        switch ( leaf )
+        {
+        case 0:
+            max_leaf = eax;
+            break;
+
+        case 0x4:
+            subleaf++;
+            if ( (eax & 0x1f) != 0 )
+                continue;
+            break;
+
+        case 0x7:
+            if ( subleaf == 0 )
+                max_l7_subleaf = eax;
+            subleaf++;
+            if ( subleaf <= max_l7_subleaf )
+                continue;
+            break;
+
+        case 0xd:
+            if ( subleaf == 0 )
+                valid_xstate_leaves = ((uint64_t)edx) << 32 | eax;
+            do
+            {
+                subleaf++;
+            } while ( (subleaf < 63) &&
+                      !(valid_xstate_leaves & (1ULL << subleaf)) );
+            if ( subleaf < 63 )
+                continue;
+            break;
+
+        case 0x40000000U:
+            max_hv_leaf = eax;
+            break;
+
+        case 0x40000100U:
+            max_hv2_leaf = eax;
+            break;
+
+        case 0x80000000U:
+            max_extd_leaf = eax;
+            break;
+        }
+
+        leaf++;
+        if ( (leaf > 0) && (leaf < 0x40000000U) && (leaf > max_leaf) )
+            leaf = 0x40000000U;
+
+        if ( (leaf > 0x40000000U) && (leaf < 0x40000100U) && (leaf > max_hv_leaf) )
+            leaf = 0x40000100U;
+
+        if ( (leaf > 0x40000100U) && (leaf < 0x80000000U) && (leaf > max_hv2_leaf) )
+            leaf = 0x80000000U;
+
+        if ( (leaf > 0x80000000U) && (leaf > max_extd_leaf) )
+            break;
+
+        subleaf = ~0;
+        if ( leaf == 4 || leaf == 7 || leaf == 0xd )
+            subleaf = 0;
+    }
+}
+
+void test_main(void)
+{
+    printk("Guest cpuid information\n");
+
+    printk("Native cpuid:\n");
+    dump_leaves(cpuid_count);
+
+#ifdef CONFIG_PV
+    printk("Emulated cpuid:\n");
+    dump_leaves(pv_cpuid_count);
+#endif
+
+    xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */