Re: [PATCH v3] test: Add XSAVE unit test

2010-06-13 Thread Avi Kivity

On 06/11/2010 10:45 AM, Sheng Yang wrote:

Based on IDT test framework.

   


Nice and comprehensive.


+
+int main(void)
+{
+setup_idt();
+if (check_cpuid_1_ecx(CPUID_1_ECX_XSAVE)) {
+printf("CPU has XSAVE feature\n");
+test_xsave();
+} else {
+printf("CPU don't has XSAVE feature\n");
+test_no_xsave();
+}
+printf("Total test: %d\n", total_tests);
+if (fail_tests == 0)
+printf("ALL PASS!\n");
+else
+printf("Fail %d tests.\n", fail_tests);
+return 1;
+}
   


Need to return 0 if !fail_tests, so we can hook this up to autotest.


--
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3] test: Add XSAVE unit test

2010-06-11 Thread Sheng Yang
Based on IDT test framework.

Signed-off-by: Sheng Yang 
---
 kvm/test/config-x86-common.mak |2 +
 kvm/test/config-x86_64.mak |3 +-
 kvm/test/x86/xsave.c   |  260 
 3 files changed, 264 insertions(+), 1 deletions(-)
 create mode 100644 kvm/test/x86/xsave.c

diff --git a/kvm/test/config-x86-common.mak b/kvm/test/config-x86-common.mak
index 800b635..0e1ccce 100644
--- a/kvm/test/config-x86-common.mak
+++ b/kvm/test/config-x86-common.mak
@@ -61,6 +61,8 @@ $(TEST_DIR)/msr.flat: $(cstart.o) $(TEST_DIR)/msr.o
 
 $(TEST_DIR)/idt_test.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/idt_test.o
 
+$(TEST_DIR)/xsave.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/xsave.o
+
 arch_clean:
$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat \
$(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o
diff --git a/kvm/test/config-x86_64.mak b/kvm/test/config-x86_64.mak
index f9cd121..2da2906 100644
--- a/kvm/test/config-x86_64.mak
+++ b/kvm/test/config-x86_64.mak
@@ -5,6 +5,7 @@ ldarch = elf64-x86-64
 CFLAGS += -D__x86_64__
 
 tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
- $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat
+ $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
+ $(TEST_DIR)/xsave.flat
 
 include config-x86-common.mak
diff --git a/kvm/test/x86/xsave.c b/kvm/test/x86/xsave.c
new file mode 100644
index 000..30e3b31
--- /dev/null
+++ b/kvm/test/x86/xsave.c
@@ -0,0 +1,260 @@
+#include "libcflat.h"
+#include "idt.h"
+
+#ifdef __x86_64__
+#define uint64_t unsigned long
+#else
+#define uint64_t unsigned long long
+#endif
+
+static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
+unsigned int *ecx, unsigned int *edx)
+{
+/* ecx is often an input as well as an output. */
+asm volatile("cpuid"
+: "=a" (*eax),
+"=b" (*ebx),
+"=c" (*ecx),
+"=d" (*edx)
+: "0" (*eax), "2" (*ecx));
+}
+
+/*
+ * Generic CPUID function
+ * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+ * resulting in stale register contents being returned.
+ */
+void cpuid(unsigned int op,
+unsigned int *eax, unsigned int *ebx,
+unsigned int *ecx, unsigned int *edx)
+{
+*eax = op;
+*ecx = 0;
+__cpuid(eax, ebx, ecx, edx);
+}
+
+/* Some CPUID calls want 'count' to be placed in ecx */
+void cpuid_count(unsigned int op, int count,
+unsigned int *eax, unsigned int *ebx,
+unsigned int *ecx, unsigned int *edx)
+{
+*eax = op;
+*ecx = count;
+__cpuid(eax, ebx, ecx, edx);
+}
+
+int xgetbv_checking(u32 index, u64 *result)
+{
+u32 eax, edx;
+
+asm volatile(ASM_TRY("1f")
+".byte 0x0f,0x01,0xd0\n\t" /* xgetbv */
+"1:"
+: "=a" (eax), "=d" (edx)
+: "c" (index));
+*result = eax + ((u64)edx << 32);
+return exception_vector();
+}
+
+int xsetbv_checking(u32 index, u64 value)
+{
+u32 eax = value;
+u32 edx = value >> 32;
+
+asm volatile(ASM_TRY("1f")
+".byte 0x0f,0x01,0xd1\n\t" /* xsetbv */
+"1:"
+: : "a" (eax), "d" (edx), "c" (index));
+return exception_vector();
+}
+
+unsigned long read_cr4(void)
+{
+unsigned long val;
+asm volatile("mov %%cr4,%0" : "=r" (val));
+return val;
+}
+
+int write_cr4_checking(unsigned long val)
+{
+asm volatile(ASM_TRY("1f")
+"mov %0,%%cr4\n\t"
+"1:": : "r" (val));
+return exception_vector();
+}
+
+#define CPUID_1_ECX_XSAVE  (1 << 26)
+#define CPUID_1_ECX_OSXSAVE(1 << 27)
+int check_cpuid_1_ecx(unsigned int bit)
+{
+unsigned int eax, ebx, ecx, edx;
+cpuid(1, &eax, &ebx, &ecx, &edx);
+if (ecx & bit)
+return 1;
+return 0;
+}
+
+uint64_t get_supported_xcr0(void)
+{
+unsigned int eax, ebx, ecx, edx;
+cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
+printf("eax %x, ebx %x, ecx %x, edx %x\n",
+eax, ebx, ecx, edx);
+return eax + ((u64)edx << 32);
+}
+
+#define X86_CR4_OSXSAVE0x0004
+#define XCR_XFEATURE_ENABLED_MASK   0x
+#define XCR_XFEATURE_ILLEGAL_MASK   0x0010
+
+#define XSTATE_FP   0x1
+#define XSTATE_SSE  0x2
+#define XSTATE_YMM  0x4
+
+static int total_tests, fail_tests;
+
+void pass_if(int condition)
+{
+total_tests ++;
+if (condition)
+printf("Pass!\n");
+else {
+printf("Fail!\n");
+fail_tests ++;
+}
+}
+
+void test_xsave(void)
+{
+unsigned long cr4;
+uint64_t supported_xcr0;
+uint64_t test_bits;
+u64 xcr0;
+int r;
+
+printf("Legal instruction testing:\n");
+supported_xcr0 = get_supported_xcr0();
+printf("Supported XCR0 bits: 0x%x\n", supported_xcr0);
+
+printf("Check minimal XSAVE required bits: ");
+test_bits = XSTATE_FP | XSTATE_SSE;
+pass_if((supported_xcr0 & test_bits) == test_bits);
+
+printf("Set CR4 OSXSAVE: ");