Received: by 10.223.176.5 with SMTP id f5csp14125wra; Tue, 6 Feb 2018 16:09:10 -0800 (PST) X-Google-Smtp-Source: AH8x2272fa1kq21pHVQY23yxjeuvmsaMXmTMpvkHu7P8gI+7iPGfVLpGOOLdyJGzeSXIgXdiM/ZU X-Received: by 2002:a17:902:9895:: with SMTP id s21-v6mr3978460plp.297.1517962150009; Tue, 06 Feb 2018 16:09:10 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517962149; cv=none; d=google.com; s=arc-20160816; b=GITVQvzr5FeX1526BnRRB/pErhTp1cFDZQWnfw26nQfCmeb17wFiumTYsd/XBcNTAo 9IJd0DGzvqocBf8v8cRQrsi7CN3gpB7lrnLW1Wbp+kP5tb7aM3Rx+K/AZU/dmYbmMGvf c0Axhs+kVSiBcPA88vgJZlwy8s3Uh5ldIqpXE6ke5hYsSP1DmgOGbIARKbQ8U2Ist9EB 0ieE6WH4q7UUx9l/BZazfrImQTg0MlH0rGpueBHDrAA0d/3a3PuPmFOG0y1D2veOXPRW /nciagnCa/I4S8RwGBgvOyMQqfRz8Ooh6l5PNLLWHrJEx64l4l02K9IrOUDAZyz28E4B TMug== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:to:from:dkim-signature:arc-authentication-results; bh=bDpdgj3Vb7XnnPdMuywP1Xkq5FS+enQsLzyykxM43gs=; b=YrgLsxEbdZfusq2Y7yV2qAfglwUZ+KGM03gikV1cnie+gdncaEe4ZVnKqJJJ7QmTLa ZYjVdRbcThjEJnxRI0KD8N0yJ/gZjhiKgMhu3LYsuFfhL7t6FWX1yAJwodRkgxR+PYv1 FxPFimx5R91YVn2bxiUjMcRPVFOIfSrXSoO7IkLUmJT2DxkBvCXNLacNh+5A/vxULsfI CGlV0EHbII5tUXGNAt8OTyCZW/OIWIQ8cQCQd+uQucqXyizh/Z9EWk+08bVqXaALt8By 6dNqZ0c5rg9yqJefx+iAoqiqKFfXpydh5WHHVum+GnsxHbFeprSlV6btl2MtoQTsSI96 RpYA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amazon.co.uk header.s=amazon201209 header.b=aLm+k2P0; 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.co.uk Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v14si130600pgc.350.2018.02.06.16.08.52; Tue, 06 Feb 2018 16:09:09 -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.co.uk header.s=amazon201209 header.b=aLm+k2P0; 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.co.uk Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754226AbeBGAH0 (ORCPT + 99 others); Tue, 6 Feb 2018 19:07:26 -0500 Received: from smtp-fw-9102.amazon.com ([207.171.184.29]:57687 "EHLO smtp-fw-9102.amazon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754095AbeBGAHZ (ORCPT ); Tue, 6 Feb 2018 19:07:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.co.uk; i=@amazon.co.uk; q=dns/txt; s=amazon201209; t=1517962045; x=1549498045; h=from:to:subject:date:message-id:in-reply-to:references; bh=bDpdgj3Vb7XnnPdMuywP1Xkq5FS+enQsLzyykxM43gs=; b=aLm+k2P0a8JBNyr/qshoCLPLwxI8HJbfePgxy92G47y66mxnYo3ViJcp lUBweUJfe1PZ1u6C/hiwo8JGAwG+zsRIDcw8jxjyewsRWXyqX2pNW20FD n1gbQ25N4Aw/xHHq0Rf9eTOoGUmZJaraiKUjZWctyFBu6HESOhP9WEIMP E=; X-IronPort-AV: E=Sophos;i="5.46,470,1511827200"; d="scan'208";a="593724387" Received: from sea3-co-svc-lb6-vlan3.sea.amazon.com (HELO email-inbound-relay-1a-7d76a15f.us-east-1.amazon.com) ([10.47.22.38]) by smtp-border-fw-out-9102.sea19.amazon.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 07 Feb 2018 00:04:08 +0000 Received: from uc8d3ff76b9bc5848a9cc.ant.amazon.com (iad1-ws-svc-lb91-vlan2.amazon.com [10.0.103.146]) by email-inbound-relay-1a-7d76a15f.us-east-1.amazon.com (8.14.7/8.14.7) with ESMTP id w1703blY018971 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 7 Feb 2018 00:03:40 GMT Received: from uc8d3ff76b9bc5848a9cc.ant.amazon.com (localhost [127.0.0.1]) by uc8d3ff76b9bc5848a9cc.ant.amazon.com (8.15.2/8.15.2/Debian-3) with ESMTP id w1703aIj015515; Wed, 7 Feb 2018 00:03:36 GMT Received: (from dwmw@localhost) by uc8d3ff76b9bc5848a9cc.ant.amazon.com (8.15.2/8.15.2/Submit) id w1703a86015514; Wed, 7 Feb 2018 00:03:36 GMT From: David Woodhouse To: tglx@linutronix.de, torvalds@linux-foundation.org, x86@kernel.org, linux-kernel@vger.kernel.org, bp@alien8.de, peterz@infradead.org, tim.c.chen@linux.intel.com, dave.hansen@intel.com, arjan.van.de.ven@intel.com Subject: [RFC PATCH 3/4] x86/speculation: Use IBRS if available before calling into firmware Date: Wed, 7 Feb 2018 00:03:13 +0000 Message-Id: <1517961794-14972-4-git-send-email-dwmw@amazon.co.uk> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1517961794-14972-1-git-send-email-dwmw@amazon.co.uk> References: <1517961794-14972-1-git-send-email-dwmw@amazon.co.uk> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. Signed-off-by: David Woodhouse --- arch/x86/include/asm/apm.h | 6 ++++++ arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/efi.h | 13 +++++++++++-- arch/x86/include/asm/nospec-branch.h | 37 +++++++++++++++++++++++++++--------- arch/x86/kernel/cpu/bugs.c | 12 +++++++++++- drivers/watchdog/hpwdt.c | 3 +++ 6 files changed, 60 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/apm.h b/arch/x86/include/asm/apm.h index 4d4015d..4483616 100644 --- a/arch/x86/include/asm/apm.h +++ b/arch/x86/include/asm/apm.h @@ -7,6 +7,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" \ @@ -32,6 +34,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, * 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" @@ -44,6 +47,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, "=S" (*esi) : "a" (func), "b" (ebx_in), "c" (ecx_in) : "memory", "cc"); + firmware_restrict_branch_speculation_end(); } static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, @@ -56,6 +60,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, * 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" @@ -68,6 +73,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, "=S" (si) : "a" (func), "b" (ebx_in), "c" (ecx_in) : "memory", "cc"); + firmware_restrict_branch_speculation_end(); return error; } diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 73b5fff..66c1434 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -211,6 +211,7 @@ #define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */ #define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */ +#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */ /* Virtualization flags: Linux defined, word 8 */ #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 85f6ccb..6b27828 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -6,6 +6,7 @@ #include #include #include +#include /* * We map the EFI regions needed for runtime services non-contiguously, @@ -36,8 +37,14 @@ extern asmlinkage unsigned long efi_call_phys(void *, ...); -#define arch_efi_call_virt_setup() kernel_fpu_begin() -#define arch_efi_call_virt_teardown() kernel_fpu_end() +#define arch_efi_call_virt_setup() \ + kernel_fpu_begin() \ + firmware_restrict_branch_speculation_start(); + +#define arch_efi_call_virt_teardown() \ + firmware_restrict_branch_speculation_end(); \ + kernel_fpu_end() + /* * Wrap all the virtual calls in a way that forces the parameters on the stack. @@ -73,6 +80,7 @@ struct efi_scratch { efi_sync_low_kernel_mappings(); \ preempt_disable(); \ __kernel_fpu_begin(); \ + firmware_restrict_branch_speculation_start(); \ \ if (efi_scratch.use_pgd) { \ efi_scratch.prev_cr3 = __read_cr3(); \ @@ -91,6 +99,7 @@ struct efi_scratch { __flush_tlb_all(); \ } \ \ + firmware_restrict_branch_speculation_end(); \ __kernel_fpu_end(); \ preempt_enable(); \ }) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 300cc15..788c4da 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -162,17 +162,36 @@ 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) +{ + 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); } #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 61152aa..6f6d763 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -303,6 +303,15 @@ static void __init spectre_v2_select_mitigation(void) 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 @@ -332,8 +341,9 @@ ssize_t cpu_show_spectre_v2(struct device *dev, 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 diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 67fbe35..bab3721 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -38,6 +38,7 @@ #endif /* CONFIG_HPWDT_NMI_DECODING */ #include #include +#include #define HPWDT_VERSION "1.4.0" #define SECS_TO_TICKS(secs) ((secs) * 1000 / 128) @@ -486,11 +487,13 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs) if (!hpwdt_nmi_decoding) return NMI_DONE; + firmware_restrict_branch_speculation_start(); spin_lock_irqsave(&rom_lock, rom_pl); if (!die_nmi_called && !is_icru && !is_uefi) asminline_call(&cmn_regs, cru_rom_addr); die_nmi_called = 1; spin_unlock_irqrestore(&rom_lock, rom_pl); + firmware_restrict_branch_speculation_end(); if (allow_kdump) hpwdt_stop(); -- 2.7.4