From patchwork Wed Jan 25 17:26:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Dyasli X-Patchwork-Id: 9537593 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 23D596046A for ; Wed, 25 Jan 2017 17:29:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 145272831C for ; Wed, 25 Jan 2017 17:29:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 073FB28334; Wed, 25 Jan 2017 17:29:57 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 69A822831C for ; Wed, 25 Jan 2017 17:29:56 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cWRLD-0006YS-So; Wed, 25 Jan 2017 17:26:39 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cWRLD-0006YH-DW for xen-devel@lists.xen.org; Wed, 25 Jan 2017 17:26:39 +0000 Received: from [193.109.254.147] by server-6.bemta-6.messagelabs.com id 10/36-15112-ECFD8885; Wed, 25 Jan 2017 17:26:38 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmphkeJIrShJLcpLzFFi42JxWrohUvfc/Y4 Ig1N3xCyWfFzM4sDocXT3b6YAxijWzLyk/IoE1ow9E3axFBxSq7jbK9TAuEm2i5GTQ0LAX2L5 0V2MIDabgJ7ExtmvmEBsEQFZidVdc9i7GLk4mAWOMEpMXXUEyOHgEBawkTi+IRGkhkVAVaLz7 Q6wXl4BD4muz7NYIWbKSdw818kMYnMKeEq0XpkKViMEVLNxzmIoW1Xi9YtdLBC9ghInZz4Bs5 kFJCQOvnjBPIGRdxaS1CwkqQWMTKsYNYpTi8pSi3SNDPSSijLTM0pyEzNzdA0NzPRyU4uLE9N TcxKTivWS83M3MQJDhwEIdjD+WhZwiFGSg0lJlPfUqY4IIb6k/JTKjMTijPii0pzU4kOMMhwc ShK8B+8B5QSLUtNTK9Iyc4BBDJOW4OBREuF9DZLmLS5IzC3OTIdInWJUlBLn7QFJCIAkMkrz4 NpgkXOJUVZKmJcR6BAhnoLUotzMElT5V4ziHIxKwrwXQKbwZOaVwE1/BbSYCWjxBeZ2kMUliQ gpqQZGxuPPAx7s3Bi71mdW1vJW+8vvbSZ+XzjZZmr02vv3LA0N0r/nOMd9XvrrmnbpI50b8/4 +unlNVOKiv2uRM9+lWT9uKG9trz/fLKAwW+bPH/Em2W2PXYLy7HNuz381X8qM/ea6oFO5KVa6 y8z4tzf+ls41nShwbEFC1pU29pPuh+sXShvUmf2RU2Ipzkg01GIuKk4EAA5sztOXAgAA X-Env-Sender: prvs=1919916e1=sergey.dyasli@citrix.com X-Msg-Ref: server-8.tower-27.messagelabs.com!1485365196!73447744!1 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.1.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 14647 invoked from network); 25 Jan 2017 17:26:38 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-8.tower-27.messagelabs.com with RC4-SHA encrypted SMTP; 25 Jan 2017 17:26:38 -0000 X-IronPort-AV: E=Sophos;i="5.33,284,1477958400"; d="scan'208";a="401954426" From: Sergey Dyasli To: Date: Wed, 25 Jan 2017 17:26:30 +0000 Message-ID: <1485365191-26692-2-git-send-email-sergey.dyasli@citrix.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1485365191-26692-1-git-send-email-sergey.dyasli@citrix.com> References: <1485365191-26692-1-git-send-email-sergey.dyasli@citrix.com> MIME-Version: 1.0 Cc: Andrew Cooper , Kevin Tian , Jan Beulich , Jun Nakajima , Sergey Dyasli Subject: [Xen-devel] [PATCH 1/2] x86/VMX: introduce vmx_find_guest_msr() X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Currently there can be up to 256 entries in a guest's MSR array and all entries are stored in the order they were added. Such design requires to perform a linear scan of the whole array in order to find the MSR with required index which can be a costly operation. To avoid that, reuse the existing code for heap sort and binary search and optimize existing functions which deal with guest's MSR arrays. This way the time complexity of searching for required MSR reduces from linear to logarithmic. Signed-off-by: Sergey Dyasli --- xen/arch/x86/hvm/vmx/vmcs.c | 80 +++++++++++++++++++++++++++++--------- xen/include/asm-x86/hvm/vmx/vmcs.h | 1 + 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 59ef199..d04de8d 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1283,19 +1284,36 @@ static int construct_vmcs(struct vcpu *v) return 0; } -int vmx_read_guest_msr(u32 msr, u64 *val) +static int vmx_msr_entry_key_cmp(const void *key, const void *elt) { - struct vcpu *curr = current; - unsigned int i, msr_count = curr->arch.hvm_vmx.msr_count; + const u32 *msr = key; + const struct vmx_msr_entry *entry = elt; + + if ( *msr > entry->index ) + return 1; + if ( *msr < entry->index ) + return -1; + return 0; +} + +struct vmx_msr_entry *vmx_find_guest_msr(const u32 msr) +{ + const struct vcpu *curr = current; + const unsigned int msr_count = curr->arch.hvm_vmx.msr_count; const struct vmx_msr_entry *msr_area = curr->arch.hvm_vmx.msr_area; - for ( i = 0; i < msr_count; i++ ) + return bsearch(&msr, msr_area, msr_count, sizeof(struct vmx_msr_entry), + vmx_msr_entry_key_cmp); +} + +int vmx_read_guest_msr(u32 msr, u64 *val) +{ + const struct vmx_msr_entry *ent; + + if ( (ent = vmx_find_guest_msr(msr)) != NULL ) { - if ( msr_area[i].index == msr ) - { - *val = msr_area[i].data; + *val = ent->data; return 0; - } } return -ESRCH; @@ -1303,22 +1321,37 @@ int vmx_read_guest_msr(u32 msr, u64 *val) int vmx_write_guest_msr(u32 msr, u64 val) { - struct vcpu *curr = current; - unsigned int i, msr_count = curr->arch.hvm_vmx.msr_count; - struct vmx_msr_entry *msr_area = curr->arch.hvm_vmx.msr_area; + struct vmx_msr_entry *ent; - for ( i = 0; i < msr_count; i++ ) + if ( (ent = vmx_find_guest_msr(msr)) != NULL ) { - if ( msr_area[i].index == msr ) - { - msr_area[i].data = val; + ent->data = val; return 0; - } } return -ESRCH; } +static void vmx_msr_entry_swap(void *a, void *b, int size) +{ + struct vmx_msr_entry *l = a, *r = b, tmp; + + tmp = *l; + *l = *r; + *r = tmp; +} + +static int vmx_msr_entry_cmp(const void *a, const void *b) +{ + const struct vmx_msr_entry *l = a, *r = b; + + if ( l->index > r->index ) + return 1; + if ( l->index < r->index ) + return -1; + return 0; +} + int vmx_add_msr(u32 msr, int type) { struct vcpu *curr = current; @@ -1351,9 +1384,17 @@ int vmx_add_msr(u32 msr, int type) __vmwrite(VM_EXIT_MSR_LOAD_ADDR, virt_to_maddr(*msr_area)); } - for ( idx = 0; idx < *msr_count; idx++ ) - if ( (*msr_area)[idx].index == msr ) + if ( type == VMX_GUEST_MSR ) + { + if ( vmx_find_guest_msr(msr) != NULL ) return 0; + } + else + { + for ( idx = 0; idx < *msr_count; idx++ ) + if ( (*msr_area)[idx].index == msr ) + return 0; + } if ( *msr_count == (PAGE_SIZE / sizeof(struct vmx_msr_entry)) ) return -ENOSPC; @@ -1369,6 +1410,9 @@ int vmx_add_msr(u32 msr, int type) msr_area_elem->data = 0; __vmwrite(VM_EXIT_MSR_STORE_COUNT, *msr_count); __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, *msr_count); + + sort(*msr_area, *msr_count, sizeof(struct vmx_msr_entry), + vmx_msr_entry_cmp, vmx_msr_entry_swap); } else { diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h index 6c3d7ba..d01099e 100644 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -589,6 +589,7 @@ enum vmx_insn_errno void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr, int type); void vmx_enable_intercept_for_msr(struct vcpu *v, u32 msr, int type); +struct vmx_msr_entry *vmx_find_guest_msr(const u32 msr); int vmx_read_guest_msr(u32 msr, u64 *val); int vmx_write_guest_msr(u32 msr, u64 val); int vmx_add_msr(u32 msr, int type);