]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
*Scaffolding* x86/spec_ctrl: Add sysctl knobs to enable/disable SPEC_CTRL feature
authorTim Chen <tim.c.chen@linux.intel.com>
Mon, 18 Dec 2017 18:54:59 +0000 (10:54 -0800)
committerKirtikar Kashyap <kirtikar.kashyap@oracle.com>
Fri, 12 Jan 2018 18:19:55 +0000 (10:19 -0800)
1. At boot time
        noibrs kernel boot parameter will disable IBRS usage
        noibpb kernel boot parameter will disable IBPB usage

Otherwise if the above parameters are not specified, the system
will enable ibrs and ibpb usage if the cpu supports it.

Orabug: 27344012
CVE: CVE-2017-5715

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
[*Scaffolding*:This backport lacks a lot. It is only put it on so that the
 later patches compiled _and_ can be tested to run. It is meant to be removed
 once the full set of patches are all good. Aka scaffolding.]

Reviewed-by: John Haxby <john.haxby@oracle.com>
Signed-off-by: Kirtikar Kashyap <kirtikar.kashyap@oracle.com>
Documentation/kernel-parameters.txt
arch/x86/include/asm/spec_ctrl.h
arch/x86/kernel/cpu/intel.c
include/linux/smp.h
kernel/smp.c

index 198bcf10d93b48546bd130cc21fe0c2b6d27f768..ad6bb62c209e5288144ee61e6bbd7b3b63044a22 100644 (file)
@@ -2354,6 +2354,16 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        noexec=on: enable non-executable mappings (default)
                        noexec=off: disable non-executable mappings
 
+       noibrs          [X86]
+                       Don't use indirect branch restricted speculation (IBRS)
+                       feature when running in secure environment,
+                       to avoid performance overhead.
+
+       noibpb          [X86]
+                       Don't use indirect branch prediction barrier (IBPB)
+                       feature when running in secure environment,
+                       to avoid performance overhead.
+
        nosmap          [X86]
                        Disable SMAP (Supervisor Mode Access Prevention)
                        even if it is supported by processor.
index 3080f33fbd08259a26bd482f31086eb4c932a50d..1d313ff9799bb7e882bb28335ae0cb573fab4b7e 100644 (file)
@@ -8,6 +8,8 @@
 
 #ifdef __ASSEMBLY__
 
+.extern use_ibrs
+
 #define __ASM_ENABLE_IBRS                      \
        pushq %rax;                             \
        pushq %rcx;                             \
index 4257d6a7db7d81c474124709bdfca6fb13f2f0b4..bcb5303de9026377a8c92a6dcabe650c93dbe021 100644 (file)
@@ -494,8 +494,10 @@ static void init_intel(struct cpuinfo_x86 *c)
                }
        }
 
-       if (boot_cpu_has(X86_FEATURE_SPEC_CTRL))
+       if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
                printk_once(KERN_INFO "FEATURE SPEC_CTRL Present\n");
+               set_ibrs_supported();
+       }
        else
                printk_once(KERN_INFO "FEATURE SPEC_CTRL Not Present\n");
 }
index c4414074bd88e2ae1b042cb477440f54b2f241dd..c340e38a6656283cbf3f44ac4a81fdfad6fcfc0f 100644 (file)
@@ -50,6 +50,92 @@ void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
 
 int smp_call_function_single_async(int cpu, struct call_single_data *csd);
 
+#ifdef CONFIG_X86
+/* indicate usage of IBRS to control execution speculation */
+extern int use_ibrs;
+extern u32 sysctl_ibrs_enabled;
+#define ibrs_supported         (use_ibrs & 0x2)
+#define ibrs_disabled          (use_ibrs & 0x4)
+static inline void set_ibrs_inuse(void)
+{
+       if (ibrs_supported)
+               use_ibrs |= 0x1;
+}
+static inline void clear_ibrs_inuse(void)
+{
+       use_ibrs &= ~0x1;
+}
+static inline int check_ibrs_inuse(void)
+{
+       if (use_ibrs & 0x1)
+               return 1;
+       else
+               /* rmb to prevent wrong speculation for security */
+               rmb();
+       return 0;
+}
+static inline void set_ibrs_supported(void)
+{
+       use_ibrs |= 0x2;
+       if (!ibrs_disabled)
+               set_ibrs_inuse();
+}
+static inline void set_ibrs_disabled(void)
+{
+       use_ibrs |= 0x4;
+       if (check_ibrs_inuse())
+               clear_ibrs_inuse();
+}
+static inline void clear_ibrs_disabled(void)
+{
+       use_ibrs &= ~0x4;
+       set_ibrs_inuse();
+}
+#define ibrs_inuse             (check_ibrs_inuse())
+
+/* indicate usage of IBPB to control execution speculation */
+extern int use_ibpb;
+extern u32 sysctl_ibpb_enabled;
+#define ibpb_supported         (use_ibpb & 0x2)
+#define ibpb_disabled          (use_ibpb & 0x4)
+static inline void set_ibpb_inuse(void)
+{
+       if (ibpb_supported)
+               use_ibpb |= 0x1;
+}
+static inline void clear_ibpb_inuse(void)
+{
+       use_ibpb &= ~0x1;
+}
+static inline int check_ibpb_inuse(void)
+{
+       if (use_ibpb & 0x1)
+               return 1;
+       else
+               /* rmb to prevent wrong speculation for security */
+               rmb();
+       return 0;
+}
+static inline void set_ibpb_supported(void)
+{
+       use_ibpb |= 0x2;
+       if (!ibpb_disabled)
+               set_ibpb_inuse();
+}
+static inline void set_ibpb_disabled(void)
+{
+       use_ibpb |= 0x4;
+       if (check_ibpb_inuse())
+               clear_ibpb_inuse();
+}
+static inline void clear_ibpb_disabled(void)
+{
+       use_ibpb &= ~0x4;
+       set_ibpb_inuse();
+}
+#define ibpb_inuse             (check_ibpb_inuse())
+#endif
+
 #ifdef CONFIG_SMP
 
 #include <linux/preempt.h>
index 07854477c16447ff87df874b4f117bcafadd4f33..8db57e98cd2d0817ce112be82705ba45516dcf41 100644 (file)
@@ -499,6 +499,24 @@ EXPORT_SYMBOL(smp_call_function);
 unsigned int setup_max_cpus = NR_CPUS;
 EXPORT_SYMBOL(setup_max_cpus);
 
+/*
+ * use IBRS
+ * bit 0 = indicate if ibrs is currently in use
+ * bit 1 = indicate if system supports ibrs
+ * bit 2 = indicate if admin disables ibrs
+*/
+
+int use_ibrs;
+EXPORT_SYMBOL(use_ibrs);
+
+/*
+ * use IBRS
+ * bit 0 = indicate if ibpb is currently in use
+ * bit 1 = indicate if system supports ibpb
+ * bit 2 = indicate if admin disables ibpb
+*/
+int use_ibpb;
+EXPORT_SYMBOL(use_ibpb);
 
 /*
  * Setup routine for controlling SMP activation
@@ -523,6 +541,25 @@ static int __init nosmp(char *str)
 
 early_param("nosmp", nosmp);
 
+static int __init noibrs(char *str)
+{
+       set_ibrs_disabled();
+
+       return 0;
+}
+
+early_param("noibrs", noibrs);
+
+static int __init noibpb(char *str)
+{
+       set_ibpb_disabled();
+
+       return 0;
+}
+
+early_param("noibpb", noibpb);
+
+
 /* this is hard limit */
 static int __init nrcpus(char *str)
 {