From patchwork Wed Apr 4 14:40:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vitaly Kuznetsov X-Patchwork-Id: 10322645 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BC7F360390 for ; Wed, 4 Apr 2018 14:40:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AA34628CBA for ; Wed, 4 Apr 2018 14:40:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9E26928EC5; Wed, 4 Apr 2018 14:40:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2D8F628CBA for ; Wed, 4 Apr 2018 14:40:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751415AbeDDOkc (ORCPT ); Wed, 4 Apr 2018 10:40:32 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52934 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751443AbeDDOkQ (ORCPT ); Wed, 4 Apr 2018 10:40:16 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3F935EC017; Wed, 4 Apr 2018 14:40:16 +0000 (UTC) Received: from vitty.brq.redhat.com (unknown [10.43.2.155]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4095F2024CA2; Wed, 4 Apr 2018 14:40:14 +0000 (UTC) From: Vitaly Kuznetsov To: kvm@vger.kernel.org Cc: x86@kernel.org, Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Roman Kagan , "K. Y. Srinivasan" , Haiyang Zhang , Stephen Hemminger , "Michael Kelley (EOSG)" , Mohammed Gamal , Cathy Avery , linux-kernel@vger.kernel.org Subject: [PATCH RFC] KVM: x86: VMX: hyper-v: Enlightened MSR-Bitmap support Date: Wed, 4 Apr 2018 16:40:12 +0200 Message-Id: <20180404144012.15063-1-vkuznets@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Wed, 04 Apr 2018 14:40:16 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Wed, 04 Apr 2018 14:40:16 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'vkuznets@redhat.com' RCPT:'' Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Enlightened MSR-Bitmap is a natural extension of Enlightened VMCS: Hyper-V Top Level Functional Specification states: "The L1 hypervisor may collaborate with the L0 hypervisor to make MSR accesses more efficient. It can enable enlightened MSR bitmaps by setting the corresponding field in the enlightened VMCS to 1. When enabled, the L0 hypervisor does not monitor the MSR bitmaps for changes. Instead, the L1 hypervisor must invalidate the corresponding clean field after making changes to one of the MSR bitmaps." Signed-off-by: Vitaly Kuznetsov --- RFC part: while the implementation is simple and straightforward, I'm not observing any performance improvement with this patch. I tried both tight CPUID loop and tight loops reading different MSR (which we intercept in L1 and which we don't). The fluctuations in the results is too big (probably because there's no CPU pinning in Hyper-V and there's an always running Windows in parallel). I'd be very grateful for any insights or ideas how this can be tested. --- arch/x86/include/asm/hyperv-tlfs.h | 9 ++++++++- arch/x86/kvm/vmx.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 1c602ad4bda8..26e7e2240066 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -300,6 +300,9 @@ struct ms_hyperv_tsc_page { /* TSC emulation after migration */ #define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x40000106 +/* Nested features (CPUID 0x4000000A) EAX */ +#define HV_X64_NESTED_MSR_BITMAP BIT(19) + struct hv_reenlightenment_control { __u64 vector:8; __u64 reserved1:8; @@ -665,7 +668,11 @@ struct hv_enlightened_vmcs { u32 hv_clean_fields; u32 hv_padding_32; u32 hv_synthetic_controls; - u32 hv_enlightenments_control; + struct { + u32 nested_flush_hypercall:1; + u32 msr_bitmap:1; + u32 reserved:30; + } hv_enlightenments_control; u32 hv_vp_id; u64 hv_vm_id; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index b2f8a700aeef..73313a71dd1b 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1014,6 +1014,7 @@ static const u32 vmx_msr_index[] = { }; DEFINE_STATIC_KEY_FALSE(enable_evmcs); +DEFINE_STATIC_KEY_FALSE(enable_emsr_bitmap); #define current_evmcs ((struct hv_enlightened_vmcs *)this_cpu_read(current_vmcs)) @@ -1090,6 +1091,15 @@ static inline u16 evmcs_read16(unsigned long field) return *(u16 *)((char *)current_evmcs + offset); } +static inline void evmcs_touch_msr_bitmap(void) +{ + if (unlikely(!current_evmcs)) + return; + + current_evmcs->hv_clean_fields &= + ~HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP; +} + static void evmcs_load(u64 phys_addr) { struct hv_vp_assist_page *vp_ap = @@ -1174,6 +1184,7 @@ static inline u32 evmcs_read32(unsigned long field) { return 0; } static inline u16 evmcs_read16(unsigned long field) { return 0; } static inline void evmcs_load(u64 phys_addr) {} static inline void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) {} +static inline void evmcs_touch_msr_bitmap(void) {} #endif /* IS_ENABLED(CONFIG_HYPERV) */ static inline bool is_exception_n(u32 intr_info, u8 vector) @@ -4206,6 +4217,8 @@ static struct vmcs *alloc_vmcs(void) static int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs) { + struct hv_enlightened_vmcs *evmcs; + loaded_vmcs->vmcs = alloc_vmcs(); if (!loaded_vmcs->vmcs) return -ENOMEM; @@ -4218,6 +4231,11 @@ static int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs) if (!loaded_vmcs->msr_bitmap) goto out_vmcs; memset(loaded_vmcs->msr_bitmap, 0xff, PAGE_SIZE); + + if (static_branch_unlikely(&enable_emsr_bitmap)) { + evmcs = (struct hv_enlightened_vmcs *)loaded_vmcs->vmcs; + evmcs->hv_enlightenments_control.msr_bitmap = 1; + } } return 0; @@ -5335,6 +5353,9 @@ static void __always_inline vmx_disable_intercept_for_msr(unsigned long *msr_bit if (!cpu_has_vmx_msr_bitmap()) return; + if (static_branch_unlikely(&enable_emsr_bitmap)) + evmcs_touch_msr_bitmap(); + /* * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals * have the write-low and read-high bitmap offsets the wrong way round. @@ -5370,6 +5391,9 @@ static void __always_inline vmx_enable_intercept_for_msr(unsigned long *msr_bitm if (!cpu_has_vmx_msr_bitmap()) return; + if (static_branch_unlikely(&enable_emsr_bitmap)) + evmcs_touch_msr_bitmap(); + /* * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals * have the write-low and read-high bitmap offsets the wrong way round. @@ -12790,8 +12814,16 @@ static int __init vmx_init(void) } if (enlightened_vmcs) { - pr_info("KVM: vmx: using Hyper-V Enlightened VMCS\n"); static_branch_enable(&enable_evmcs); + + /* Nested MSR-Bitmap */ + if (ms_hyperv.nested_features & + HV_X64_NESTED_MSR_BITMAP) + static_branch_enable(&enable_emsr_bitmap); + + pr_info("KVM: vmx: using Hyper-V Enlightened VMCS %s\n", + !static_branch_likely(&enable_emsr_bitmap) ? "" + : "with MSR-Bitmap"); } } else { enlightened_vmcs = false;