Return-path: Received: from aserp2120.oracle.com ([141.146.126.78]) by Galois.linutronix.de with esmtps (TLS1.2:RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1fBqp5-00061Q-Od for speck@linutronix.de; Fri, 27 Apr 2018 02:01:12 +0200 Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w3QNvW9L088027 for ; Fri, 27 Apr 2018 00:01:04 GMT Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp2120.oracle.com with ESMTP id 2hfw9anb7a-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 27 Apr 2018 00:01:04 +0000 Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.14.4) with ESMTP id w3R013Ra032466 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 27 Apr 2018 00:01:03 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id w3R0129Y007238 for ; Fri, 27 Apr 2018 00:01:02 GMT Message-Id: <20180426234831.205464050@localhost.localdomain> Date: Thu, 26 Apr 2018 19:48:23 -0400 From: konrad.wilk@oracle.com Subject: [MODERATED] [PATCH v6 03/11] [PATCH v6 03/10] Linux Patch #3 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit To: speck@linutronix.de List-ID: The 336996-Speculative-Execution-Side-Channel-Mitigations.pdf refers to all the other bits as reserved. The Intel SDM glossary defines reserved as implementation specific - aka unknown. As such at bootup we should take it into account and apply proper masking for the bits we use. A copy of this document is available at https://bugzilla.kernel.org/show_bug.cgi?id=199511 xReviewed-by: Borislav Petkov xSuggested-by: Jon Masters Signed-off-by: Konrad Rzeszutek Wilk --- v2: New patch v3: Expose only one global variable v4: Don't expose global variable. Provide x86_set_spec_ctrl and x86_get_spec_ctrl Only filter IBRS on x86_set_spec_ctrl v5: Add bugzilla URL Added Reviewed-by Removed spec_ctrl_save_msr s/x86_get_spec_ctrl/x86_get_default_spec_ctrl/ Add __read_mostly on the variable Add comment for what it is. v6: Made x86_spec_ctrl_base static Added Reviewed-by --- arch/x86/include/asm/nospec-branch.h | 25 +++++++++++++++++++++---- arch/x86/kernel/cpu/bugs.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index f928ad9b143f..984f4a36960f 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -217,6 +217,17 @@ enum spectre_v2_mitigation { SPECTRE_V2_IBRS, }; +/* + * The Intel specification for the SPEC_CTRL MSR requires that we + * preserve any already set reserved bits at boot time (e.g. for + * future additions that this kernel is not currently aware of). + * We then set any additional mitigation bits that we want + * ourselves and always use this as the base for SPEC_CTRL. + * We also use this when handling guest entry/exit as below. + */ +extern void x86_set_spec_ctrl(u64); +extern u64 x86_get_default_spec_ctrl(void); + extern char __indirect_thunk_start[]; extern char __indirect_thunk_end[]; @@ -248,12 +259,14 @@ static inline void vmexit_fill_RSB(void) "movl $0, %%edx\n\t" \ "wrmsr", \ _feature) \ - : : [msr] "i" (_msr), [val] "i" (_val) \ + : : [msr] "i" (_msr), [val] "m" (_val) \ : "eax", "ecx", "edx", "memory") static inline void indirect_branch_prediction_barrier(void) { - alternative_msr_write(MSR_IA32_PRED_CMD, PRED_CMD_IBPB, + u64 val = PRED_CMD_IBPB; + + alternative_msr_write(MSR_IA32_PRED_CMD, val, X86_FEATURE_USE_IBPB); } @@ -265,14 +278,18 @@ static inline void indirect_branch_prediction_barrier(void) */ #define firmware_restrict_branch_speculation_start() \ do { \ + u64 val = x86_get_default_spec_ctrl() | SPEC_CTRL_IBRS; \ + \ preempt_disable(); \ - alternative_msr_write(MSR_IA32_SPEC_CTRL, SPEC_CTRL_IBRS, \ + alternative_msr_write(MSR_IA32_SPEC_CTRL, val, \ X86_FEATURE_USE_IBRS_FW); \ } while (0) #define firmware_restrict_branch_speculation_end() \ do { \ - alternative_msr_write(MSR_IA32_SPEC_CTRL, 0, \ + u64 val = x86_get_default_spec_ctrl(); \ + \ + alternative_msr_write(MSR_IA32_SPEC_CTRL, val, \ X86_FEATURE_USE_IBRS_FW); \ preempt_enable(); \ } while (0) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index ad613f73d071..048719d5c9b8 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -28,10 +28,23 @@ static void __init spectre_v2_select_mitigation(void); +/* + * Our boot-time value of SPEC_CTRL MSR. We read it once so that any + * writes to SPEC_CTRL contain whatever reserved bits have been set. + */ +static u64 __read_mostly x86_spec_ctrl_base; + void __init check_bugs(void) { identify_boot_cpu(); + /* + * Read the SPEC_CTRL MSR to account for reserved bits which may have + * unknown values. + */ + if (boot_cpu_has(X86_FEATURE_IBRS)) + rdmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base); + if (!IS_ENABLED(CONFIG_SMP)) { pr_info("CPU: "); print_cpu_info(&boot_cpu_data); @@ -95,6 +108,21 @@ static const char *spectre_v2_strings[] = { static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE; +void x86_set_spec_ctrl(u64 val) +{ + if (val & ~(SPEC_CTRL_IBRS)) + WARN_ONCE(1, "SPEC_CTRL MSR value 0x%16llx is unknown.\n", val); + else + wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base | val); +} +EXPORT_SYMBOL_GPL(x86_set_spec_ctrl); + +u64 x86_get_default_spec_ctrl(void) +{ + return x86_spec_ctrl_base; +} +EXPORT_SYMBOL_GPL(x86_get_default_spec_ctrl); + #ifdef RETPOLINE static bool spectre_v2_bad_module; -- 2.14.3