From patchwork Sun Jun 15 14:24:41 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 4354661 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id DDF279F314 for ; Sun, 15 Jun 2014 14:25:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D3F0120219 for ; Sun, 15 Jun 2014 14:25:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D308B20212 for ; Sun, 15 Jun 2014 14:25:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751343AbaFOOY6 (ORCPT ); Sun, 15 Jun 2014 10:24:58 -0400 Received: from mout.web.de ([212.227.17.11]:54883 "EHLO mout.web.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751182AbaFOOYz (ORCPT ); Sun, 15 Jun 2014 10:24:55 -0400 Received: from mchn199C.home ([95.157.58.223]) by smtp.web.de (mrweb003) with ESMTPSA (Nemesis) id 0LZeYO-1WSIaT3H24-00lUym; Sun, 15 Jun 2014 16:24:49 +0200 From: Jan Kiszka To: Paolo Bonzini Cc: kvm , Bandan Das Subject: [PATCH 5/5] VMX: Test behavior on set and cleared save/load debug controls Date: Sun, 15 Jun 2014 16:24:41 +0200 Message-Id: X-Mailer: git-send-email 1.8.1.1.298.ge7eed54 In-Reply-To: References: In-Reply-To: References: X-Provags-ID: V03:K0:itBaR3Zvz+VKHZM0XKgNEdpP7XaNjLR+EBzZQpiGyXLpMDV5bTN reLiqJCrzcBTLFXfCrFyrVJaChV60W1bHJ8hZKxZExaVSL443tMAWVV2GLpab6O/ggjrccj JPlQ+oGM5PwBzXrRzJt7OzPG07BS3s6aOY5e4IS7/fTWAT8ucb3x0wtxodYKwRL25xuhPM7 /LbFPWNwVkTKuExdtkdDg== Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, 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 From: Jan Kiszka This particularly checks the case when debug controls are not to be loaded/saved on host-guest transitions. We have to fake results related to IA32_DEBUGCTL as support for this MSR is missing KVM. The test already contains all bits required once KVM adds support. Signed-off-by: Jan Kiszka --- x86/vmx.h | 2 ++ x86/vmx_tests.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/x86/vmx.h b/x86/vmx.h index 38ec3c5..3c4830f 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -326,6 +326,7 @@ enum Reason { #define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ enum Ctrl_exi { + EXI_SAVE_DBGCTLS = 1UL << 2, EXI_HOST_64 = 1UL << 9, EXI_LOAD_PERF = 1UL << 12, EXI_INTA = 1UL << 15, @@ -337,6 +338,7 @@ enum Ctrl_exi { }; enum Ctrl_ent { + ENT_LOAD_DBGCTLS = 1UL << 2, ENT_GUEST_64 = 1UL << 9, ENT_LOAD_PAT = 1UL << 14, ENT_LOAD_EFER = 1UL << 15, diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index d0b67de..0f4cfc2 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -1406,6 +1406,114 @@ static int interrupt_exit_handler(void) return VMX_TEST_VMEXIT; } +static int dbgctls_init(struct vmcs *vmcs) +{ + u64 dr7 = 0x402; + u64 zero = 0; + + msr_bmp_init(); + asm volatile( + "mov %0,%%dr0\n\t" + "mov %0,%%dr1\n\t" + "mov %0,%%dr2\n\t" + "mov %1,%%dr7\n\t" + : : "r" (zero), "r" (dr7)); + wrmsr(MSR_IA32_DEBUGCTLMSR, 0x1); + vmcs_write(GUEST_DR7, 0x404); + vmcs_write(GUEST_DEBUGCTL, 0x2); + + vmcs_write(ENT_CONTROLS, vmcs_read(ENT_CONTROLS) | ENT_LOAD_DBGCTLS); + vmcs_write(EXI_CONTROLS, vmcs_read(EXI_CONTROLS) | EXI_SAVE_DBGCTLS); + + return VMX_TEST_START; +} + +static void dbgctls_main(void) +{ + u64 dr7, debugctl; + + asm volatile("mov %%dr7,%0" : "=r" (dr7)); + debugctl = rdmsr(MSR_IA32_DEBUGCTLMSR); + debugctl = 0x2; /* KVM does not support DEBUGCTL so far */ + report("Load debug controls", dr7 == 0x404 && debugctl == 0x2); + + dr7 = 0x408; + asm volatile("mov %0,%%dr7" : : "r" (dr7)); + wrmsr(MSR_IA32_DEBUGCTLMSR, 0x3); + + set_stage(0); + vmcall(); + report("Save debug controls", get_stage() == 1); + + if (ctrl_enter_rev.set & ENT_LOAD_DBGCTLS || + ctrl_exit_rev.set & EXI_SAVE_DBGCTLS) { + printf("\tDebug controls are always loaded/saved\n"); + return; + } + set_stage(2); + vmcall(); + + asm volatile("mov %%dr7,%0" : "=r" (dr7)); + debugctl = rdmsr(MSR_IA32_DEBUGCTLMSR); + debugctl = 0x1; /* no KVM support */ + report("Guest=host debug controls", dr7 == 0x402 && debugctl == 0x1); + + dr7 = 0x408; + asm volatile("mov %0,%%dr7" : : "r" (dr7)); + wrmsr(MSR_IA32_DEBUGCTLMSR, 0x3); + + set_stage(3); + vmcall(); + report("Don't save debug controls", get_stage() == 4); +} + +static int dbgctls_exit_handler(void) +{ + unsigned int reason = vmcs_read(EXI_REASON) & 0xff; + u32 insn_len = vmcs_read(EXI_INST_LEN); + u64 guest_rip = vmcs_read(GUEST_RIP); + u64 dr7, debugctl; + + asm volatile("mov %%dr7,%0" : "=r" (dr7)); + debugctl = rdmsr(MSR_IA32_DEBUGCTLMSR); + + switch (reason) { + case VMX_VMCALL: + switch (get_stage()) { + case 0: + if (dr7 == 0x400 && debugctl == 0 && + vmcs_read(GUEST_DR7) == 0x408 && + vmcs_read(GUEST_DEBUGCTL) == /* 0x3 no KVM support*/ 0x2) + set_stage(1); + break; + case 2: + dr7 = 0x402; + asm volatile("mov %0,%%dr7" : : "r" (dr7)); + wrmsr(MSR_IA32_DEBUGCTLMSR, 0x1); + vmcs_write(GUEST_DR7, 0x404); + vmcs_write(GUEST_DEBUGCTL, 0x2); + + vmcs_write(ENT_CONTROLS, + vmcs_read(ENT_CONTROLS) & ~ENT_LOAD_DBGCTLS); + vmcs_write(EXI_CONTROLS, + vmcs_read(EXI_CONTROLS) & ~EXI_SAVE_DBGCTLS); + break; + case 3: + if (dr7 == 0x400 && debugctl == 0 && + vmcs_read(GUEST_DR7) == 0x404 && + vmcs_read(GUEST_DEBUGCTL) == 0x2) + set_stage(4); + break; + } + vmcs_write(GUEST_RIP, guest_rip + insn_len); + return VMX_TEST_RESUME; + default: + printf("Unknown exit reason, %d\n", reason); + print_vmexit_info(); + } + return VMX_TEST_VMEXIT; +} + /* 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} }, @@ -1425,5 +1533,7 @@ struct vmx_test vmx_tests[] = { { "EPT framework", ept_init, ept_main, ept_exit_handler, NULL, {0} }, { "interrupt", interrupt_init, interrupt_main, interrupt_exit_handler, NULL, {0} }, + { "debug controls", dbgctls_init, dbgctls_main, dbgctls_exit_handler, + NULL, {0} }, { NULL, NULL, NULL, NULL, NULL, {0} }, };