From patchwork Mon Jul 24 13:47:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Sergey Dyasli X-Patchwork-Id: 9859423 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 6C1FC60349 for ; Mon, 24 Jul 2017 13:50:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5C9D127CF9 for ; Mon, 24 Jul 2017 13:50:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 51B1827F97; Mon, 24 Jul 2017 13:50:32 +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 48B1C28409 for ; Mon, 24 Jul 2017 13:50:31 +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 1dZdiF-0001Qx-FP; Mon, 24 Jul 2017 13:47:55 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dZdiD-0001OT-Jg for xen-devel@lists.xen.org; Mon, 24 Jul 2017 13:47:53 +0000 Received: from [85.158.139.211] by server-1.bemta-5.messagelabs.com id BF/09-01993-98AF5795; Mon, 24 Jul 2017 13:47:53 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrCIsWRWlGSWpSXmKPExsXitHSDvW7Hr9J Ig9tnNC2WfFzM4sDocXT3b6YAxijWzLyk/IoE1oxL27+zFJzIqfi0rYG9gfFnQBcjJ4eEgL/E 3ubr7CA2m4CexMbZr5hAbBEBWYnVXXOA4lwczAJHGCWmrjoCViQsYCmxoe8rSxcjBweLgKrEj 7WRICavgI3Eh41hECPlJXa1XWQFsTkFbCUO31vODGILAZWsmrkOLM4rIChxcuYTFhCbWUBTon X7b3YIW16ieetsqHpVidcvdrFMYOSbhaRlFpKWWUhaFjAyr2LUKE4tKkst0jUy1ksqykzPKMl NzMzRNTQw1ctNLS5OTE/NSUwq1kvOz93ECAy1egYGxh2MO9r9DjFKcjApifJenlEaKcSXlJ9S mZFYnBFfVJqTWnyIUYODQ+DKubnTmaRY8vLzUpUkeH1+AtUJFqWmp1akZeYAowGmVIKDR0mEt xMkzVtckJhbnJkOkTrFqMvxasL/b0xCYDOkxHmrQYoEQIoySvPgRsAi8xKjrJQwLyMDA4MQT0 FqUW5mCar8K0ZxDkYlYd40kCk8mXklcJteAR3BBHTEnBlgR5QkIqSkGhgn7RDyl93rVms7T+R h138hl6a5P4Tlo3oiPM/fNAoLvKFjlXBKNbzuK+MaKZul3rVHXn62Vz3CUML0Y96Zzu0vuE46 Ffp7TjbjePdMuGub4gdvuc4/s48Yhh24zPcp//lxt/V3a1mV/SZ2NJfeFZB6wsNX3WcocPXpq R0HBQ6sm1I3PV8i/aMSS3FGoqEWc1FxIgAPHLvFxwIAAA== X-Env-Sender: prvs=3711c57a7=sergey.dyasli@citrix.com X-Msg-Ref: server-5.tower-206.messagelabs.com!1500904069!102629335!3 X-Originating-IP: [66.165.176.63] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.4.25; banners=-,-,- X-VirusChecked: Checked Received: (qmail 27876 invoked from network); 24 Jul 2017 13:47:52 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-5.tower-206.messagelabs.com with RC4-SHA encrypted SMTP; 24 Jul 2017 13:47:52 -0000 X-IronPort-AV: E=Sophos;i="5.40,407,1496102400"; d="scan'208";a="441052122" From: Sergey Dyasli To: Date: Mon, 24 Jul 2017 14:47:44 +0100 Message-ID: <20170724134745.4787-5-sergey.dyasli@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170724134745.4787-1-sergey.dyasli@citrix.com> References: <20170724134745.4787-1-sergey.dyasli@citrix.com> MIME-Version: 1.0 Cc: Andrew Cooper , Kevin Tian , Jan Beulich , Jun Nakajima , Sergey Dyasli Subject: [Xen-devel] [PATCH v2 4/5] x86/vvmx: add vvmx_max_msr_policy 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, when nested virt is enabled, the set of L1 VMX features is fixed and calculated by nvmx_msr_read_intercept() as an intersection between the full set of Xen's supported L1 VMX features, the set of actual H/W features and, for MSR_IA32_VMX_EPT_VPID_CAP, the set of features that Xen uses. Add vvmx_max_msr_policy object which represents the end result of nvmx_msr_read_intercept() on current H/W. Most of the code is moved from nvmx_msr_read_intercept() to calculate_vvmx_max_policy() which is called only once during the startup. There is no functional change to what L1 sees in VMX MSRs. Signed-off-by: Sergey Dyasli --- v1 --> v2: - Renamed hvm_max_vmx_msr_policy to vvmx_max_msr_policy and made it static - calculate_hvm_max_policy() is renamed to calculate_vvmx_max_policy() - Declaration of calculate_vvmx_max_policy() is removed from vmcs.c and added to vvmx.h - Removed comment "XXX: vmcs_revision_id for nested virt" - nvmx_msr_read_intercept() now uses const struct vmx_msr_policy * - Shortened "msr = *msr &" to "*msr &=" - Removed usage of "data" as an intermediate variable for 4 MSRs - Replaced magic constant for disabling MSR_IA32_VMX_VMFUNC with gen_vmx_msr_mask() - get_vmx_msr_ptr() and get_vmx_msr_val() helpers are used instead of accessing MSR array directly xen/arch/x86/hvm/vmx/vmcs.c | 1 + xen/arch/x86/hvm/vmx/vvmx.c | 284 +++++++++++++++++-------------------- xen/include/asm-x86/hvm/vmx/vvmx.h | 2 + 3 files changed, 134 insertions(+), 153 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index bd36b6e12a..67077cc41a 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -493,6 +493,7 @@ static int vmx_init_vmcs_config(void) vmx_virt_exception = !!(_vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS); vmx_display_features(); + calculate_vvmx_max_policy(); /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ if ( raw_vmx_msr_policy.basic.vmcs_region_size > PAGE_SIZE ) diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c index 2c8cf637a8..e71728f356 100644 --- a/xen/arch/x86/hvm/vmx/vvmx.c +++ b/xen/arch/x86/hvm/vmx/vvmx.c @@ -1941,6 +1941,8 @@ int nvmx_handle_invvpid(struct cpu_user_regs *regs) return X86EMUL_OKAY; } +static struct vmx_msr_policy __read_mostly vvmx_max_msr_policy; + #define __emul_value(enable1, default1) \ ((enable1 | default1) << 32 | (default1)) @@ -1948,6 +1950,128 @@ int nvmx_handle_invvpid(struct cpu_user_regs *regs) (((__emul_value(enable1, default1) & host_value) & (~0ul << 32)) | \ ((uint32_t)(__emul_value(enable1, default1) | host_value))) +void __init calculate_vvmx_max_policy(void) +{ + struct vmx_msr_policy *p = &vvmx_max_msr_policy; + uint64_t data, *msr; + u32 default1_bits; + + *p = raw_vmx_msr_policy; + + /* Pinbased controls 1-settings */ + data = PIN_BASED_EXT_INTR_MASK | + PIN_BASED_NMI_EXITING | + PIN_BASED_PREEMPT_TIMER; + + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_PINBASED_CTLS); + *msr = gen_vmx_msr(data, VMX_PINBASED_CTLS_DEFAULT1, *msr); + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_TRUE_PINBASED_CTLS); + *msr = gen_vmx_msr(data, VMX_PINBASED_CTLS_DEFAULT1, *msr); + + /* Procbased controls 1-settings */ + default1_bits = VMX_PROCBASED_CTLS_DEFAULT1; + data = CPU_BASED_HLT_EXITING | + CPU_BASED_VIRTUAL_INTR_PENDING | + CPU_BASED_CR8_LOAD_EXITING | + CPU_BASED_CR8_STORE_EXITING | + CPU_BASED_INVLPG_EXITING | + CPU_BASED_CR3_LOAD_EXITING | + CPU_BASED_CR3_STORE_EXITING | + CPU_BASED_MONITOR_EXITING | + CPU_BASED_MWAIT_EXITING | + CPU_BASED_MOV_DR_EXITING | + CPU_BASED_ACTIVATE_IO_BITMAP | + CPU_BASED_USE_TSC_OFFSETING | + CPU_BASED_UNCOND_IO_EXITING | + CPU_BASED_RDTSC_EXITING | + CPU_BASED_MONITOR_TRAP_FLAG | + CPU_BASED_VIRTUAL_NMI_PENDING | + CPU_BASED_ACTIVATE_MSR_BITMAP | + CPU_BASED_PAUSE_EXITING | + CPU_BASED_RDPMC_EXITING | + CPU_BASED_TPR_SHADOW | + CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; + + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_PROCBASED_CTLS); + *msr = gen_vmx_msr(data, default1_bits, *msr); + + default1_bits &= ~(CPU_BASED_CR3_LOAD_EXITING | + CPU_BASED_CR3_STORE_EXITING | + CPU_BASED_INVLPG_EXITING); + + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + *msr = gen_vmx_msr(data, default1_bits, *msr); + + /* Procbased-2 controls 1-settings */ + data = SECONDARY_EXEC_DESCRIPTOR_TABLE_EXITING | + SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | + SECONDARY_EXEC_ENABLE_VPID | + SECONDARY_EXEC_UNRESTRICTED_GUEST | + SECONDARY_EXEC_ENABLE_EPT; + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_PROCBASED_CTLS2); + *msr = gen_vmx_msr(data, 0, *msr); + + /* Vmexit controls 1-settings */ + data = VM_EXIT_ACK_INTR_ON_EXIT | + VM_EXIT_IA32E_MODE | + VM_EXIT_SAVE_PREEMPT_TIMER | + VM_EXIT_SAVE_GUEST_PAT | + VM_EXIT_LOAD_HOST_PAT | + VM_EXIT_SAVE_GUEST_EFER | + VM_EXIT_LOAD_HOST_EFER | + VM_EXIT_LOAD_PERF_GLOBAL_CTRL; + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_EXIT_CTLS); + *msr = gen_vmx_msr(data, VMX_EXIT_CTLS_DEFAULT1, *msr); + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_TRUE_EXIT_CTLS); + *msr = gen_vmx_msr(data, VMX_EXIT_CTLS_DEFAULT1, *msr); + + /* Vmentry controls 1-settings */ + data = VM_ENTRY_LOAD_GUEST_PAT | + VM_ENTRY_LOAD_GUEST_EFER | + VM_ENTRY_LOAD_PERF_GLOBAL_CTRL | + VM_ENTRY_IA32E_MODE; + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_ENTRY_CTLS); + *msr = gen_vmx_msr(data, VMX_ENTRY_CTLS_DEFAULT1, *msr); + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_TRUE_ENTRY_CTLS); + *msr = gen_vmx_msr(data, VMX_ENTRY_CTLS_DEFAULT1, *msr); + + /* MSR_IA32_VMX_VMCS_ENUM */ + /* The max index of VVMCS encoding is 0x1f. */ + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_VMCS_ENUM); + *msr = 0x1f << 1; + + /* MSR_IA32_VMX_CR0_FIXED0 */ + /* PG, PE bits must be 1 in VMX operation */ + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_CR0_FIXED0); + *msr = X86_CR0_PE | X86_CR0_PG; + + /* MSR_IA32_VMX_CR0_FIXED1 */ + /* allow 0-settings for all bits */ + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_CR0_FIXED1); + *msr = 0xffffffff; + + /* MSR_IA32_VMX_CR4_FIXED0 */ + /* VMXE bit must be 1 in VMX operation */ + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_CR4_FIXED0); + *msr = X86_CR4_VMXE; + + /* MSR_IA32_VMX_CR4_FIXED1 */ + /* Treated dynamically */ + + /* MSR_IA32_VMX_MISC */ + /* Do not support CR3-target feature now */ + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_MISC); + *msr &= ~VMX_MISC_CR3_TARGET; + + /* MSR_IA32_VMX_EPT_VPID_CAP */ + msr = get_vmx_msr_ptr(p, MSR_IA32_VMX_EPT_VPID_CAP); + *msr = nept_get_ept_vpid_cap(); + + /* MSR_IA32_VMX_VMFUNC is N/A */ + p->available &= ~gen_vmx_msr_mask(MSR_IA32_VMX_VMFUNC, + MSR_IA32_VMX_VMFUNC); +} + /* * Capability reporting */ @@ -1955,167 +2079,21 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 *msr_content) { struct vcpu *v = current; struct domain *d = v->domain; - u64 data = 0, host_data = 0; + const struct vmx_msr_policy *p = &vvmx_max_msr_policy; int r = 1; /* VMX capablity MSRs are available only when guest supports VMX. */ if ( !nestedhvm_enabled(d) || !d->arch.cpuid->basic.vmx ) return 0; - /* - * These MSRs are only available when flags in other MSRs are set. - * These prerequisites are listed in the Intel 64 and IA-32 - * Architectures Software Developer’s Manual, Vol 3, Appendix A. - */ - switch ( msr ) - { - case MSR_IA32_VMX_PROCBASED_CTLS2: - if ( !cpu_has_vmx_secondary_exec_control ) - return 0; - break; - - case MSR_IA32_VMX_EPT_VPID_CAP: - if ( !(cpu_has_vmx_ept || cpu_has_vmx_vpid) ) - return 0; - break; - - case MSR_IA32_VMX_TRUE_PINBASED_CTLS: - case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: - case MSR_IA32_VMX_TRUE_EXIT_CTLS: - case MSR_IA32_VMX_TRUE_ENTRY_CTLS: - if ( !(vmx_basic_msr & VMX_BASIC_DEFAULT1_ZERO) ) - return 0; - break; - - case MSR_IA32_VMX_VMFUNC: - if ( !cpu_has_vmx_vmfunc ) - return 0; - break; - } - - rdmsrl(msr, host_data); - - /* - * Remove unsupport features from n1 guest capability MSR - */ - switch (msr) { - case MSR_IA32_VMX_BASIC: - { - const struct vmcs_struct *vmcs = - map_domain_page(_mfn(PFN_DOWN(v->arch.hvm_vmx.vmcs_pa))); - - data = (host_data & (~0ul << 32)) | - (vmcs->vmcs_revision_id & 0x7fffffff); - unmap_domain_page(vmcs); - break; - } - case MSR_IA32_VMX_PINBASED_CTLS: - case MSR_IA32_VMX_TRUE_PINBASED_CTLS: - /* 1-settings */ - data = PIN_BASED_EXT_INTR_MASK | - PIN_BASED_NMI_EXITING | - PIN_BASED_PREEMPT_TIMER; - data = gen_vmx_msr(data, VMX_PINBASED_CTLS_DEFAULT1, host_data); - break; - case MSR_IA32_VMX_PROCBASED_CTLS: - case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: - { - u32 default1_bits = VMX_PROCBASED_CTLS_DEFAULT1; - /* 1-settings */ - data = CPU_BASED_HLT_EXITING | - CPU_BASED_VIRTUAL_INTR_PENDING | - CPU_BASED_CR8_LOAD_EXITING | - CPU_BASED_CR8_STORE_EXITING | - CPU_BASED_INVLPG_EXITING | - CPU_BASED_CR3_LOAD_EXITING | - CPU_BASED_CR3_STORE_EXITING | - CPU_BASED_MONITOR_EXITING | - CPU_BASED_MWAIT_EXITING | - CPU_BASED_MOV_DR_EXITING | - CPU_BASED_ACTIVATE_IO_BITMAP | - CPU_BASED_USE_TSC_OFFSETING | - CPU_BASED_UNCOND_IO_EXITING | - CPU_BASED_RDTSC_EXITING | - CPU_BASED_MONITOR_TRAP_FLAG | - CPU_BASED_VIRTUAL_NMI_PENDING | - CPU_BASED_ACTIVATE_MSR_BITMAP | - CPU_BASED_PAUSE_EXITING | - CPU_BASED_RDPMC_EXITING | - CPU_BASED_TPR_SHADOW | - CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; - - if ( msr == MSR_IA32_VMX_TRUE_PROCBASED_CTLS ) - default1_bits &= ~(CPU_BASED_CR3_LOAD_EXITING | - CPU_BASED_CR3_STORE_EXITING | - CPU_BASED_INVLPG_EXITING); - - data = gen_vmx_msr(data, default1_bits, host_data); - break; - } - case MSR_IA32_VMX_PROCBASED_CTLS2: - /* 1-settings */ - data = SECONDARY_EXEC_DESCRIPTOR_TABLE_EXITING | - SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | - SECONDARY_EXEC_ENABLE_VPID | - SECONDARY_EXEC_UNRESTRICTED_GUEST | - SECONDARY_EXEC_ENABLE_EPT; - data = gen_vmx_msr(data, 0, host_data); - break; - case MSR_IA32_VMX_EXIT_CTLS: - case MSR_IA32_VMX_TRUE_EXIT_CTLS: - /* 1-settings */ - data = VM_EXIT_ACK_INTR_ON_EXIT | - VM_EXIT_IA32E_MODE | - VM_EXIT_SAVE_PREEMPT_TIMER | - VM_EXIT_SAVE_GUEST_PAT | - VM_EXIT_LOAD_HOST_PAT | - VM_EXIT_SAVE_GUEST_EFER | - VM_EXIT_LOAD_HOST_EFER | - VM_EXIT_LOAD_PERF_GLOBAL_CTRL; - data = gen_vmx_msr(data, VMX_EXIT_CTLS_DEFAULT1, host_data); - break; - case MSR_IA32_VMX_ENTRY_CTLS: - case MSR_IA32_VMX_TRUE_ENTRY_CTLS: - /* 1-settings */ - data = VM_ENTRY_LOAD_GUEST_PAT | - VM_ENTRY_LOAD_GUEST_EFER | - VM_ENTRY_LOAD_PERF_GLOBAL_CTRL | - VM_ENTRY_IA32E_MODE; - data = gen_vmx_msr(data, VMX_ENTRY_CTLS_DEFAULT1, host_data); - break; + if ( !vmx_msr_available(p, msr) ) + return 0; - case MSR_IA32_VMX_VMCS_ENUM: - /* The max index of VVMCS encoding is 0x1f. */ - data = 0x1f << 1; - break; - case MSR_IA32_VMX_CR0_FIXED0: - /* PG, PE bits must be 1 in VMX operation */ - data = X86_CR0_PE | X86_CR0_PG; - break; - case MSR_IA32_VMX_CR0_FIXED1: - /* allow 0-settings for all bits */ - data = 0xffffffff; - break; - case MSR_IA32_VMX_CR4_FIXED0: - /* VMXE bit must be 1 in VMX operation */ - data = X86_CR4_VMXE; - break; - case MSR_IA32_VMX_CR4_FIXED1: - data = hvm_cr4_guest_valid_bits(v, 0); - break; - case MSR_IA32_VMX_MISC: - /* Do not support CR3-target feature now */ - data = host_data & ~VMX_MISC_CR3_TARGET; - break; - case MSR_IA32_VMX_EPT_VPID_CAP: - data = nept_get_ept_vpid_cap(); - break; - default: - r = 0; - break; - } + if ( msr == MSR_IA32_VMX_CR4_FIXED1 ) + *msr_content = hvm_cr4_guest_valid_bits(v, 0); + else + *msr_content = get_vmx_msr_val(p, msr); - *msr_content = data; return r; } diff --git a/xen/include/asm-x86/hvm/vmx/vvmx.h b/xen/include/asm-x86/hvm/vmx/vvmx.h index 3285b03bbb..150124f3a3 100644 --- a/xen/include/asm-x86/hvm/vmx/vvmx.h +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h @@ -244,5 +244,7 @@ int nept_translate_l2ga(struct vcpu *v, paddr_t l2ga, uint64_t *exit_qual, uint32_t *exit_reason); int nvmx_cpu_up_prepare(unsigned int cpu); void nvmx_cpu_dead(unsigned int cpu); + +void calculate_vvmx_max_policy(void); #endif /* __ASM_X86_HVM_VVMX_H__ */