]> xenbits.xensource.com Git - xtf.git/commitdiff
x86/msr: Introduce xtf_msr_consistency_test()
authorAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 9 Nov 2017 12:09:06 +0000 (12:09 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 28 Dec 2017 17:29:39 +0000 (17:29 +0000)
To help with testing the correctness of MSRs which may be passed directly
through to a guest.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/include/arch/msr.h
arch/x86/msr.c [new file with mode: 0644]
build/files.mk

index 3c58eafee5939d878c917c2344a4766acf9203d1..9fdc236baa332e23b31551947db028a9b5c33233 100644 (file)
@@ -107,6 +107,40 @@ typedef union msr_vmx_basic {
     };
 } msr_vmx_basic_t;
 
+/*
+ * Library logic for MSRs.
+ */
+struct xtf_msr_consistency_test_data
+{
+    uint32_t msr;
+
+    const struct xtf_msr_consistency_test_vals
+    {
+        uint64_t val;
+        bool pred;
+    } *vals;
+
+    size_t nr_vals;
+};
+
+/**
+ * Run consistency tests as described by @p t
+ *
+ * Some MSRs may be passed directly through to guests for performance reasons.
+ * This introduces an extra level of complexity for context switching an
+ * emulation purposes.
+ *
+ * To check that synchronisation is working properly, @p t describes an MSR
+ * and an array of predicated values.  For each value where the predicate is
+ * true, mix regular and forced reads and writes to check that values written
+ * via one mechanism become visible via the other.
+ *
+ * This logic is only applicable to read/write MSRs which expect to retain
+ * their written values on subsequent reads, and for values which will succeed
+ * when written.
+ */
+void xtf_msr_consistency_test(const struct xtf_msr_consistency_test_data *t);
+
 #endif /* XTF_X86_MSR_H */
 
 /*
diff --git a/arch/x86/msr.c b/arch/x86/msr.c
new file mode 100644 (file)
index 0000000..321fab2
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * @file arch/x86/msr.c
+ *
+ * Library logic for MSRs.
+ */
+#include <xtf/report.h>
+#include <xtf/test.h>
+
+#include <arch/msr.h>
+
+static uint64_t force_rdmsr(uint32_t idx)
+{
+    uint32_t lo, hi;
+
+    asm volatile (_ASM_XEN_FEP "rdmsr"
+                  : "=a" (lo), "=d" (hi)
+                  : "c" (idx));
+
+    return (((uint64_t)hi) << 32) | lo;
+}
+
+static void force_wrmsr(uint32_t idx, uint64_t val)
+{
+    asm volatile (_ASM_XEN_FEP "wrmsr":
+                  : "c" (idx), "a" ((uint32_t)val),
+                    "d" ((uint32_t)(val >> 32)));
+}
+
+void xtf_msr_consistency_test(const struct xtf_msr_consistency_test_data *t)
+{
+    size_t i;
+    uint64_t val;
+
+    for ( i = 0; i < t->nr_vals; ++i )
+    {
+        if ( !t->vals[i].pred )
+            continue;
+
+        wrmsr(t->msr, t->vals[i].val);
+        val = rdmsr(t->msr);
+
+        if ( val != t->vals[i].val )
+            xtf_failure("Fail: MSR %08x, real write, real read\n"
+                        "  Got %016"PRIx64", Expected %016"PRIx64"\n",
+                        t->msr, val, t->vals[i].val);
+
+        if ( !xtf_has_fep )
+            continue;
+
+        val = force_rdmsr(t->msr);
+
+        if ( val != t->vals[i].val )
+            xtf_failure("Fail: MSR %08x, real write, emul read\n"
+                        "  Got %016"PRIx64", Expected %016"PRIx64"\n",
+                        t->msr, val, t->vals[i].val);
+    }
+
+    if ( !xtf_has_fep )
+        return;
+
+    for ( i = 0; i < t->nr_vals; ++i )
+    {
+        if ( !t->vals[i].pred )
+            continue;
+
+        force_wrmsr(t->msr, t->vals[i].val);
+        val = rdmsr(t->msr);
+
+        if ( val != t->vals[i].val )
+            xtf_failure("Fail: MSR %08x, emul write, real read\n"
+                        "  Got %016"PRIx64", Expected %016"PRIx64"\n",
+                        t->msr, val, t->vals[i].val);
+
+        val = force_rdmsr(t->msr);
+
+        if ( val != t->vals[i].val )
+            xtf_failure("Fail: MSR %08x, emul write, emul read\n"
+                        "  Got %016"PRIx64", Expected %016"PRIx64"\n",
+                        t->msr, val, t->vals[i].val);
+    }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index f9bb3b4028a3f03d35773ec0792c4fb37e9eda1e..46b42d6bc086456cc11b6d3bed2274e201c2e47e 100644 (file)
@@ -22,6 +22,7 @@ obj-perenv += $(ROOT)/arch/x86/desc.o
 obj-perenv += $(ROOT)/arch/x86/extable.o
 obj-perenv += $(ROOT)/arch/x86/grant_table.o
 obj-perenv += $(ROOT)/arch/x86/hypercall_page.o
+obj-perenv += $(ROOT)/arch/x86/msr.o
 obj-perenv += $(ROOT)/arch/x86/setup.o
 obj-perenv += $(ROOT)/arch/x86/traps.o