Reconstruct VMX codes and put all VMX test suites in x86/vmx_tests.c. Signed-off-by: Arthur Chunqi Li <yzt356@xxxxxxxxx> --- ChangeLog to v1: Reassign places of global variants. Move vmx_tests to vmx_tests.c. config-x86-common.mak | 2 +- x86/vmx.c | 108 ++++++++----------------------------------------- x86/vmx.h | 47 ++++++++++++++------- x86/vmx_tests.c | 88 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 107 deletions(-) create mode 100644 x86/vmx_tests.c diff --git a/config-x86-common.mak b/config-x86-common.mak index 34a41e1..bf88c67 100644 --- a/config-x86-common.mak +++ b/config-x86-common.mak @@ -101,7 +101,7 @@ $(TEST_DIR)/asyncpf.elf: $(cstart.o) $(TEST_DIR)/asyncpf.o $(TEST_DIR)/pcid.elf: $(cstart.o) $(TEST_DIR)/pcid.o -$(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o +$(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ diff --git a/x86/vmx.c b/x86/vmx.c index 082c3bb..92c259d 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -7,7 +7,7 @@ #include "smp.h" #include "io.h" -int fails = 0, tests = 0; +int fails, tests; u32 *vmxon_region; struct vmcs *vmcs_root; u32 vpid_cnt; @@ -17,9 +17,16 @@ ulong fix_cr0_set, fix_cr0_clr; ulong fix_cr4_set, fix_cr4_clr; struct regs regs; struct vmx_test *current; -u64 hypercall_field = 0; +u64 hypercall_field; bool launched; +union vmx_basic basic; +union vmx_ctrl_pin ctrl_pin_rev; +union vmx_ctrl_cpu ctrl_cpu_rev[2]; +union vmx_ctrl_exit ctrl_exit_rev; +union vmx_ctrl_ent ctrl_enter_rev; +union vmx_ept_vpid ept_vpid; + extern u64 gdt64_desc[]; extern u64 idt_descr[]; extern u64 tss_descr[]; @@ -27,7 +34,7 @@ extern void *vmx_return; extern void *entry_sysenter; extern void *guest_entry; -static void report(const char *name, int result) +void report(const char *name, int result) { ++tests; if (result) @@ -80,7 +87,7 @@ static inline int vmx_off() return ret; } -static void print_vmexit_info() +void print_vmexit_info() { u64 guest_rip, guest_rsp; ulong reason = vmcs_read(EXI_REASON) & 0xff; @@ -552,98 +559,16 @@ static int test_run(struct vmx_test *test) return 0; } -static void basic_init() -{ -} - -static void basic_guest_main() -{ - /* Here is null guest_main, print Hello World */ - printf("\tHello World, this is null_guest_main!\n"); -} - -static int basic_exit_handler() -{ - u64 guest_rip; - ulong reason; - - guest_rip = vmcs_read(GUEST_RIP); - reason = vmcs_read(EXI_REASON) & 0xff; - - switch (reason) { - case VMX_VMCALL: - print_vmexit_info(); - vmcs_write(GUEST_RIP, guest_rip + 3); - return VMX_TEST_RESUME; - default: - break; - } - printf("ERROR : Unhandled vmx exit.\n"); - print_vmexit_info(); - return VMX_TEST_EXIT; -} - -static void basic_syscall_handler(u64 syscall_no) -{ -} - -static void vmenter_main() -{ - u64 rax; - u64 rsp, resume_rsp; - - report("test vmlaunch", 1); - - asm volatile( - "mov %%rsp, %0\n\t" - "mov %3, %%rax\n\t" - "vmcall\n\t" - "mov %%rax, %1\n\t" - "mov %%rsp, %2\n\t" - : "=r"(rsp), "=r"(rax), "=r"(resume_rsp) - : "g"(0xABCD)); - report("test vmresume", (rax == 0xFFFF) && (rsp == resume_rsp)); -} - -static int vmenter_exit_handler() -{ - u64 guest_rip; - ulong reason; - - guest_rip = vmcs_read(GUEST_RIP); - reason = vmcs_read(EXI_REASON) & 0xff; - switch (reason) { - case VMX_VMCALL: - if (current->guest_regs.rax != 0xABCD) { - report("test vmresume", 0); - return VMX_TEST_VMEXIT; - } - current->guest_regs.rax = 0xFFFF; - vmcs_write(GUEST_RIP, guest_rip + 3); - return VMX_TEST_RESUME; - default: - report("test vmresume", 0); - print_vmexit_info(); - } - return VMX_TEST_VMEXIT; -} - - -/* name/init/guest_main/exit_handler/syscall_handler/guest_regs - basic_* just implement some basic functions */ -static struct vmx_test vmx_tests[] = { - { "null", basic_init, basic_guest_main, basic_exit_handler, - basic_syscall_handler, {0} }, - { "vmenter", basic_init, vmenter_main, vmenter_exit_handler, - basic_syscall_handler, {0} }, -}; +extern struct vmx_test vmx_tests[]; int main(void) { - int i; + int i = 0; setup_vm(); setup_idt(); + fails = tests = 0; + hypercall_field = 0; if (test_vmx_capability() != 0) { printf("ERROR : vmx not supported, check +vmx option\n"); @@ -664,10 +589,9 @@ int main(void) } test_vmxoff(); - for (i = 1; i < ARRAY_SIZE(vmx_tests); ++i) { + while (vmx_tests[++i].name != NULL) if (test_run(&vmx_tests[i])) goto exit; - } exit: printf("\nSUMMARY: %d tests, %d failures\n", tests, fails); diff --git a/x86/vmx.h b/x86/vmx.h index d80e000..c84942f 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -1,5 +1,5 @@ -#ifndef __HYPERVISOR_H -#define __HYPERVISOR_H +#ifndef __VMX_H +#define __VMX_H #include "libcflat.h" @@ -41,7 +41,7 @@ struct vmx_test { int exits; }; -static union vmx_basic { +union vmx_basic { u64 val; struct { u32 revision; @@ -53,37 +53,37 @@ static union vmx_basic { insouts:1, ctrl:1; }; -} basic; +}; -static union vmx_ctrl_pin { +union vmx_ctrl_pin { u64 val; struct { u32 set, clr; }; -} ctrl_pin_rev; +}; -static union vmx_ctrl_cpu { +union vmx_ctrl_cpu { u64 val; struct { u32 set, clr; }; -} ctrl_cpu_rev[2]; +}; -static union vmx_ctrl_exit { +union vmx_ctrl_exit { u64 val; struct { u32 set, clr; }; -} ctrl_exit_rev; +}; -static union vmx_ctrl_ent { +union vmx_ctrl_ent { u64 val; struct { u32 set, clr; }; -} ctrl_enter_rev; +}; -static union vmx_ept_vpid { +union vmx_ept_vpid { u64 val; struct { u32:16, @@ -93,7 +93,7 @@ static union vmx_ept_vpid { : 11; u32 invvpid:1; }; -} ept_vpid; +}; struct descr { u16 limit; @@ -432,6 +432,22 @@ enum Ctrl1 { #define HYPERCALL_MASK 0xFFF #define HYPERCALL_VMEXIT 0x1 + +extern u64 hypercall_field; +extern u32 vpid_cnt; +extern ulong fix_cr0_set, fix_cr0_clr; +extern ulong fix_cr4_set, fix_cr4_clr; +extern struct regs regs; +extern struct vmx_test *current; +extern bool launched; + +extern union vmx_basic basic; +extern union vmx_ctrl_pin ctrl_pin_rev; +extern union vmx_ctrl_cpu ctrl_cpu_rev[2]; +extern union vmx_ctrl_exit ctrl_exit_rev; +extern union vmx_ctrl_ent ctrl_enter_rev; +extern union vmx_ept_vpid ept_vpid; + static inline int vmcs_clear(struct vmcs *vmcs) { bool ret; @@ -462,5 +478,8 @@ static inline int vmcs_save(struct vmcs **vmcs) return ret; } +void report(const char *name, int result); +void print_vmexit_info(); + #endif diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c new file mode 100644 index 0000000..4761d95 --- /dev/null +++ b/x86/vmx_tests.c @@ -0,0 +1,88 @@ +#include "vmx.h" + +void basic_init() +{ +} + +void basic_guest_main() +{ + /* Here is a basic guest_main, print Hello World */ + printf("\tHello World, this is null_guest_main!\n"); +} + +int basic_exit_handler() +{ + u64 guest_rip; + ulong reason; + + guest_rip = vmcs_read(GUEST_RIP); + reason = vmcs_read(EXI_REASON) & 0xff; + + switch (reason) { + case VMX_VMCALL: + print_vmexit_info(); + vmcs_write(GUEST_RIP, guest_rip + 3); + return VMX_TEST_RESUME; + default: + break; + } + printf("ERROR : Unhandled vmx exit.\n"); + print_vmexit_info(); + return VMX_TEST_EXIT; +} + +void basic_syscall_handler(u64 syscall_no) +{ +} + +void vmenter_main() +{ + u64 rax; + u64 rsp, resume_rsp; + + report("test vmlaunch", 1); + + asm volatile( + "mov %%rsp, %0\n\t" + "mov %3, %%rax\n\t" + "vmcall\n\t" + "mov %%rax, %1\n\t" + "mov %%rsp, %2\n\t" + : "=r"(rsp), "=r"(rax), "=r"(resume_rsp) + : "g"(0xABCD)); + report("test vmresume", (rax == 0xFFFF) && (rsp == resume_rsp)); +} + +int vmenter_exit_handler() +{ + u64 guest_rip; + ulong reason; + + guest_rip = vmcs_read(GUEST_RIP); + reason = vmcs_read(EXI_REASON) & 0xff; + switch (reason) { + case VMX_VMCALL: + if (current->guest_regs.rax != 0xABCD) { + report("test vmresume", 0); + return VMX_TEST_VMEXIT; + } + current->guest_regs.rax = 0xFFFF; + vmcs_write(GUEST_RIP, guest_rip + 3); + return VMX_TEST_RESUME; + default: + report("test vmresume", 0); + print_vmexit_info(); + } + return VMX_TEST_VMEXIT; +} + +/* name/init/guest_main/exit_handler/syscall_handler/guest_regs + basic_* just implement some basic functions */ +struct vmx_test vmx_tests[] = { + { "null", basic_init, basic_guest_main, basic_exit_handler, + basic_syscall_handler, {0} }, + { "vmenter", basic_init, vmenter_main, vmenter_exit_handler, + basic_syscall_handler, {0} }, + { NULL, NULL, NULL, NULL, NULL, {0} }, +}; + -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html