From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Google-Smtp-Source: AH8x227qXcy4F2B1Sig91f1uCoqF32f28LlzI1c2iGBUm1poT4bhkU2evdOvjfgFCyI97+GTvKBX ARC-Seal: i=1; a=rsa-sha256; t=1517167787; cv=none; d=google.com; s=arc-20160816; b=UbJFGx4LeseUM4zpBiIGBL8lw3ZYP79Iiwx/7NZ0fZNnV9YdakHXh4/x2ycGWglMSX D4tLCWzEgZmkWDEgSZM7Jz1iJy3iX/ToepBgBEak1GBQqCAZyVck7qxv4mFk7YSamJkJ nDTddr8Di7rpDhL7m3SCu8txNtFZQiw1JqPCPwtLTkM8HSv7nO4+SdRhzQ/CDRErKiNA gTlRIqsYFPX6voIL2iIeR5Orj/Slymce08xEFW/ojtsjH6qMfjVrIWtvSkzXWD3RsUkM L0FACc2Qn24t6ASFHCZD6aR47ImvBItj6Yos0jQ6RywuPyaPtiHTTJYNk25zJFEkB76Z H6pA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=eh8XKcebiqc92v9xhLNon5n3JNlGAJj+tqwgb233u1Q=; b=uDCfAYIJho3z/CLPUhCiGnP9cRqieMdUWn3NE67eHI9ERdMRZZWOn+sS5N04Glemg3 8lezuVp3Ez6TLuQiVysOMhB9GIDFwUIg1tVcNV4fPOZRZplVf/OxyYpmYlyGCOBltHnO 6BgSFw0OlFjVAdTJbGoG921r5ZB0DiRSsWbrrCBOcVE7jx4H0QxWCwq9JQzfpg6djRya 51FJmorawylsp/bZ7+cpV7ZEht1hnYWHX0xUI+EPGgcrObZqQNyoyRb4ootB3f9uh3i8 QrX2m9jbE++Ysuln6jFVjqX+rFFHqgDe1/aLr1Lm2yLpm0m5E1iwjcaqVBCy6lP6QVtC BVUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amazon.de header.s=amazon201209 header.b=LYd/z7xP; spf=pass (google.com: domain of prvs=559324c7a=karahmed@amazon.com designates 207.171.184.29 as permitted sender) smtp.mailfrom=prvs=559324c7a=karahmed@amazon.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.de Authentication-Results: mx.google.com; dkim=pass header.i=@amazon.de header.s=amazon201209 header.b=LYd/z7xP; spf=pass (google.com: domain of prvs=559324c7a=karahmed@amazon.com designates 207.171.184.29 as permitted sender) smtp.mailfrom=prvs=559324c7a=karahmed@amazon.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.de X-IronPort-AV: E=Sophos;i="5.46,427,1511827200"; d="scan'208";a="590575590" 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 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: =?utf-8?q?1590865729989295970?= X-GMAIL-MSGID: =?utf-8?q?1590865729989295970?= X-Mailing-List: linux-kernel@vger.kernel.org List-ID: 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