On Mon, Jan 08, 2018 at 01:47:07PM +0100, Peter Zijlstra wrote:
> > a good suggestion, but we encountered some issues with it either
> > crashing the kernel at boot or not properly turning on/off.

The below boots, but I lack stuff to test the enabling.

--- a/arch/x86/include/asm/spec_ctrl.h
+++ b/arch/x86/include/asm/spec_ctrl.h
@@ -9,9 +9,8 @@
 
 void scan_spec_ctrl_feature(struct cpuinfo_x86 *c);
 void rescan_spec_ctrl_feature(struct cpuinfo_x86 *c);
-bool ibrs_inuse(void);
 
-extern unsigned int dynamic_ibrs;
+DECLARE_STATIC_KEY_FALSE(ibrs_key);
 
 static inline void __disable_indirect_speculation(void)
 {
@@ -31,21 +30,14 @@ static inline void __enable_indirect_spe
 static inline void unprotected_speculation_begin(void)
 {
        lockdep_assert_irqs_disabled();
-       if (dynamic_ibrs)
+       if (static_branch_unlikely(&ibrs_key))
                __enable_indirect_speculation();
 }
 
 static inline void unprotected_speculation_end(void)
 {
-       if (dynamic_ibrs) {
+       if (static_branch_unlikely(&ibrs_key))
                __disable_indirect_speculation();
-       } else {
-               /*
-                * rmb prevent unwanted speculation when we
-                * are setting IBRS
-                */
-               rmb();
-       }
 }
 
 #endif /* _ASM_X86_SPEC_CTRL_H */
--- a/arch/x86/kernel/cpu/spec_ctrl.c
+++ b/arch/x86/kernel/cpu/spec_ctrl.c
@@ -7,8 +7,7 @@
 #include <asm/spec_ctrl.h>
 #include <asm/cpufeature.h>
 
-unsigned int dynamic_ibrs __read_mostly;
-EXPORT_SYMBOL_GPL(dynamic_ibrs);
+DEFINE_STATIC_KEY_FALSE(ibrs_key);
 
 enum {
        IBRS_DISABLED,
@@ -27,7 +26,7 @@ DEFINE_MUTEX(spec_ctrl_mutex);
 static inline void set_ibrs_feature(void)
 {
        if (!ibrs_admin_disabled) {
-               dynamic_ibrs = 1;
+               static_branch_enable(&ibrs_key);
                ibrs_enabled = IBRS_ENABLED;
        }
 }
@@ -54,12 +53,6 @@ void rescan_spec_ctrl_feature(struct cpu
 }
 EXPORT_SYMBOL_GPL(rescan_spec_ctrl_feature);
 
-bool ibrs_inuse(void)
-{
-       return ibrs_enabled == IBRS_ENABLED;
-}
-EXPORT_SYMBOL_GPL(ibrs_inuse);
-
 static int __init noibrs(char *str)
 {
        ibrs_admin_disabled = true;
@@ -124,19 +117,23 @@ static ssize_t ibrs_enabled_write(struct
        if (enable == IBRS_DISABLED) {
                /* disable IBRS usage */
                ibrs_admin_disabled = true;
-               dynamic_ibrs = 0;
+               static_branch_disable(&ibrs_key);
                spec_ctrl_flush_all_cpus(MSR_IA32_SPEC_CTRL,
                                         SPEC_CTRL_FEATURE_DISABLE_IBRS);
 
        } else if (enable == IBRS_ENABLED) {
                /* enable IBRS usage in kernel */
                ibrs_admin_disabled = false;
-               dynamic_ibrs = 1;
+               static_branch_enable(&ibrs_key);
+               /*
+                * This too needs an IPI to force all active CPUs into a known 
state.
+                */
 
        } else if (enable == IBRS_ENABLED_USER) {
                /* enable IBRS all the time in both userspace and kernel */
                ibrs_admin_disabled = false;
-               dynamic_ibrs = 0;
+               static_branch_disable(&ibrs_key);
+
                spec_ctrl_flush_all_cpus(MSR_IA32_SPEC_CTRL,
                                         SPEC_CTRL_FEATURE_ENABLE_IBRS);
        }
--- a/arch/x86/entry/calling.h
+++ b/arch/x86/entry/calling.h
@@ -373,22 +373,17 @@ For 32-bit we have the following convent
 .endm
 
 .macro ENABLE_IBRS
-       testl   $1, dynamic_ibrs
-       jz      .Lskip_\@
+       STATIC_JUMP_IF_FALSE .Lskip_\@, ibrs_key, def=0
 
        PUSH_MSR_REGS
        WRMSR_ASM $MSR_IA32_SPEC_CTRL, $SPEC_CTRL_FEATURE_ENABLE_IBRS
        POP_MSR_REGS
-       jmp     .Ldone_\@
 
 .Lskip_\@:
-       lfence
-.Ldone_\@:
 .endm
 
 .macro DISABLE_IBRS
-       testl   $1, dynamic_ibrs
-       jz      .Lskip_\@
+       STATIC_JUMP_IF_FALSE .Lskip_\@, ibrs_key, def=0
 
        PUSH_MSR_REGS
        WRMSR_ASM $MSR_IA32_SPEC_CTRL, $SPEC_CTRL_FEATURE_DISABLE_IBRS
@@ -398,20 +393,15 @@ For 32-bit we have the following convent
 .endm
 
 .macro ENABLE_IBRS_CLOBBER
-       testl   $1, dynamic_ibrs
-       jz      .Lskip_\@
+       STATIC_JUMP_IF_FALSE .Lskip_\@, ibrs_key, def=0
 
        WRMSR_ASM $MSR_IA32_SPEC_CTRL, $SPEC_CTRL_FEATURE_ENABLE_IBRS
-       jmp     .Ldone_\@
 
 .Lskip_\@:
-       lfence
-.Ldone_\@:
 .endm
 
 .macro DISABLE_IBRS_CLOBBER
-       testl   $1, dynamic_ibrs
-       jz      .Lskip_\@
+       STATIC_JUMP_IF_FALSE .Lskip_\@, ibrs_key, def=0
 
        WRMSR_ASM $MSR_IA32_SPEC_CTRL, $SPEC_CTRL_FEATURE_DISABLE_IBRS
 
@@ -419,8 +409,7 @@ For 32-bit we have the following convent
 .endm
 
 .macro ENABLE_IBRS_SAVE_AND_CLOBBER save_reg:req
-       testl   $1, dynamic_ibrs
-       jz      .Lskip_\@
+       STATIC_JUMP_IF_FALSE .Lskip_\@, ibrs_key, def=0
 
        movl    $MSR_IA32_SPEC_CTRL, %ecx
        rdmsr
@@ -429,25 +418,18 @@ For 32-bit we have the following convent
        movl    $0, %edx
        movl    $SPEC_CTRL_FEATURE_ENABLE_IBRS, %eax
        wrmsr
-       jmp     .Ldone_\@
 
 .Lskip_\@:
-       lfence
-.Ldone_\@:
 .endm
 
 .macro RESTORE_IBRS_CLOBBER save_reg:req
-       testl   $1, dynamic_ibrs
-       jz      .Lskip_\@
+       STATIC_JUMP_IF_FALSE .Lskip_\@, ibrs_key, def=0
 
        /* Set IBRS to the value saved in the save_reg */
        movl    $MSR_IA32_SPEC_CTRL, %ecx
        movl    $0, %edx
        movl    \save_reg, %eax
        wrmsr
-       jmp     .Ldone_\@
 
 .Lskip_\@:
-       lfence
-.Ldone_\@:
 .endm

Reply via email to