This checks some usage cases of VMX MSR load/store feature: 1) VM-entry MSR-load area is correctly filled 2) VM-exit MSR-store area is correctly filled 3) VM-exit MSR-load area is correctly filled 4) Attempt to load MSR_FS_BASE on VM entry (must generate VM-entry failure due to MSR loading) Signed-off-by: Eugene Korenevsky <ekorenevsky@xxxxxxxxx> --- x86/vmx_tests.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 184fafc..913904a 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -1525,6 +1525,80 @@ static int dbgctls_exit_handler(void) return VMX_TEST_VMEXIT; } +struct vmx_msr_entry { + u32 index; + u32 reserved; + u64 value; +} __attribute__((packed)); + +#define MSR_MAGIC 0x31415926 +struct vmx_msr_entry *exit_msr_store, *entry_msr_load, *exit_msr_load; + +static int msr_switch_init(struct vmcs *vmcs) +{ + msr_bmp_init(); + exit_msr_store = alloc_page(); + exit_msr_load = alloc_page(); + entry_msr_load = alloc_page(); + memset(exit_msr_store, 0, PAGE_SIZE); + memset(exit_msr_load, 0, PAGE_SIZE); + memset(entry_msr_load, 0, PAGE_SIZE); + entry_msr_load[0].index = MSR_KERNEL_GS_BASE; + entry_msr_load[0].value = MSR_MAGIC; + + vmx_set_test_stage(1); + vmcs_write(ENT_MSR_LD_CNT, 1); + vmcs_write(ENTER_MSR_LD_ADDR, (u64)entry_msr_load); + vmcs_write(EXI_MSR_ST_CNT, 1); + vmcs_write(EXIT_MSR_ST_ADDR, (u64)exit_msr_store); + vmcs_write(EXI_MSR_LD_CNT, 1); + vmcs_write(EXIT_MSR_LD_ADDR, (u64)exit_msr_load); + return VMX_TEST_START; +} + +static void msr_switch_main() +{ + if (vmx_get_test_stage() == 1) { + report("VM entry MSR load", + rdmsr(MSR_KERNEL_GS_BASE) == MSR_MAGIC); + vmx_set_test_stage(2); + wrmsr(MSR_KERNEL_GS_BASE, MSR_MAGIC + 1); + exit_msr_store[0].index = MSR_KERNEL_GS_BASE; + exit_msr_load[0].index = MSR_KERNEL_GS_BASE; + exit_msr_load[0].value = MSR_MAGIC + 2; + } + vmcall(); +} + +static int msr_switch_exit_handler() +{ + ulong reason; + + reason = vmcs_read(EXI_REASON); + switch (reason) { + case 0x80000000 | VMX_FAIL_MSR: + if (vmx_get_test_stage() == 3) { + report("VM entry MSR load: try to load FS_BASE", + vmcs_read(EXI_QUALIFICATION) == 1); + return VMX_TEST_VMEXIT; + } + break; + case VMX_VMCALL: + if (vmx_get_test_stage() == 2) { + report("VM exit MSR store", + exit_msr_store[0].value == MSR_MAGIC + 1); + report("VM exit MSR load", + rdmsr(MSR_KERNEL_GS_BASE) == MSR_MAGIC + 2); + vmx_set_test_stage(3); + entry_msr_load[0].index = MSR_FS_BASE; + return VMX_TEST_RESUME; + } + } + printf("ERROR %s: unexpected stage=%u or reason=%lu\n", + __func__, vmx_get_test_stage(), reason); + return VMX_TEST_EXIT; +} + /* name/init/guest_main/exit_handler/syscall_handler/guest_regs */ struct vmx_test vmx_tests[] = { { "null", NULL, basic_guest_main, basic_exit_handler, NULL, {0} }, @@ -1546,5 +1620,7 @@ struct vmx_test vmx_tests[] = { interrupt_exit_handler, NULL, {0} }, { "debug controls", dbgctls_init, dbgctls_main, dbgctls_exit_handler, NULL, {0} }, + { "MSR switch", msr_switch_init, msr_switch_main, + msr_switch_exit_handler, NULL, {0} }, { NULL, NULL, NULL, NULL, NULL, {0} }, }; -- 2.0.4 -- 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