Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933279AbeALBco (ORCPT + 1 other); Thu, 11 Jan 2018 20:32:44 -0500 Received: from mga11.intel.com ([192.55.52.93]:45984 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932817AbeALBcY (ORCPT ); Thu, 11 Jan 2018 20:32:24 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,346,1511856000"; d="scan'208";a="10606006" From: Ashok Raj To: linux-kernel@vger.kernel.org, Thomas Gleixner , Tim Chen , Andy Lutomirski , Linus Torvalds , Greg KH Cc: Ashok Raj , Dave Hansen , Andrea Arcangeli , Andi Kleen , Arjan Van De Ven , David Woodhouse , Peter Zijlstra , Dan Williams , Paolo Bonzini , Jun Nakajima , Asit Mallick Subject: [PATCH 5/5] x86/feature: Detect the x86 feature Indirect Branch Prediction Barrier Date: Thu, 11 Jan 2018 17:32:19 -0800 Message-Id: <1515720739-43819-6-git-send-email-ashok.raj@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515720739-43819-1-git-send-email-ashok.raj@intel.com> References: <1515720739-43819-1-git-send-email-ashok.raj@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: cpuid ax=0x7, return rdx bit 26 to indicate presence of both IA32_SPEC_CTRL(MSR 0x48) and IA32_PRED_CMD(MSR 0x49) BIT0: Indirect Branch Prediction Barrier When this MSR is written with IBPB=1 it ensures that earlier code's behavior doesn't control later indirect branch predictions. Note this MSR is only writable and does not carry any state. Its a barrier so the code should perform a wrmsr when the barrier is needed. Signed-off-by: Ashok Raj --- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/msr-index.h | 3 +++ arch/x86/kernel/cpu/spec_ctrl.c | 7 +++++++ arch/x86/kvm/svm.c | 16 ++++++++++++++++ arch/x86/kvm/vmx.c | 10 ++++++++++ 5 files changed, 37 insertions(+) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 624b58e..52f37fc 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -213,6 +213,7 @@ #define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */ #define X86_FEATURE_SPEC_CTRL ( 7*32+19) /* Speculation Control */ #define X86_FEATURE_SPEC_CTRL_IBRS ( 7*32+20) /* Speculation Control, use IBRS */ +#define X86_FEATURE_PRED_CMD ( 7*32+21) /* Indirect Branch Prediction Barrier */ /* Virtualization flags: Linux defined, word 8 */ #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 3e1cb18..1888e19 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -46,6 +46,9 @@ #define SPEC_CTRL_DISABLE_IBRS (0 << 0) #define SPEC_CTRL_ENABLE_IBRS (1 << 0) +#define MSR_IA32_PRED_CMD 0x00000049 +#define FEATURE_SET_IBPB (1<<0) + #define MSR_IA32_PERFCTR0 0x000000c1 #define MSR_IA32_PERFCTR1 0x000000c2 #define MSR_FSB_FREQ 0x000000cd diff --git a/arch/x86/kernel/cpu/spec_ctrl.c b/arch/x86/kernel/cpu/spec_ctrl.c index 02fc630..6cfec19 100644 --- a/arch/x86/kernel/cpu/spec_ctrl.c +++ b/arch/x86/kernel/cpu/spec_ctrl.c @@ -15,6 +15,13 @@ void spec_ctrl_scan_feature(struct cpuinfo_x86 *c) if (!c->cpu_index) static_branch_enable(&spec_ctrl_dynamic_ibrs); } + /* + * For Intel CPU's this MSR is shared the same cpuid + * enumeration. When MSR_IA32_SPEC_CTRL is present + * MSR_IA32_SPEC_CTRL is also available + * TBD: AMD might have a separate enumeration for each. + */ + set_cpu_cap(c, X86_FEATURE_PRED_CMD); } } diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 7c14471a..36924c9 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -251,6 +251,7 @@ static const struct svm_direct_access_msrs { { .index = MSR_SYSCALL_MASK, .always = true }, #endif { .index = MSR_IA32_SPEC_CTRL, .always = true }, + { .index = MSR_IA32_PRED_CMD, .always = false }, { .index = MSR_IA32_LASTBRANCHFROMIP, .always = false }, { .index = MSR_IA32_LASTBRANCHTOIP, .always = false }, { .index = MSR_IA32_LASTINTFROMIP, .always = false }, @@ -531,6 +532,7 @@ struct svm_cpu_data { struct kvm_ldttss_desc *tss_desc; struct page *save_area; + struct vmcb *current_vmcb; }; static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data); @@ -923,6 +925,8 @@ static void svm_vcpu_init_msrpm(u32 *msrpm) if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) set_msr_interception(msrpm, MSR_IA32_SPEC_CTRL, 1, 1); + if (boot_cpu_has(X86_FEATURE_PRED_CMD)) + set_msr_interception(msrpm, MSR_IA32_PRED_CMD, 1, 1); } static void add_msr_offset(u32 offset) @@ -1711,11 +1715,18 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu) __free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER); kvm_vcpu_uninit(vcpu); kmem_cache_free(kvm_vcpu_cache, svm); + /* + * The VMCB could be recycled, causing a false negative in svm_vcpu_load; + * block speculative execution. + */ + if (boot_cpu_has(X86_FEATURE_PRED_CMD)) + native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB); } static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { struct vcpu_svm *svm = to_svm(vcpu); + struct svm_cpu_data *sd = per_cpu(svm_data, cpu); int i; if (unlikely(cpu != vcpu->cpu)) { @@ -1744,6 +1755,11 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (static_cpu_has(X86_FEATURE_RDTSCP)) wrmsrl(MSR_TSC_AUX, svm->tsc_aux); + if (sd->current_vmcb != svm->vmcb) { + sd->current_vmcb = svm->vmcb; + if (boot_cpu_has(X86_FEATURE_PRED_CMD)) + native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB); + } avic_vcpu_load(vcpu, cpu); } diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 1913896..caeb9ff 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2280,6 +2280,8 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) { per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs; vmcs_load(vmx->loaded_vmcs->vmcs); + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB); } if (!already_loaded) { @@ -3837,6 +3839,12 @@ static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs) free_vmcs(loaded_vmcs->vmcs); loaded_vmcs->vmcs = NULL; WARN_ON(loaded_vmcs->shadow_vmcs != NULL); + /* + * The VMCS could be recycled, causing a false negative in vmx_vcpu_load + * block speculative execution. + */ + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB); } static void free_kvm_area(void) @@ -6804,6 +6812,8 @@ static __init int hardware_setup(void) */ if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) vmx_disable_intercept_for_msr(MSR_IA32_SPEC_CTRL, false); + if (boot_cpu_has(X86_FEATURE_PRED_CMD)) + vmx_disable_intercept_for_msr(MSR_IA32_PRED_CMD, false); vmx_disable_intercept_for_msr(MSR_FS_BASE, false); vmx_disable_intercept_for_msr(MSR_GS_BASE, false); -- 2.7.4