Received: by 10.223.176.5 with SMTP id f5csp2036689wra; Sun, 28 Jan 2018 11:31:28 -0800 (PST) X-Google-Smtp-Source: AH8x226/03/NScSxBbKcjqwSSf/z6HWZ20b1c3jKsKpPGyPCO+JgKPgdERQLyY4sHt2vZv2l8gHA X-Received: by 2002:a17:902:7e0e:: with SMTP id b14-v6mr3720719plm.97.1517167888681; Sun, 28 Jan 2018 11:31:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517167888; cv=none; d=google.com; s=arc-20160816; b=d3G/OQwAE/RXmlCsO3rN5PVOkZIgxcXJSQYm5CJ9n+BeAFRPUtztO5amuP5Y4evEEi JmQgpgYtGJPeE9Q/KhFHJKpSzkGgO7cZNl1x9BwL/YPUxWdaWX8VChLM+TQKQ5+X9Sqw QX+tq10V7xI1LBNVgEw+MVDxseD5DpCfti3EWr5gN+65asspm/V4+btZQEicAfp9x+La D/MQInzQZgRychLULrvY1a8RLMhFTBtB77bGUscjMOoVibbuxI9TTWafa3KzbSUCs5Ub iIABoFst3ltJuPM++Vs+1MVU20UTQx7bXak0ndrxZHiIu2EW53K8MxhTfb3fOXb7eD9q myCQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=eh8XKcebiqc92v9xhLNon5n3JNlGAJj+tqwgb233u1Q=; b=CEMAaq8ILbyU08GwkMG9omLdh7IaObVz5t9N+uLSZFa1xHtDNfE6vaEfZLx7PPZMUl 5eXdsT7UUHehYMeGKQXYnfiL2JLDRBXXXnJOu1+FnthxpDLaVyUIQkMwrhtXdQAqA11q OfSViNy9bPdMblMM78tnkIvXsdL88spfZGp/XtQz+IsWwgnIX21Lxqfrf14FwrRaENyd UVvl3x1EpCoAFC804dmLNu4FOecETTEJYuG+gdbjnUCi3tsEDIfbHxBZT8tIrOPuCLKS Q/2iOBqxRSW6dtrAAFb6FsytVJFzBIPs5IBQu2lg3MfqN+GEJOtpISXRotJzpGR/xECr eXUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amazon.de header.s=amazon201209 header.b=g6eAJq6N; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.de Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z5si6109496pgz.803.2018.01.28.11.31.14; Sun, 28 Jan 2018 11:31:28 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@amazon.de header.s=amazon201209 header.b=g6eAJq6N; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752453AbeA1T3u (ORCPT + 99 others); Sun, 28 Jan 2018 14:29:50 -0500 Received: from smtp-fw-9102.amazon.com ([207.171.184.29]:23558 "EHLO smtp-fw-9102.amazon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752110AbeA1T3s (ORCPT ); Sun, 28 Jan 2018 14:29:48 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.de; i=@amazon.de; q=dns/txt; s=amazon201209; t=1517167788; x=1548703788; h=from:to:cc:subject:date:message-id; bh=eh8XKcebiqc92v9xhLNon5n3JNlGAJj+tqwgb233u1Q=; b=g6eAJq6NzmxDxul1qW1BKFsKlZuCz+WzulF2yn5fD9fKFLy5h/PJ+IwP X5lxyeTTOVsTLeVB0pD1D6T75L51FN3Xa0oBWoRNARA41y+0gwygvDfXW Mm8sbcjRXE8r9cteFL5e3rIEhYI/f38mh9p2kYHSnKV4B0whHmg7d/7o4 Y=; X-IronPort-AV: E=Sophos;i="5.46,427,1511827200"; d="scan'208";a="590575590" Received: from sea3-co-svc-lb6-vlan3.sea.amazon.com (HELO email-inbound-relay-2c-168cbb73.us-west-2.amazon.com) ([10.47.22.38]) by smtp-border-fw-out-9102.sea19.amazon.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 28 Jan 2018 19:29:46 +0000 Received: from u54e1ad5160425a4b64ea.ant.amazon.com (pdx2-ws-svc-lb17-vlan3.amazon.com [10.247.140.70]) by email-inbound-relay-2c-168cbb73.us-west-2.amazon.com (8.14.7/8.14.7) with ESMTP id w0SJTfko123304 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sun, 28 Jan 2018 19:29:43 GMT Received: from u54e1ad5160425a4b64ea.ant.amazon.com (localhost [127.0.0.1]) by u54e1ad5160425a4b64ea.ant.amazon.com (8.15.2/8.15.2/Debian-3) with ESMTP id w0SJTdBg023850; Sun, 28 Jan 2018 20:29:39 +0100 Received: (from karahmed@localhost) by u54e1ad5160425a4b64ea.ant.amazon.com (8.15.2/8.15.2/Submit) id w0SJTb0N023847; Sun, 28 Jan 2018 20:29:37 +0100 From: KarimAllah Ahmed To: kvm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: KarimAllah Ahmed , Asit Mallick , Arjan Van De Ven , Dave Hansen , Andi Kleen , Andrea Arcangeli , Linus Torvalds , Tim Chen , Thomas Gleixner , Dan Williams , Jun Nakajima , Paolo Bonzini , David Woodhouse , Greg KH , Andy Lutomirski , Ashok Raj Subject: [PATCH] x86: vmx: Allow direct access to MSR_IA32_SPEC_CTRL Date: Sun, 28 Jan 2018 20:29:10 +0100 Message-Id: <1517167750-23485-1-git-send-email-karahmed@amazon.de> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add direct access to MSR_IA32_SPEC_CTRL for guests. This is needed for guests that will only mitigate Spectre V2 through IBRS+IBPB and will not be using a retpoline+IBPB based approach. To avoid the overhead of atomically saving and restoring the MSR_IA32_SPEC_CTRL for guests that do not actually use the MSR, only add_atomic_switch_msr when a non-zero is written to it. Cc: Asit Mallick Cc: Arjan Van De Ven Cc: Dave Hansen Cc: Andi Kleen Cc: Andrea Arcangeli Cc: Linus Torvalds Cc: Tim Chen Cc: Thomas Gleixner Cc: Dan Williams Cc: Jun Nakajima Cc: Paolo Bonzini Cc: David Woodhouse Cc: Greg KH Cc: Andy Lutomirski Signed-off-by: KarimAllah Ahmed Signed-off-by: Ashok Raj --- arch/x86/kvm/cpuid.c | 4 +++- arch/x86/kvm/cpuid.h | 1 + arch/x86/kvm/vmx.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 0099e10..dc78095 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -70,6 +70,7 @@ u64 kvm_supported_xcr0(void) /* These are scattered features in cpufeatures.h. */ #define KVM_CPUID_BIT_AVX512_4VNNIW 2 #define KVM_CPUID_BIT_AVX512_4FMAPS 3 +#define KVM_CPUID_BIT_SPEC_CTRL 26 #define KF(x) bit(KVM_CPUID_BIT_##x) int kvm_update_cpuid(struct kvm_vcpu *vcpu) @@ -392,7 +393,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, /* cpuid 7.0.edx*/ const u32 kvm_cpuid_7_0_edx_x86_features = - KF(AVX512_4VNNIW) | KF(AVX512_4FMAPS); + KF(AVX512_4VNNIW) | KF(AVX512_4FMAPS) | \ + (boot_cpu_has(X86_FEATURE_SPEC_CTRL) ? KF(SPEC_CTRL) : 0); /* all calls to cpuid_count() should be made on the same cpu */ get_cpu(); diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index cdc70a3..dcfe227 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -54,6 +54,7 @@ static const struct cpuid_reg reverse_cpuid[] = { [CPUID_8000_000A_EDX] = {0x8000000a, 0, CPUID_EDX}, [CPUID_7_ECX] = { 7, 0, CPUID_ECX}, [CPUID_8000_0007_EBX] = {0x80000007, 0, CPUID_EBX}, + [CPUID_7_EDX] = { 7, 0, CPUID_EDX}, }; static __always_inline struct cpuid_reg x86_feature_cpuid(unsigned x86_feature) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index aa8638a..1b743a0 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -920,6 +920,9 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked); static bool nested_vmx_is_page_fault_vmexit(struct vmcs12 *vmcs12, u16 error_code); static void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu); +static void __always_inline vmx_disable_intercept_for_msr(unsigned long *msr_bitmap, + u32 msr, int type); + static DEFINE_PER_CPU(struct vmcs *, vmxarea); static DEFINE_PER_CPU(struct vmcs *, current_vmcs); @@ -2007,6 +2010,28 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, m->host[i].value = host_val; } +/* do not touch guest_val and host_val if the msr is not found */ +static int read_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, + u64 *guest_val, u64 *host_val) +{ + unsigned i; + struct msr_autoload *m = &vmx->msr_autoload; + + for (i = 0; i < m->nr; ++i) + if (m->guest[i].index == msr) + break; + + if (i == m->nr) + return 1; + + if (guest_val) + *guest_val = m->guest[i].value; + if (host_val) + *host_val = m->host[i].value; + + return 0; +} + static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) { u64 guest_efer = vmx->vcpu.arch.efer; @@ -3203,7 +3228,9 @@ static inline bool vmx_feature_control_msr_valid(struct kvm_vcpu *vcpu, */ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { + u64 spec_ctrl = 0; struct shared_msr_entry *msr; + struct vcpu_vmx *vmx = to_vmx(vcpu); switch (msr_info->index) { #ifdef CONFIG_X86_64 @@ -3223,6 +3250,19 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_IA32_TSC: msr_info->data = guest_read_tsc(vcpu); break; + case MSR_IA32_SPEC_CTRL: + if (!msr_info->host_initiated && + !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL)) + return 1; + + /* + * If the MSR is not in the atomic list yet, then it was never + * written to. So the MSR value will be '0'. + */ + read_atomic_switch_msr(vmx, MSR_IA32_SPEC_CTRL, &spec_ctrl, NULL); + + msr_info->data = spec_ctrl; + break; case MSR_IA32_SYSENTER_CS: msr_info->data = vmcs_read32(GUEST_SYSENTER_CS); break; @@ -3289,6 +3329,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) int ret = 0; u32 msr_index = msr_info->index; u64 data = msr_info->data; + unsigned long *msr_bitmap; + + /* + * IBRS is not used (yet) to protect the host. Once it does, this + * variable needs to be a bit smarter. + */ + u64 host_spec_ctrl = 0; switch (msr_index) { case MSR_EFER: @@ -3330,6 +3377,22 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_IA32_TSC: kvm_write_tsc(vcpu, msr_info); break; + case MSR_IA32_SPEC_CTRL: + if (!msr_info->host_initiated && + !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL)) + return 1; + + /* + * Now we know that the guest is actually using the MSR, so + * atomically load and save the SPEC_CTRL MSR and pass it + * through to the guest. + */ + add_atomic_switch_msr(vmx, MSR_IA32_SPEC_CTRL, msr_info->data, + host_spec_ctrl); + msr_bitmap = vmx->vmcs01.msr_bitmap; + vmx_disable_intercept_for_msr(msr_bitmap, MSR_FS_BASE, MSR_TYPE_RW); + + break; case MSR_IA32_CR_PAT: if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) { if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data)) -- 2.7.4