Linux Patch #3
Subsystems (2)
PATCH v6 3/10 Linux Patch #3
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
---
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(-)
arch/x86/include/asm/nospec-branch.h +21 -4
@@ -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)
arch/x86/kernel/cpu/bugs.c +28 -0
@@ -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;
Signature · 1 line
2.14.3
arch/x86/kernel/cpu/bugs.c line 35
Quoted 5 lines · speck for konrad.wilk_at_oracle.com
arch/x86/kernel/cpu/bugs.c +5
-0+/* +* 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;
This wants to be __ro_after_init. Nothing can change it during runtime.