*
* - 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)
--- /dev/null
+/**
+ * @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:
+ */
--- /dev/null
+/**
+ * @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:
+ */
--- /dev/null
+/**
+ * @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:
+ */
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)))
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;
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)
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
#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 */
--- /dev/null
+#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:
+ */