From patchwork Thu Aug 15 11:45:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arthur Chunqi Li X-Patchwork-Id: 2845123 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 409DDBF546 for ; Thu, 15 Aug 2013 11:45:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D427220207 for ; Thu, 15 Aug 2013 11:45:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 36746201C7 for ; Thu, 15 Aug 2013 11:45:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756661Ab3HOLp1 (ORCPT ); Thu, 15 Aug 2013 07:45:27 -0400 Received: from mail-pb0-f49.google.com ([209.85.160.49]:52117 "EHLO mail-pb0-f49.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755978Ab3HOLp0 (ORCPT ); Thu, 15 Aug 2013 07:45:26 -0400 Received: by mail-pb0-f49.google.com with SMTP id xb4so627608pbc.8 for ; Thu, 15 Aug 2013 04:45:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/BMQe7LcwadRUot4S56MJwfjMIzNJoAR4melbR0acvg=; b=q1to3fqyALp818fzNKSowRfjNoeooOWYIE+yYeQ+qLhTg8Kfg9Mxs6mpwWt22xpvBF 6HA9BeYIgmr/rEoNSffOnS0W0H/HD2YUCxkYgB3YmBo8XX4GIgJryiOET2pyLAPLNusc DS5/DMYSJvV17tEO48DV0zBoy48VAJoEPmX9BXv9rFtLEVaYtSuUQvy6/2+BmPPxcKsf Vzv2B/pUVQIo/F7sIsaWnvHJCGjn6dUTGhl7whIdyLtVtn3QvnLzb9JTIx/tKJVD9MSf /35Zk9L2jE4uvc3XAM2Q0y0SjqjJVXGTD0BWWpI3VhGa3Z/EGDxzJ8nViggDcDLsym+m wWow== X-Received: by 10.68.136.7 with SMTP id pw7mr14916438pbb.106.1376567125871; Thu, 15 Aug 2013 04:45:25 -0700 (PDT) Received: from Blade1-02.Blade1-02 ([162.105.146.101]) by mx.google.com with ESMTPSA id om2sm56378153pbb.34.2013.08.15.04.45.22 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 15 Aug 2013 04:45:24 -0700 (PDT) From: Arthur Chunqi Li To: kvm@vger.kernel.org Cc: jan.kiszka@web.de, gleb@redhat.com, pbonzini@redhat.com, Arthur Chunqi Li Subject: [PATCH v2 1/4] kvm-unit-tests: VMX: Add test cases for PAT and EFER Date: Thu, 15 Aug 2013 19:45:06 +0800 Message-Id: <1376567109-20834-2-git-send-email-yzt356@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1376567109-20834-1-git-send-email-yzt356@gmail.com> References: <1376567109-20834-1-git-send-email-yzt356@gmail.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add test cases for ENT_LOAD_PAT, ENT_LOAD_EFER, EXI_LOAD_PAT, EXI_SAVE_PAT, EXI_LOAD_EFER, EXI_SAVE_PAT flags in enter/exit control fields. Signed-off-by: Arthur Chunqi Li --- x86/vmx.h | 7 +++ x86/vmx_tests.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) diff --git a/x86/vmx.h b/x86/vmx.h index 28595d8..18961f1 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -152,10 +152,12 @@ enum Encoding { GUEST_DEBUGCTL = 0x2802ul, GUEST_DEBUGCTL_HI = 0x2803ul, GUEST_EFER = 0x2806ul, + GUEST_PAT = 0x2804ul, GUEST_PERF_GLOBAL_CTRL = 0x2808ul, GUEST_PDPTE = 0x280aul, /* 64-Bit Host State */ + HOST_PAT = 0x2c00ul, HOST_EFER = 0x2c02ul, HOST_PERF_GLOBAL_CTRL = 0x2c04ul, @@ -330,11 +332,15 @@ enum Ctrl_exi { EXI_HOST_64 = 1UL << 9, EXI_LOAD_PERF = 1UL << 12, EXI_INTA = 1UL << 15, + EXI_SAVE_PAT = 1UL << 18, + EXI_LOAD_PAT = 1UL << 19, + EXI_SAVE_EFER = 1UL << 20, EXI_LOAD_EFER = 1UL << 21, }; enum Ctrl_ent { ENT_GUEST_64 = 1UL << 9, + ENT_LOAD_PAT = 1UL << 14, ENT_LOAD_EFER = 1UL << 15, }; @@ -354,6 +360,7 @@ enum Ctrl0 { CPU_NMI_WINDOW = 1ul << 22, CPU_IO = 1ul << 24, CPU_IO_BITMAP = 1ul << 25, + CPU_MSR_BITMAP = 1ul << 28, CPU_SECONDARY = 1ul << 31, }; diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index c1b39f4..61b0cef 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -1,4 +1,15 @@ #include "vmx.h" +#include "msr.h" +#include "processor.h" +#include "vm.h" + +u64 ia32_pat; +u64 ia32_efer; + +static inline void vmcall() +{ + asm volatile("vmcall"); +} void basic_init() { @@ -76,6 +87,176 @@ int vmenter_exit_handler() return VMX_TEST_VMEXIT; } +void msr_bmp_init() +{ + void *msr_bitmap; + u32 ctrl_cpu0; + + msr_bitmap = alloc_page(); + memset(msr_bitmap, 0x0, PAGE_SIZE); + ctrl_cpu0 = vmcs_read(CPU_EXEC_CTRL0); + ctrl_cpu0 |= CPU_MSR_BITMAP; + vmcs_write(CPU_EXEC_CTRL0, ctrl_cpu0); + vmcs_write(MSR_BITMAP, (u64)msr_bitmap); +} + +static void test_ctrl_pat_init() +{ + u64 ctrl_ent; + u64 ctrl_exi; + + msr_bmp_init(); + ctrl_ent = vmcs_read(ENT_CONTROLS); + ctrl_exi = vmcs_read(EXI_CONTROLS); + vmcs_write(ENT_CONTROLS, ctrl_ent | ENT_LOAD_PAT); + vmcs_write(EXI_CONTROLS, ctrl_exi | (EXI_SAVE_PAT | EXI_LOAD_PAT)); + ia32_pat = rdmsr(MSR_IA32_CR_PAT); + vmcs_write(GUEST_PAT, 0x0); + vmcs_write(HOST_PAT, ia32_pat); +} + +static void test_ctrl_pat_main() +{ + u64 guest_ia32_pat; + + guest_ia32_pat = rdmsr(MSR_IA32_CR_PAT); + if (!(ctrl_enter_rev.clr & ENT_LOAD_PAT)) + printf("\tENT_LOAD_PAT is not supported.\n"); + else { + if (guest_ia32_pat != 0) { + report("Entry load PAT", 0); + return; + } + } + wrmsr(MSR_IA32_CR_PAT, 0x6); + vmcall(); + guest_ia32_pat = rdmsr(MSR_IA32_CR_PAT); + if (ctrl_enter_rev.clr & ENT_LOAD_PAT) { + if (guest_ia32_pat != ia32_pat) { + report("Entry load PAT", 0); + return; + } + report("Entry load PAT", 1); + } +} + +static int test_ctrl_pat_exit_handler() +{ + u64 guest_rip; + ulong reason; + u64 guest_pat; + + guest_rip = vmcs_read(GUEST_RIP); + reason = vmcs_read(EXI_REASON) & 0xff; + switch (reason) { + case VMX_VMCALL: + guest_pat = vmcs_read(GUEST_PAT); + if (!(ctrl_exit_rev.clr & EXI_SAVE_PAT)) { + printf("\tEXI_SAVE_PAT is not supported\n"); + vmcs_write(GUEST_PAT, 0x6); + } else { + if (guest_pat == 0x6) + report("Exit save PAT", 1); + else + report("Exit save PAT", 0); + } + if (!(ctrl_exit_rev.clr & EXI_LOAD_PAT)) + printf("\tEXI_LOAD_PAT is not supported\n"); + else { + if (rdmsr(MSR_IA32_CR_PAT) == ia32_pat) + report("Exit load PAT", 1); + else + report("Exit load PAT", 0); + } + vmcs_write(GUEST_PAT, ia32_pat); + vmcs_write(GUEST_RIP, guest_rip + 3); + return VMX_TEST_RESUME; + default: + printf("ERROR : Undefined exit reason, reason = %d.\n", reason); + break; + } + return VMX_TEST_VMEXIT; +} + +static void test_ctrl_efer_init() +{ + u64 ctrl_ent; + u64 ctrl_exi; + + msr_bmp_init(); + ctrl_ent = vmcs_read(ENT_CONTROLS) | ENT_LOAD_EFER; + ctrl_exi = vmcs_read(EXI_CONTROLS) | EXI_SAVE_EFER | EXI_LOAD_EFER; + vmcs_write(ENT_CONTROLS, ctrl_ent & ctrl_enter_rev.clr); + vmcs_write(EXI_CONTROLS, ctrl_exi & ctrl_exit_rev.clr); + ia32_efer = rdmsr(MSR_EFER); + vmcs_write(GUEST_EFER, ia32_efer ^ EFER_NX); + vmcs_write(HOST_EFER, ia32_efer ^ EFER_NX); +} + +static void test_ctrl_efer_main() +{ + u64 guest_ia32_efer; + + guest_ia32_efer = rdmsr(MSR_EFER); + if (!(ctrl_enter_rev.clr & ENT_LOAD_EFER)) + printf("\tENT_LOAD_EFER is not supported.\n"); + else { + if (guest_ia32_efer != (ia32_efer ^ EFER_NX)) { + report("Entry load EFER", 0); + return; + } + } + wrmsr(MSR_EFER, ia32_efer); + vmcall(); + guest_ia32_efer = rdmsr(MSR_EFER); + if (ctrl_enter_rev.clr & ENT_LOAD_EFER) { + if (guest_ia32_efer != ia32_efer) { + report("Entry load EFER", 0); + return; + } + report("Entry load EFER", 1); + } +} + +static int test_ctrl_efer_exit_handler() +{ + u64 guest_rip; + ulong reason; + u64 guest_efer; + + guest_rip = vmcs_read(GUEST_RIP); + reason = vmcs_read(EXI_REASON) & 0xff; + switch (reason) { + case VMX_VMCALL: + guest_efer = vmcs_read(GUEST_EFER); + if (!(ctrl_exit_rev.clr & EXI_SAVE_EFER)) { + printf("\tEXI_SAVE_EFER is not supported\n"); + vmcs_write(GUEST_EFER, ia32_efer); + } else { + if (guest_efer == ia32_efer) + report("Exit save EFER", 1); + else + report("Exit save EFER", 0); + } + if (!(ctrl_exit_rev.clr & EXI_LOAD_EFER)) { + printf("\tEXI_LOAD_EFER is not supported\n"); + wrmsr(MSR_EFER, ia32_efer ^ EFER_NX); + } else { + if (rdmsr(MSR_EFER) == (ia32_efer ^ EFER_NX)) + report("Exit load EFER", 1); + else + report("Exit load EFER", 0); + } + vmcs_write(GUEST_PAT, ia32_efer); + vmcs_write(GUEST_RIP, guest_rip + 3); + return VMX_TEST_RESUME; + default: + printf("ERROR : Undefined exit reason, reason = %d.\n", reason); + break; + } + 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[] = { @@ -83,5 +264,9 @@ struct vmx_test vmx_tests[] = { basic_syscall_handler, {0} }, { "vmenter", basic_init, vmenter_main, vmenter_exit_handler, basic_syscall_handler, {0} }, + { "control field PAT", test_ctrl_pat_init, test_ctrl_pat_main, + test_ctrl_pat_exit_handler, basic_syscall_handler, {0} }, + { "control field EFER", test_ctrl_efer_init, test_ctrl_efer_main, + test_ctrl_efer_exit_handler, basic_syscall_handler, {0} }, { NULL, NULL, NULL, NULL, NULL, {0} }, };