]> xenbits.xensource.com Git - people/andrewcoop/xen-test-framework.git/commitdiff
LBR/TSX VMentry failure test
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 12 Oct 2016 17:23:42 +0000 (18:23 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 25 Apr 2017 12:55:42 +0000 (13:55 +0100)
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/include/arch/msr-index.h
docs/all-tests.dox
tests/lbr-tsx-vmentry/Makefile [new file with mode: 0644]
tests/lbr-tsx-vmentry/main.c [new file with mode: 0644]

index 2e900797bf7a0f178e96060d124bfe5ba972ab17..72373c6ffb16064d67c6670ef5a0f9f56768f43e 100644 (file)
 #define _MSR_MISC_FEATURES_CPUID_FAULTING        0
 #define MSR_MISC_FEATURES_CPUID_FAULTING         (1ULL << _MSR_MISC_FEATURES_CPUID_FAULTING)
 
+#define MSR_DEBUGCTL                    0x000001d9
+#define _MSR_DEBUGCTL_LBR               0 /* Last Branch Record. */
+#define MSR_DEBUGCTL_LBR                (_AC(1, L) << _MSR_DEBUGCTL_LBR)
+
 #define MSR_EFER                        0xc0000080 /* Extended Feature register. */
 #define _EFER_SCE                       0  /* SYSCALL Enable. */
 #define EFER_SCE                        (_AC(1, L) << _EFER_SCE)
index b037bc650406bd6121085000272a247bc118e527..398ba2c56a4165cc993f124a48cc523c4c546831 100644 (file)
@@ -22,6 +22,8 @@ and functionality.
 
 @subpage test-invlpg - `invlpg` instruction behaviour.
 
+@subpage test-lbr-tsx-vmentry - Haswell and later LBR/TSX Vmentry failure test.
+
 @subpage test-livepatch-priv-check - Live Patch Privilege Check.
 
 @subpage test-pv-iopl - IOPL emulation for PV guests.
diff --git a/tests/lbr-tsx-vmentry/Makefile b/tests/lbr-tsx-vmentry/Makefile
new file mode 100644 (file)
index 0000000..208cec3
--- /dev/null
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := lbr-tsx-vmentry
+CATEGORY  := functional
+TEST-ENVS := hvm64
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/lbr-tsx-vmentry/main.c b/tests/lbr-tsx-vmentry/main.c
new file mode 100644 (file)
index 0000000..5353bb2
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * @file tests/lbr-tsx-vmentry/main.c
+ * @ref test-lbr-tsx-vmentry
+ *
+ * @page test-lbr-tsx-vmentry LBR/TSX VMentry failure
+ *
+ * MSR load and save lists are a VT-x capability whereby hardware logically
+ * performs a rdmsr() from the load list on VMentry, and a wrmsr() to the save
+ * list on VMexit.  This facility is used by Xen for a number of MSRs,
+ * including the LBR registers if the guest enables MSR_DEBUGCTL.LBR.
+ *
+ * On Haswell and later hardware, the LBR format includes two TSX bits (61 and
+ * 62) in the LBR entries.
+ *
+ * When TSX has been disabled (most usually via microcode), hardware writes
+ * LBR records into the MSR load/save area wit the TSX bits cleared.  However
+ * with TSX disabled, hardware expects the TSX bits to be part of the linear
+ * address in the record (i.e. properly sign extended).
+ *
+ * Therefore, when an LBR record is generated in the upper canonical region,
+ * the value written into the save record by VMexit is not tolerated by the
+ * VMentry logic, resulting in a vmentry failure, e.g:
+ *
+ * <pre>
+ *    (XEN) d1v0 vmentry failure (reason 0x80000022): MSR loading (entry 3)
+ *    (XEN)   msr 00000680 val 1fff800000102e60 (mbz 0)
+ * </pre>
+ *
+ * In the affected configuration, Xen must fix up the VMentry load list on
+ * every VMentry for the VM to continue to function.  This test sets up such a
+ * condition, and checks to see whether it keeps running to completion.
+ *
+ * @see tests/lbr-tsx-vmentry/main.c
+ */
+#include <xtf.h>
+
+#include <arch/msr-index.h>
+
+const char test_title[] = "LBR/TSX VMentry failure test";
+
+static void int3_stub(void)
+{
+    /* Force a LBR record to be generated. */
+    asm volatile ("jmp 1f; 1:");
+
+    /*
+     * After latching an LBR record, we need to force a subsequent vmentry.
+     * Using printk() is the easiest way.
+     */
+    printk("Latched a Last Branch Record in the upper canonical half\n");
+}
+
+void test_main(void)
+{
+    uint64_t dbgctl;
+
+    /* Alias everything in the upper canonical half. */
+    pae_l4_identmap[256] = pae_l4_identmap[0];
+    barrier();
+
+    /* Probe for, and enable Last Branch Record. */
+    if ( rdmsr_safe(MSR_DEBUGCTL, &dbgctl) )
+        return xtf_skip("Skip: MSR_DEBUGCTL not available\n");
+    else if ( wrmsr_safe(MSR_DEBUGCTL, dbgctl | MSR_DEBUGCTL_LBR) )
+        return xtf_skip("Skip: MSR_DEBUGCTL.LBR not available\n");
+
+    /* Construct a function pointer to int3_stub() via its upper alias. */
+    void (*int3_stub_alias)(void) =
+        _p((unsigned long)&int3_stub | 0xffff800000000000);
+
+    int3_stub_alias();
+
+    /*
+     * If XTF is alive at this point, the vmentry succeeded.  This will either
+     * be unaffected hardware, or Xen has all applicable workarounds.
+     */
+    xtf_success("Success: No LBR/TSX VMentry failure in this configuration\n");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */