Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp2275552imm; Thu, 7 Jun 2018 08:04:16 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKutT8mGlQPYQ5FxjVAd8WCzhPXGDwqG2bSA7sJcJGH6tSDuZTS2rMmstKLgCkP7bNM3Fd7 X-Received: by 2002:a17:902:aa03:: with SMTP id be3-v6mr2352611plb.165.1528383856230; Thu, 07 Jun 2018 08:04:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528383856; cv=none; d=google.com; s=arc-20160816; b=0hyQG6xCRbKWpVhkKz/QZ+t5veS1qOh4t8UzuhpElPBEcz1fKgTd/nwo5/UP+iZxGf lzQA23R0iltE3BP/ubmmHIkwkP0fc/Zy9Dd2XRtU2eP5OlT2oqfEwaWMfuqYJBkTUXus fwjWfYXkncV51onJHKKXkMU+T4HDm7+OhYlAPQKVUAcTyFsCmna7rkLQKmkqO8WtXC3q reabPBEA+AoqQ7JATdQp2G462z2qRX5tNJTEjMCay2kHHwgTY0Q63PMM20fQpVcquUCk 1UuJzqc/rjEPOYsw3HrPVvEh5gaVILpo3YJ10kVDiauMtPM8vsm0iJ9PM5Xt991CedsQ XRHg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition :arc-authentication-results; bh=IZY8dAyQrXkfuKTCyGkJQzHjWxDaszgIG+9S921hDa4=; b=cFRtyPm9nWHcXFnFO7SlR5bdS+XXEq3CSn1tYpdxMsoGL8mJyQqZHhz0GE9uw0vtP/ dFZtZLwBTjiiA29WKsDddsg4OPrAnyvPONJE/O2wsOMFCDWetFBxsivDuZ5GI9tb4Ayr M7m0+dmdeNm0Pmk6wrkHwpXBSIQP6RY2RzhtDXq0nBAZlsVndM10MzIQl4zioXXgTWDS s25lAPgxMkuXJHpmAIuJrwKtDtk+V7HpWjN2VFzJ5AcGkKEhNj5DcR5or8z35B+junAp 0SjCdEHUjWsyMh68NmXgDpoTJlwt8vkAhePIV3g96a9z8oYyURPVsSfUqDC6ZcNZ67ZB lGoQ== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t9-v6si14241909pgf.222.2018.06.07.08.04.01; Thu, 07 Jun 2018 08:04:16 -0700 (PDT) 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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964944AbeFGPCm (ORCPT + 99 others); Thu, 7 Jun 2018 11:02:42 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:41452 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935115AbeFGPCj (ORCPT ); Thu, 7 Jun 2018 11:02:39 -0400 Received: from [148.252.241.226] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1fQvbx-0005Zj-2f; Thu, 07 Jun 2018 15:09:57 +0100 Received: from ben by deadeye with local (Exim 4.91) (envelope-from ) id 1fQvaz-0002k7-19; Thu, 07 Jun 2018 15:08:57 +0100 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, arjan.van.de.ven@intel.com, dave.hansen@intel.com, rkrcmar@redhat.com, karahmed@amazon.de, kvm@vger.kernel.org, "Thomas Gleixner" , "Linus Torvalds" , pbonzini@redhat.com, "Ingo Molnar" , "David Woodhouse" , bp@alien8.de, "Peter Zijlstra" , jmattson@google.com Date: Thu, 07 Jun 2018 15:05:21 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 050/410] x86/speculation: Use IBRS if available before calling into firmware In-Reply-To: X-SA-Exim-Connect-IP: 148.252.241.226 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.57-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: David Woodhouse commit dd84441a797150dcc49298ec95c459a8891d8bb1 upstream. Retpoline means the kernel is safe because it has no indirect branches. But firmware isn't, so use IBRS for firmware calls if it's available. Block preemption while IBRS is set, although in practice the call sites already had to be doing that. Ignore hpwdt.c for now. It's taking spinlocks and calling into firmware code, from an NMI handler. I don't want to touch that with a bargepole. Signed-off-by: David Woodhouse Reviewed-by: Thomas Gleixner Cc: Linus Torvalds Cc: Peter Zijlstra Cc: arjan.van.de.ven@intel.com Cc: bp@alien8.de Cc: dave.hansen@intel.com Cc: jmattson@google.com Cc: karahmed@amazon.de Cc: kvm@vger.kernel.org Cc: pbonzini@redhat.com Cc: rkrcmar@redhat.com Link: http://lkml.kernel.org/r/1519037457-7643-2-git-send-email-dwmw@amazon.co.uk Signed-off-by: Ingo Molnar [bwh: Backported to 3.16: - x86 defines {,__}efi_call_virt() itself; update those definitions - Renumber the feature bit - Adjust context] Signed-off-by: Ben Hutchings --- arch/x86/include/asm/apm.h | 6 +++++ arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/efi.h | 8 ++++++ arch/x86/include/asm/nospec-branch.h | 39 +++++++++++++++++++++------- arch/x86/kernel/cpu/bugs.c | 12 ++++++++- 5 files changed, 56 insertions(+), 10 deletions(-) --- a/arch/x86/include/asm/apm.h +++ b/arch/x86/include/asm/apm.h @@ -6,6 +6,8 @@ #ifndef _ASM_X86_MACH_DEFAULT_APM_H #define _ASM_X86_MACH_DEFAULT_APM_H +#include + #ifdef APM_ZERO_SEGS # define APM_DO_ZERO_SEGS \ "pushl %%ds\n\t" \ @@ -31,6 +33,7 @@ static inline void apm_bios_call_asm(u32 * N.B. We do NOT need a cld after the BIOS call * because we always save and restore the flags. */ + firmware_restrict_branch_speculation_start(); __asm__ __volatile__(APM_DO_ZERO_SEGS "pushl %%edi\n\t" "pushl %%ebp\n\t" @@ -43,6 +46,7 @@ static inline void apm_bios_call_asm(u32 "=S" (*esi) : "a" (func), "b" (ebx_in), "c" (ecx_in) : "memory", "cc"); + firmware_restrict_branch_speculation_end(); } static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in, @@ -55,6 +59,7 @@ static inline u8 apm_bios_call_simple_as * N.B. We do NOT need a cld after the BIOS call * because we always save and restore the flags. */ + firmware_restrict_branch_speculation_start(); __asm__ __volatile__(APM_DO_ZERO_SEGS "pushl %%edi\n\t" "pushl %%ebp\n\t" @@ -67,6 +72,7 @@ static inline u8 apm_bios_call_simple_as "=S" (si) : "a" (func), "b" (ebx_in), "c" (ecx_in) : "memory", "cc"); + firmware_restrict_branch_speculation_end(); return error; } --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -190,6 +190,7 @@ #define X86_FEATURE_RSB_CTXSW (7*32+11) /* "" Fill RSB on context switches */ #define X86_FEATURE_USE_IBPB (7*32+12) /* "" Indirect Branch Prediction Barrier enabled */ +#define X86_FEATURE_USE_IBRS_FW (7*32+13) /* "" Use IBRS during runtime firmware calls */ #define X86_FEATURE_RETPOLINE (7*32+29) /* "" Generic Retpoline mitigation for Spectre variant 2 */ #define X86_FEATURE_RETPOLINE_AMD (7*32+30) /* "" AMD Retpoline mitigation for Spectre variant 2 */ --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -2,6 +2,8 @@ #define _ASM_X86_EFI_H #include +#include + /* * We map the EFI regions needed for runtime services non-contiguously, * with preserved alignment on virtual addresses starting from -4G down @@ -37,8 +39,10 @@ extern unsigned long asmlinkage efi_call ({ \ efi_status_t __s; \ kernel_fpu_begin(); \ + firmware_restrict_branch_speculation_start(); \ __s = ((efi_##f##_t __attribute__((regparm(0)))*) \ efi.systab->runtime->f)(args); \ + firmware_restrict_branch_speculation_end(); \ kernel_fpu_end(); \ __s; \ }) @@ -47,8 +51,10 @@ extern unsigned long asmlinkage efi_call #define __efi_call_virt(f, args...) \ ({ \ kernel_fpu_begin(); \ + firmware_restrict_branch_speculation_start(); \ ((efi_##f##_t __attribute__((regparm(0)))*) \ efi.systab->runtime->f)(args); \ + firmware_restrict_branch_speculation_end(); \ kernel_fpu_end(); \ }) @@ -69,7 +75,9 @@ extern u64 asmlinkage efi_call(void *fp, efi_sync_low_kernel_mappings(); \ preempt_disable(); \ __kernel_fpu_begin(); \ + firmware_restrict_branch_speculation_start(); \ __s = efi_call((void *)efi.systab->runtime->f, __VA_ARGS__); \ + firmware_restrict_branch_speculation_end(); \ __kernel_fpu_end(); \ preempt_enable(); \ __s; \ --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -194,17 +194,38 @@ static inline void vmexit_fill_RSB(void) #endif } +#define alternative_msr_write(_msr, _val, _feature) \ + asm volatile(ALTERNATIVE("", \ + "movl %[msr], %%ecx\n\t" \ + "movl %[val], %%eax\n\t" \ + "movl $0, %%edx\n\t" \ + "wrmsr", \ + _feature) \ + : : [msr] "i" (_msr), [val] "i" (_val) \ + : "eax", "ecx", "edx", "memory") + static inline void indirect_branch_prediction_barrier(void) { - asm volatile(ALTERNATIVE("", - "movl %[msr], %%ecx\n\t" - "movl %[val], %%eax\n\t" - "movl $0, %%edx\n\t" - "wrmsr", - X86_FEATURE_USE_IBPB) - : : [msr] "i" (MSR_IA32_PRED_CMD), - [val] "i" (PRED_CMD_IBPB) - : "eax", "ecx", "edx", "memory"); + alternative_msr_write(MSR_IA32_PRED_CMD, PRED_CMD_IBPB, + X86_FEATURE_USE_IBPB); +} + +/* + * With retpoline, we must use IBRS to restrict branch prediction + * before calling into firmware. + */ +static inline void firmware_restrict_branch_speculation_start(void) +{ + preempt_disable(); + alternative_msr_write(MSR_IA32_SPEC_CTRL, SPEC_CTRL_IBRS, + X86_FEATURE_USE_IBRS_FW); +} + +static inline void firmware_restrict_branch_speculation_end(void) +{ + alternative_msr_write(MSR_IA32_SPEC_CTRL, 0, + X86_FEATURE_USE_IBRS_FW); + preempt_enable(); } #endif /* __ASSEMBLY__ */ --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -364,6 +364,15 @@ retpoline_auto: setup_force_cpu_cap(X86_FEATURE_USE_IBPB); pr_info("Enabling Indirect Branch Prediction Barrier\n"); } + + /* + * Retpoline means the kernel is safe because it has no indirect + * branches. But firmware isn't, so use IBRS to protect that. + */ + if (boot_cpu_has(X86_FEATURE_IBRS)) { + setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW); + pr_info("Enabling Restricted Speculation for firmware calls\n"); + } } #undef pr_fmt @@ -393,8 +402,9 @@ ssize_t cpu_show_spectre_v2(struct devic if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2)) return sprintf(buf, "Not affected\n"); - return sprintf(buf, "%s%s%s\n", spectre_v2_strings[spectre_v2_enabled], + return sprintf(buf, "%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled], boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "", + boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "", spectre_v2_module_string()); } #endif