Merge tag 'x86_microcode_for_v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / arch / x86 / kernel / cpu / intel.c
index b6997eb..291d416 100644 (file)
@@ -1176,8 +1176,32 @@ static const struct {
 
 static struct ratelimit_state bld_ratelimit;
 
+static unsigned int sysctl_sld_mitigate = 1;
 static DEFINE_SEMAPHORE(buslock_sem);
 
+#ifdef CONFIG_PROC_SYSCTL
+static struct ctl_table sld_sysctls[] = {
+       {
+               .procname       = "split_lock_mitigate",
+               .data           = &sysctl_sld_mitigate,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_douintvec_minmax,
+               .extra1         = SYSCTL_ZERO,
+               .extra2         = SYSCTL_ONE,
+       },
+       {}
+};
+
+static int __init sld_mitigate_sysctl_init(void)
+{
+       register_sysctl_init("kernel", sld_sysctls);
+       return 0;
+}
+
+late_initcall(sld_mitigate_sysctl_init);
+#endif
+
 static inline bool match_option(const char *arg, int arglen, const char *opt)
 {
        int len = strlen(opt), ratelimit;
@@ -1288,12 +1312,20 @@ static void split_lock_init(void)
                split_lock_verify_msr(sld_state != sld_off);
 }
 
-static void __split_lock_reenable(struct work_struct *work)
+static void __split_lock_reenable_unlock(struct work_struct *work)
 {
        sld_update_msr(true);
        up(&buslock_sem);
 }
 
+static DECLARE_DELAYED_WORK(sl_reenable_unlock, __split_lock_reenable_unlock);
+
+static void __split_lock_reenable(struct work_struct *work)
+{
+       sld_update_msr(true);
+}
+static DECLARE_DELAYED_WORK(sl_reenable, __split_lock_reenable);
+
 /*
  * If a CPU goes offline with pending delayed work to re-enable split lock
  * detection then the delayed work will be executed on some other CPU. That
@@ -1311,10 +1343,9 @@ static int splitlock_cpu_offline(unsigned int cpu)
        return 0;
 }
 
-static DECLARE_DELAYED_WORK(split_lock_reenable, __split_lock_reenable);
-
 static void split_lock_warn(unsigned long ip)
 {
+       struct delayed_work *work;
        int cpu;
 
        if (!current->reported_split_lock)
@@ -1322,14 +1353,26 @@ static void split_lock_warn(unsigned long ip)
                                    current->comm, current->pid, ip);
        current->reported_split_lock = 1;
 
-       /* misery factor #1, sleep 10ms before trying to execute split lock */
-       if (msleep_interruptible(10) > 0)
-               return;
-       /* Misery factor #2, only allow one buslocked disabled core at a time */
-       if (down_interruptible(&buslock_sem) == -EINTR)
-               return;
+       if (sysctl_sld_mitigate) {
+               /*
+                * misery factor #1:
+                * sleep 10ms before trying to execute split lock.
+                */
+               if (msleep_interruptible(10) > 0)
+                       return;
+               /*
+                * Misery factor #2:
+                * only allow one buslocked disabled core at a time.
+                */
+               if (down_interruptible(&buslock_sem) == -EINTR)
+                       return;
+               work = &sl_reenable_unlock;
+       } else {
+               work = &sl_reenable;
+       }
+
        cpu = get_cpu();
-       schedule_delayed_work_on(cpu, &split_lock_reenable, 2);
+       schedule_delayed_work_on(cpu, work, 2);
 
        /* Disable split lock detection on this CPU to make progress */
        sld_update_msr(false);