From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eugene Korenevsky Subject: [PATCH] kvm-unit-tests: VMX: Test MSR load/store feature Date: Sun, 14 Dec 2014 04:05:14 +0300 Message-ID: <20141214010514.GA17702@gnote> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: Paolo Bonzini , Jan Kiszka To: kvm@vger.kernel.org Return-path: Received: from mail-lb0-f170.google.com ([209.85.217.170]:54787 "EHLO mail-lb0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750755AbaLNBDn (ORCPT ); Sat, 13 Dec 2014 20:03:43 -0500 Received: by mail-lb0-f170.google.com with SMTP id 10so7677706lbg.15 for ; Sat, 13 Dec 2014 17:03:41 -0800 (PST) Content-Disposition: inline Sender: kvm-owner@vger.kernel.org List-ID: 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 --- 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