]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
x86/spec: Add 'lfence_enabled' in sysfs
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Mon, 29 Jan 2018 18:51:48 +0000 (13:51 -0500)
committerJack Vogel <jack.vogel@oracle.com>
Thu, 1 Feb 2018 22:19:52 +0000 (14:19 -0800)
To toggle during runtime whether the lfence fallback should be used.
If IBRS is enabled warnings will be returned.

OraBug: 27472666
Reviewed-by: John Haxby <john.haxby@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
arch/x86/include/asm/spec_ctrl.h
arch/x86/kernel/cpu/spec_ctrl.c

index 891a569b55cb6053f5d9ca17092fea153d6ae08d..ce23ed0fb50243f2c61c83af1335206c4130eb55 100644 (file)
@@ -262,9 +262,17 @@ static inline void clear_ibrs_disabled(void)
        set_ibrs_inuse();
 }
 
+extern u32 sysctl_lfence_enabled;
 static inline void set_lfence_disabled(void)
 {
        use_ibrs |= SPEC_CTRL_LFENCE_OFF;
+       sysctl_lfence_enabled = 0;
+}
+
+static inline void clear_lfence_disabled(void)
+{
+       use_ibrs &= ~SPEC_CTRL_LFENCE_OFF;
+       sysctl_lfence_enabled = 1;
 }
 
 /* indicate usage of IBPB to control execution speculation */
index e74e500eb45e63198684dde86e8054d8b47c63c0..c27c31cea4f0b6adc9fe0fd94c7e3585b0085151 100644 (file)
@@ -15,6 +15,8 @@
  */
 
 u32 sysctl_ibrs_enabled = 0, sysctl_ibpb_enabled = 0;
+/* By default it is enabled. */
+u32 sysctl_lfence_enabled = 1;
 EXPORT_SYMBOL(sysctl_ibrs_enabled);
 EXPORT_SYMBOL(sysctl_ibpb_enabled);
 
@@ -142,12 +144,68 @@ static const struct file_operations fops_ibpb_enabled = {
        .llseek = default_llseek,
 };
 
+static ssize_t lfence_enabled_read(struct file *file, char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       uint32_t dummy = 0;
+
+       if (ibrs_disabled)
+               return __enabled_read(file, user_buf, count, ppos, &sysctl_lfence_enabled);
+
+       return __enabled_read(file, user_buf, count, ppos, &dummy);
+}
+
+static ssize_t lfence_enabled_write(struct file *file,
+                                 const char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       char buf[32];
+       ssize_t len;
+       unsigned int enable;
+
+       /* You have to disable IBRS first. */
+       if (ibrs_inuse) {
+               pr_warn("IBRS is enabled. Ignoring request to change lfence_enabled state.");
+               return -EINVAL;
+       }
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (kstrtouint(buf, 0, &enable))
+               return -EINVAL;
+
+       /* Only 0 and 1 are allowed */
+       if (enable > 1)
+               return -EINVAL;
+
+       mutex_lock(&spec_ctrl_mutex);
+
+       if (!enable)
+               set_lfence_disabled();
+       else
+               clear_lfence_disabled();
+
+       mutex_unlock(&spec_ctrl_mutex);
+       return count;
+}
+
+static const struct file_operations fops_lfence_enabled = {
+       .read = lfence_enabled_read,
+       .write = lfence_enabled_write,
+       .llseek = default_llseek,
+};
+
 static int __init debugfs_spec_ctrl(void)
 {
         debugfs_create_file("ibrs_enabled", S_IRUSR | S_IWUSR,
                             arch_debugfs_dir, NULL, &fops_ibrs_enabled);
        debugfs_create_file("ibpb_enabled", S_IRUSR | S_IWUSR,
                            arch_debugfs_dir, NULL, &fops_ibpb_enabled);
+       debugfs_create_file("lfence_enabled", S_IRUSR | S_IWUSR,
+                           arch_debugfs_dir, NULL, &fops_lfence_enabled);
         return 0;
 }
 late_initcall(debugfs_spec_ctrl);