]> xenbits.xensource.com Git - people/andrewcoop/xen-test-framework.git/commitdiff
Extend exinfo_t with test-available bits
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 28 Jun 2017 15:35:48 +0000 (15:35 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 30 Jun 2017 09:21:42 +0000 (10:21 +0100)
VT-x adds two extra logical errors from executing instructions.  Add two new
testa-avaialble bits into the generic infrastructure.

For the vvmx test, introduce XTF-wide helpers for the VMX Instruction Error
ABI, and test-specific helpers for VMX Instruction Error reporting via
extinfo_t, along with logic to decode the errors for printing.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/include/arch/exinfo.h
arch/x86/include/arch/vmx.h [new file with mode: 0644]
arch/x86/include/arch/x86-vmx.h [new file with mode: 0644]
arch/x86/vmx.c [new file with mode: 0644]
build/files.mk
common/libc/string.c
include/xtf/libc.h
tests/vvmx/Makefile
tests/vvmx/test.h
tests/vvmx/util.c [new file with mode: 0644]

index 0788cea4ac5e8507796916cc544b30bcf0f51678..71242aba9cbd665bb035323e2dd068ba752598de 100644 (file)
  *
  * - Bottom 16 bits are error code
  * - Next 8 bits are the entry vector
+ * - Next 2 bits are available for tests
  * - Top bit it set to disambiguate @#DE from no exception
  */
 typedef unsigned int exinfo_t;
 
 #define EXINFO_EXPECTED (1u << 31)
 
+#define EXINFO_AVAIL1   (1u << 25)
+#define EXINFO_AVAIL0   (1u << 24)
+
 #define EXINFO(vec, ec) (EXINFO_EXPECTED | ((vec & 0xff) << 16) | (ec & 0xffff))
 
 #define EXINFO_SYM(exc, ec) EXINFO(X86_EXC_ ## exc, ec)
diff --git a/arch/x86/include/arch/vmx.h b/arch/x86/include/arch/vmx.h
new file mode 100644 (file)
index 0000000..7004692
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * @file arch/x86/include/arch/vmx.h
+ *
+ * Helpers for VT-x.
+ */
+#ifndef XTF_X86_VMX_H
+#define XTF_X86_VMX_H
+
+#include <arch/x86-vmx.h>
+
+/**
+ * Error string for VMX Instruction Errors.
+ */
+const char *vmx_insn_err_strerror(unsigned int err);
+
+#endif /* XTF_X86_VMX_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/arch/x86/include/arch/x86-vmx.h b/arch/x86/include/arch/x86-vmx.h
new file mode 100644 (file)
index 0000000..6edefbf
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ * @file arch/x86/include/arch/x86-vmx.h
+ *
+ * VT-x hardware ABI, as specified in the Intel SDM.
+ */
+#ifndef XTF_X86_X86_VMX_H
+#define XTF_X86_X86_VMX_H
+
+/* VMX Instruction Error codes. */
+#define VMERR_VMCALL_IN_ROOT                         1
+#define VMERR_VMCLEAR_BAD_PADDR                      2
+#define VMERR_VMCLEAR_WITH_VMXON_PTR                 3
+#define VMERR_VMLAUNCH_NONCLEAR_VMCS                 4
+#define VMERR_VMRESUME_NONLAUNCHED_VMCS              5
+#define VMERR_VMRESUME_AFTER_VMXOFF                  6
+#define VMERR_INVALID_CONTROL_STATE                  7
+#define VMERR_INVALID_HOST_STATE                     8
+#define VMERR_VMPTRLD_BAD_PADDR                      9
+#define VMERR_VMPTRLD_WITH_VMXON_PTR                10
+#define VMERR_VMPTRLD_BAD_REVID                     11
+#define VMERR_UNSUPPORTED_VMCS_FIELD                12
+#define VMERR_VMWRITE_READONLY_FIELD                13
+/* 14 not specified. */
+#define VMERR_VMXON_IN_ROOT                         15
+#define VMERR_VMENTRY_BAD_EXECUTIVE                 16
+#define VMERR_VMENTRY_NONLAUNCHED_EXECUTIVE         17
+#define VMERR_VMENTRY_WITHOUT_VMXON_PTR             18
+#define VMERR_VMCALL_NONCLEAR_VMCS                  19
+#define VMERR_VMCALL_BAD_CONTROL_STATE              20
+/* 21 not specified. */
+#define VMERR_VMCALL_BAD_MSEG_REVID                 22
+#define VMERR_VMXOFF_UNDER_DUAL                     23
+#define VMERR_VMCALL_BAD_SMM_MONITOR                24
+#define VMERR_BAD_EXECUTIVE_STATE                   25
+#define VMERR_VMENTRY_MOVSS                         26
+/* 27 not specified. */
+#define VMERR_BAD_INV_OPERAND                       28
+
+#endif /* XTF_X86_X86_VMX_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/arch/x86/vmx.c b/arch/x86/vmx.c
new file mode 100644 (file)
index 0000000..b14f28a
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * @file arch/x86/vmx.c
+ *
+ * Helpers for VT-x.
+ */
+#include <xtf/lib.h>
+
+#include <arch/vmx.h>
+
+const char *vmx_insn_err_strerror(unsigned int err)
+{
+#define ERR(x) [VMERR_ ## x] = #x
+    const char *const strings[] = {
+        ERR(VMCALL_IN_ROOT),
+        ERR(VMCLEAR_BAD_PADDR),
+        ERR(VMCLEAR_WITH_VMXON_PTR),
+        ERR(VMLAUNCH_NONCLEAR_VMCS),
+        ERR(VMRESUME_NONLAUNCHED_VMCS),
+        ERR(VMRESUME_AFTER_VMXOFF),
+        ERR(INVALID_CONTROL_STATE),
+        ERR(INVALID_HOST_STATE),
+        ERR(VMPTRLD_BAD_PADDR),
+        ERR(VMPTRLD_WITH_VMXON_PTR),
+        ERR(VMPTRLD_BAD_REVID),
+        ERR(UNSUPPORTED_VMCS_FIELD),
+        ERR(VMWRITE_READONLY_FIELD),
+        ERR(VMXON_IN_ROOT),
+        ERR(VMENTRY_BAD_EXECUTIVE),
+        ERR(VMENTRY_NONLAUNCHED_EXECUTIVE),
+        ERR(VMENTRY_WITHOUT_VMXON_PTR),
+        ERR(VMCALL_NONCLEAR_VMCS),
+        ERR(VMCALL_BAD_CONTROL_STATE),
+        ERR(VMCALL_BAD_MSEG_REVID),
+        ERR(VMXOFF_UNDER_DUAL),
+        ERR(VMCALL_BAD_SMM_MONITOR),
+        ERR(BAD_EXECUTIVE_STATE),
+        ERR(VMENTRY_MOVSS),
+        ERR(BAD_INV_OPERAND),
+    };
+#undef ERR
+
+    if ( err < ARRAY_SIZE(strings) && strings[err] )
+        return strings[err];
+    else
+        return "<unknown>";
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index 3454aa38554f5f84a0b99e5ac397b4e86e57069d..8c50dd41e8462dfcbee32c02f56b3002a46926c6 100644 (file)
@@ -29,6 +29,7 @@ obj-hvm += $(ROOT)/arch/x86/hvm/pagetables.o
 obj-hvm += $(ROOT)/arch/x86/hvm/traps.o
 
 # Arguably common objects, but PV guests will have no interest in them.
+obj-hvm += $(ROOT)/arch/x86/vmx.o
 obj-hvm += $(ROOT)/arch/x86/x86-tss.o
 
 $(foreach env,$(HVM_ENVIRONMENTS),$(eval obj-$(env) += $(obj-hvm)))
index 5d972dd3f0607ca46f183dee70fa1614e32eb7ac..94acc7e576fd5cadb077e78a9d6de6a1b1653c57 100644 (file)
@@ -20,6 +20,30 @@ size_t strnlen(const char *str, size_t max)
     return s - str;
 }
 
+char *(strcpy)(char *dst, const char *src)
+{
+    char *p = dst;
+
+    while ( *p++ == *src++ )
+        ;
+
+    return dst;
+}
+
+char *(strncpy)(char *dst, const char *src, size_t n)
+{
+    char *p = dst;
+    size_t i;
+
+    for ( i = 0; i < n && src[i]; ++i )
+        p[i] = src[i];
+
+    for ( ; i < n; ++i )
+        p[i] = '\0';
+
+    return dst;
+}
+
 int (strcmp)(const char *_s1, const char *_s2)
 {
     char s1, s2;
index 18ec5f03b51ca49a3d39054bfc596f9f7fa16f42..18b1b4ac2cf4c809fad83d7abf1e51303da0d2ac 100644 (file)
 size_t strlen(const char *str);
 #define strlen(s)                   __builtin_strlen(s)
 
+char *strcpy(char *dst, const char *src);
+#define strcpy(d, s)                __builtin_strcpy(d, s)
+
+char *strncpy(char *dst, const char *src, size_t n);
+#define strncpy(d, s, n)            __builtin_strncpy(d, s, n)
+
 int strcmp(const char *s1, const char *s2);
 #define strcmp(s1, s2)              __builtin_strcmp(s1, s2)
 
index 82b895e900b78b7698f2d9cea029646c2ba7cd1a..8fe575fab1394b248f52fb72f84ea9bc8fc9d227 100644 (file)
@@ -6,6 +6,6 @@ TEST-ENVS := $(HVM_ENVIRONMENTS)
 
 TEST-EXTRA-CFG := extra.cfg.in
 
-obj-perenv += main.o msr.o
+obj-perenv += main.o msr.o util.o
 
 include $(ROOT)/build/gen.mk
index 2528df24e3145d3ec0c40507c72de3e95c54e68e..e5a1f831b755ea2c6eebf06f00c22ca81a69b340 100644 (file)
@@ -4,7 +4,26 @@
 #include <xtf.h>
 
 #include <arch/msr-index.h>
+#include <arch/vmx.h>
 
+/*
+ * Extentions on top of regular EXINFO.
+ *
+ * Use EXINFO_AVAIL{0,1} for VMFail{Invalid,Valid}.  (ab)use the fact that
+ * VMFailValid means no exception occured to stash the VMX Instruction Error
+ * code in the low bits, normally used for vector/error_code information.
+ */
+#define VMERR_SUCCESS      0
+#define VMERR_INVALID      (EXINFO_EXPECTED | EXINFO_AVAIL0)
+#define VMERR_VALID(x)     (EXINFO_EXPECTED | EXINFO_AVAIL1 | ((x) & 0xffff))
+
+/**
+ * Compare an expectation against what really happenend, printing
+ * human-readable information in case of a mismatch.
+ */
+void check(const char *func, exinfo_t got, exinfo_t exp);
+
+/* Test routines. */
 void test_msr_vmx(void);
 
 #endif /* VVMX_TEST_H */
diff --git a/tests/vvmx/util.c b/tests/vvmx/util.c
new file mode 100644 (file)
index 0000000..2a085c2
--- /dev/null
@@ -0,0 +1,63 @@
+#include "test.h"
+
+#include <arch/decode.h>
+
+static void decode_test_exinfo(char *str, size_t n, exinfo_t ex)
+{
+    if ( ex == VMERR_SUCCESS )
+    {
+        strcpy(str, "VMsucceed");
+        return;
+    }
+
+    if ( ex == VMERR_INVALID )
+    {
+        strcpy(str, "VMfailInvalid");
+        return;
+    }
+
+    unsigned int high = ex & ~0xffffff;
+
+    if ( high == VMERR_VALID(0) )
+    {
+        unsigned int low = ex & 0xffffff;
+
+        snprintf(str, n, "VMfailValid(%u) %s",
+                 low, vmx_insn_err_strerror(low));
+        return;
+    }
+
+    if ( high == EXINFO_EXPECTED )
+    {
+        x86_decode_exinfo(str, n, ex);
+        return;
+    }
+
+    strcpy(str, "<bad>");
+}
+
+void check(const char *func, exinfo_t got, exinfo_t exp)
+{
+    char gotstr[48], expstr[48];
+
+    if ( got == exp )
+        return;
+
+    decode_test_exinfo(gotstr, ARRAY_SIZE(gotstr), got);
+    decode_test_exinfo(expstr, ARRAY_SIZE(expstr), exp);
+
+    xtf_failure("Failure in %s()\n"
+                "  Expected 0x%08x: %s\n"
+                "       Got 0x%08x: %s\n",
+                func, exp, expstr, got, gotstr);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */