#define XTF_X86_LIB_H
#include <xtf/types.h>
+#include <xen/arch-x86/xen.h>
static inline uint64_t rdmsr(uint32_t idx)
{
: "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)
: "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;
--- /dev/null
+/**
+ * @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:
+ */