|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [XTF PATCH 04/16] vvmx: add C wrappers of vmxon/vmread/vmptrld
These C wrappers record the faults and VMfails in the execution of vmx
instructions vmxon, vmread and vmptrld. Further tests can use those
records to check if a VMX instruction is implemented correctly by Xen
in the nested VMX. Other VMX instructions will be added once their
test cases are added.
Signed-off-by: Haozhong Zhang <haozhong.zhang@xxxxxxxxx>
---
include/arch/x86/hvm/vmx/vmcs.h | 179 ++++++++++++++++++++++++++++++++++++++++
tests/vvmx/Makefile | 2 +-
tests/vvmx/util.c | 83 +++++++++++++++++++
tests/vvmx/util.h | 78 +++++++++++++++++
tests/vvmx/vmxon.c | 0
5 files changed, 341 insertions(+), 1 deletion(-)
create mode 100644 include/arch/x86/hvm/vmx/vmcs.h
create mode 100644 tests/vvmx/util.c
create mode 100644 tests/vvmx/util.h
create mode 100644 tests/vvmx/vmxon.c
diff --git a/include/arch/x86/hvm/vmx/vmcs.h b/include/arch/x86/hvm/vmx/vmcs.h
new file mode 100644
index 0000000..e1a6ef8
--- /dev/null
+++ b/include/arch/x86/hvm/vmx/vmcs.h
@@ -0,0 +1,179 @@
+#ifndef XTF_X86_HVM_VMX_VMCS_H
+#define XTF_X86_HVM_VMX_VMCS_H
+
+/* VMCS field encodings. */
+#define VMCS_HIGH(x) ((x) | 1)
+enum vmcs_field {
+ VIRTUAL_PROCESSOR_ID = 0x00000000,
+ POSTED_INTR_NOTIFICATION_VECTOR = 0x00000002,
+ EPTP_INDEX = 0x00000004,
+#define GUEST_SEG_SELECTOR(sel) (GUEST_ES_SELECTOR + (sel) * 2) /* ES ... GS */
+ GUEST_ES_SELECTOR = 0x00000800,
+ GUEST_CS_SELECTOR = 0x00000802,
+ GUEST_SS_SELECTOR = 0x00000804,
+ GUEST_DS_SELECTOR = 0x00000806,
+ GUEST_FS_SELECTOR = 0x00000808,
+ GUEST_GS_SELECTOR = 0x0000080a,
+ GUEST_LDTR_SELECTOR = 0x0000080c,
+ GUEST_TR_SELECTOR = 0x0000080e,
+ GUEST_INTR_STATUS = 0x00000810,
+ GUEST_PML_INDEX = 0x00000812,
+ HOST_ES_SELECTOR = 0x00000c00,
+ HOST_CS_SELECTOR = 0x00000c02,
+ HOST_SS_SELECTOR = 0x00000c04,
+ HOST_DS_SELECTOR = 0x00000c06,
+ HOST_FS_SELECTOR = 0x00000c08,
+ HOST_GS_SELECTOR = 0x00000c0a,
+ HOST_TR_SELECTOR = 0x00000c0c,
+ IO_BITMAP_A = 0x00002000,
+ IO_BITMAP_B = 0x00002002,
+ MSR_BITMAP = 0x00002004,
+ VM_EXIT_MSR_STORE_ADDR = 0x00002006,
+ VM_EXIT_MSR_LOAD_ADDR = 0x00002008,
+ VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,
+ PML_ADDRESS = 0x0000200e,
+ TSC_OFFSET = 0x00002010,
+ VIRTUAL_APIC_PAGE_ADDR = 0x00002012,
+ APIC_ACCESS_ADDR = 0x00002014,
+ PI_DESC_ADDR = 0x00002016,
+ VM_FUNCTION_CONTROL = 0x00002018,
+ EPT_POINTER = 0x0000201a,
+ EOI_EXIT_BITMAP0 = 0x0000201c,
+#define EOI_EXIT_BITMAP(n) (EOI_EXIT_BITMAP0 + (n) * 2) /* n = 0...3 */
+ EPTP_LIST_ADDR = 0x00002024,
+ VMREAD_BITMAP = 0x00002026,
+ VMWRITE_BITMAP = 0x00002028,
+ VIRT_EXCEPTION_INFO = 0x0000202a,
+ XSS_EXIT_BITMAP = 0x0000202c,
+ TSC_MULTIPLIER = 0x00002032,
+ GUEST_PHYSICAL_ADDRESS = 0x00002400,
+ VMCS_LINK_POINTER = 0x00002800,
+ GUEST_IA32_DEBUGCTL = 0x00002802,
+ GUEST_PAT = 0x00002804,
+ GUEST_EFER = 0x00002806,
+ GUEST_PERF_GLOBAL_CTRL = 0x00002808,
+ GUEST_PDPTE0 = 0x0000280a,
+#define GUEST_PDPTE(n) (GUEST_PDPTE0 + (n) * 2) /* n = 0...3 */
+ GUEST_BNDCFGS = 0x00002812,
+ HOST_PAT = 0x00002c00,
+ HOST_EFER = 0x00002c02,
+ HOST_PERF_GLOBAL_CTRL = 0x00002c04,
+ PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
+ CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
+ EXCEPTION_BITMAP = 0x00004004,
+ PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
+ PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
+ CR3_TARGET_COUNT = 0x0000400a,
+ VM_EXIT_CONTROLS = 0x0000400c,
+ VM_EXIT_MSR_STORE_COUNT = 0x0000400e,
+ VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
+ VM_ENTRY_CONTROLS = 0x00004012,
+ VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
+ VM_ENTRY_INTR_INFO = 0x00004016,
+ VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
+ VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
+ TPR_THRESHOLD = 0x0000401c,
+ SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
+ PLE_GAP = 0x00004020,
+ PLE_WINDOW = 0x00004022,
+ VM_INSTRUCTION_ERROR = 0x00004400,
+ VM_EXIT_REASON = 0x00004402,
+ VM_EXIT_INTR_INFO = 0x00004404,
+ VM_EXIT_INTR_ERROR_CODE = 0x00004406,
+ IDT_VECTORING_INFO = 0x00004408,
+ IDT_VECTORING_ERROR_CODE = 0x0000440a,
+ VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
+ VMX_INSTRUCTION_INFO = 0x0000440e,
+#define GUEST_SEG_LIMIT(sel) (GUEST_ES_LIMIT + (sel) * 2) /* ES ... GS */
+ GUEST_ES_LIMIT = 0x00004800,
+ GUEST_CS_LIMIT = 0x00004802,
+ GUEST_SS_LIMIT = 0x00004804,
+ GUEST_DS_LIMIT = 0x00004806,
+ GUEST_FS_LIMIT = 0x00004808,
+ GUEST_GS_LIMIT = 0x0000480a,
+ GUEST_LDTR_LIMIT = 0x0000480c,
+ GUEST_TR_LIMIT = 0x0000480e,
+ GUEST_GDTR_LIMIT = 0x00004810,
+ GUEST_IDTR_LIMIT = 0x00004812,
+#define GUEST_SEG_AR_BYTES(sel) (GUEST_ES_AR_BYTES + (sel) * 2) /* ES ... GS */
+ GUEST_ES_AR_BYTES = 0x00004814,
+ GUEST_CS_AR_BYTES = 0x00004816,
+ GUEST_SS_AR_BYTES = 0x00004818,
+ GUEST_DS_AR_BYTES = 0x0000481a,
+ GUEST_FS_AR_BYTES = 0x0000481c,
+ GUEST_GS_AR_BYTES = 0x0000481e,
+ GUEST_LDTR_AR_BYTES = 0x00004820,
+ GUEST_TR_AR_BYTES = 0x00004822,
+ GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
+ GUEST_ACTIVITY_STATE = 0x00004826,
+ GUEST_SMBASE = 0x00004828,
+ GUEST_SYSENTER_CS = 0x0000482a,
+ GUEST_PREEMPTION_TIMER = 0x0000482e,
+ HOST_SYSENTER_CS = 0x00004c00,
+ CR0_GUEST_HOST_MASK = 0x00006000,
+ CR4_GUEST_HOST_MASK = 0x00006002,
+ CR0_READ_SHADOW = 0x00006004,
+ CR4_READ_SHADOW = 0x00006006,
+ CR3_TARGET_VALUE0 = 0x00006008,
+#define CR3_TARGET_VALUE(n) (CR3_TARGET_VALUE0 + (n) * 2) /* n <
CR3_TARGET_COUNT */
+ EXIT_QUALIFICATION = 0x00006400,
+ GUEST_LINEAR_ADDRESS = 0x0000640a,
+ GUEST_CR0 = 0x00006800,
+ GUEST_CR3 = 0x00006802,
+ GUEST_CR4 = 0x00006804,
+#define GUEST_SEG_BASE(sel) (GUEST_ES_BASE + (sel) * 2) /* ES ... GS */
+ GUEST_ES_BASE = 0x00006806,
+ GUEST_CS_BASE = 0x00006808,
+ GUEST_SS_BASE = 0x0000680a,
+ GUEST_DS_BASE = 0x0000680c,
+ GUEST_FS_BASE = 0x0000680e,
+ GUEST_GS_BASE = 0x00006810,
+ GUEST_LDTR_BASE = 0x00006812,
+ GUEST_TR_BASE = 0x00006814,
+ GUEST_GDTR_BASE = 0x00006816,
+ GUEST_IDTR_BASE = 0x00006818,
+ GUEST_DR7 = 0x0000681a,
+ GUEST_RSP = 0x0000681c,
+ GUEST_RIP = 0x0000681e,
+ GUEST_RFLAGS = 0x00006820,
+ GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,
+ GUEST_SYSENTER_ESP = 0x00006824,
+ GUEST_SYSENTER_EIP = 0x00006826,
+ HOST_CR0 = 0x00006c00,
+ HOST_CR3 = 0x00006c02,
+ HOST_CR4 = 0x00006c04,
+ HOST_FS_BASE = 0x00006c06,
+ HOST_GS_BASE = 0x00006c08,
+ HOST_TR_BASE = 0x00006c0a,
+ HOST_GDTR_BASE = 0x00006c0c,
+ HOST_IDTR_BASE = 0x00006c0e,
+ HOST_SYSENTER_ESP = 0x00006c10,
+ HOST_SYSENTER_EIP = 0x00006c12,
+ HOST_RSP = 0x00006c14,
+ HOST_RIP = 0x00006c16,
+};
+
+/* VM Instruction error numbers */
+enum vmx_insn_errno
+{
+ VMX_INSN_VMCLEAR_INVALID_PHYADDR = 2,
+ VMX_INSN_VMLAUNCH_NONCLEAR_VMCS = 4,
+ VMX_INSN_VMRESUME_NONLAUNCHED_VMCS = 5,
+ VMX_INSN_INVALID_CONTROL_STATE = 7,
+ VMX_INSN_INVALID_HOST_STATE = 8,
+ VMX_INSN_VMPTRLD_INVALID_PHYADDR = 9,
+ VMX_INSN_UNSUPPORTED_VMCS_COMPONENT = 12,
+ VMX_INSN_VMXON_IN_VMX_ROOT = 15,
+};
+
+#endif /* XTF_X86_HVM_VMX_VMCS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/vvmx/Makefile b/tests/vvmx/Makefile
index 54769fa..24d3720 100644
--- a/tests/vvmx/Makefile
+++ b/tests/vvmx/Makefile
@@ -6,6 +6,6 @@ TEST-ENVS := hvm64
TEST-EXTRA-CFG := extra.cfg.in
-obj-perenv += main.o cpuid.o msr.o
+obj-perenv += main.o cpuid.o msr.o util.o
include $(ROOT)/build/gen.mk
diff --git a/tests/vvmx/util.c b/tests/vvmx/util.c
new file mode 100644
index 0000000..8cd35c5
--- /dev/null
+++ b/tests/vvmx/util.c
@@ -0,0 +1,83 @@
+#include <xtf.h>
+#include <arch/x86/hvm/vmx/vmcs.h>
+#include "util.h"
+
+#define VMPTRLD_OPCODE ".byte 0x0f,0xc7\n" /* reg/opcode: /6 */
+#define VMREAD_OPCODE ".byte 0x0f,0x78\n"
+#define VMXON_OPCODE ".byte 0xf3,0x0f,0xc7\n"
+
+#define MODRM_EAX_06 ".byte 0x30\n" /* [EAX], with reg/opcode: /6 */
+#define MODRM_EAX_ECX ".byte 0xc1\n" /* EAX, ECX */
+
+uint8_t vmxon(uint64_t paddr, exinfo_t *fault_info)
+{
+ exinfo_t fault = 0;
+ uint8_t valid = 0, invalid = 0;
+
+ asm volatile("1: "VMXON_OPCODE MODRM_EAX_06 "\n\t"
+ " setc %0; setz %1 \n\t"
+ "2: \n\t"
+ _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+ : "=q" (invalid), "=q" (valid), "+D" (fault)
+ : "a" (&paddr)
+ : "memory", "cc");
+
+ if ( fault && fault_info )
+ *fault_info = fault;
+
+ return (fault ? VMXERR_FAULT : 0) |
+ (valid ? VMXERR_VMFAIL_VALID : 0) |
+ (invalid ? VMXERR_VMFAIL_INVALID : 0);
+}
+
+uint8_t vmread(enum vmcs_field field, uint64_t *val, exinfo_t *fault_info)
+{
+ exinfo_t fault = 0;
+ uint8_t valid = 0, invalid = 0;
+
+ asm volatile("1: "VMREAD_OPCODE MODRM_EAX_ECX "\n\t"
+ " setc %0; setz %1 \n\t"
+ "2: \n\t"
+ _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+ : "=q" (invalid), "=q" (valid), "+D" (fault), "=c" (*val)
+ : "a" (field)
+ : "memory", "cc");
+
+ if ( fault && fault_info )
+ *fault_info = fault;
+
+ return (fault ? VMXERR_FAULT : 0) |
+ (valid ? VMXERR_VMFAIL_VALID : 0) |
+ (invalid ? VMXERR_VMFAIL_INVALID : 0);
+}
+
+uint8_t vmptrld(uint64_t paddr, exinfo_t *fault_info)
+{
+ exinfo_t fault = 0;
+ uint8_t valid = 0, invalid = 0;
+
+ asm volatile("1: "VMPTRLD_OPCODE MODRM_EAX_06 "\n\t"
+ " setc %0; setz %1 \n\t"
+ "2: \n\t"
+ _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+ : "=q" (invalid), "=q" (valid), "+D" (fault)
+ : "a" (&paddr)
+ : "memory", "cc");
+
+ if ( fault && fault_info )
+ *fault_info = fault;
+
+ return (fault ? VMXERR_FAULT : 0) |
+ (valid ? VMXERR_VMFAIL_VALID : 0) |
+ (invalid ? VMXERR_VMFAIL_INVALID : 0);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/vvmx/util.h b/tests/vvmx/util.h
new file mode 100644
index 0000000..57d3398
--- /dev/null
+++ b/tests/vvmx/util.h
@@ -0,0 +1,78 @@
+#ifndef XTF_TESTS_VVMX_UTIL_H
+#define XTF_TESTS_VVMX_UTIL_H
+
+#include <arch/x86/exinfo.h>
+#include <arch/x86/hvm/vmx/vmcs.h>
+
+/**
+ * Flags for errors during the execution of a VMX instruction.
+ *
+ * NB. Besides VMXERR_NOERR, other flags are not mutually exclusive,
+ * because we should not assume Xen implements the nested VMX
+ * instructions correctly.
+ */
+#define VMXERR_NOERR 0
+#define VMXERR_VMFAIL_VALID (1 << 0)
+#define VMXERR_VMFAIL_INVALID (1 << 1)
+#define VMXERR_FAULT (1 << 2)
+
+/**
+ * vmxon
+ *
+ * Parameters:
+ * @paddr: the physical address of the VMXON region
+ * @fault: return the information of fault encountered in the execution
+ *
+ * Return:
+ * VMXERR_ flags.
+ *
+ * If VMXERR_FAULT is present and @fault is not NULL, the fault
+ * information will be returned via @fault.
+ */
+uint8_t vmxon(uint64_t paddr, exinfo_t *fault);
+
+/**
+ * vmread
+ *
+ * Parameters:
+ * @field: the encoding of the VMCS field to read
+ * @value: return the value of the VMCS field if no error is encountered
+ * @fault: return the information of fault encountered in the execution
+ *
+ * Return:
+ * VMXERR_ flags.
+ *
+ * If VMXERR_FAULT is present and @fault is not NULL, the fault
+ * information will be returned via @fault.
+ *
+ * If VMXERR_NOERR is returned and @value is not NULL, the value of
+ * VMCS field @field will be returned via @value.
+ */
+uint8_t vmread(enum vmcs_field field, uint64_t *value, exinfo_t *fault);
+
+/**
+ * vmptrld
+ *
+ * Parameters:
+ * @paddr: the physical address of VMCS
+ * @fault: return the information of fault encountered in the execution
+ *
+ * Return:
+ * VMXERR_ flags.
+ *
+ * If VMXERR_FAULT is present and @fault is not NULL, the fault
+ * information will be returned via @fault.
+ */
+uint8_t vmptrld(uint64_t paddr, exinfo_t *fault);
+
+#endif /* XTF_TESTS_VVMX_UTIL_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/vvmx/vmxon.c b/tests/vvmx/vmxon.c
new file mode 100644
index 0000000..e69de29
--
2.10.1
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |