Merge tag 'ux500-dts-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[linux-2.6-microblaze.git] / arch / x86 / kernel / cpu / intel.c
index 9a26e97..a19a680 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/elf.h>
 #include <asm/cpu_device_id.h>
 #include <asm/cmdline.h>
+#include <asm/traps.h>
 
 #ifdef CONFIG_X86_64
 #include <linux/topology.h>
@@ -1066,13 +1067,10 @@ static void split_lock_init(void)
        split_lock_verify_msr(sld_state != sld_off);
 }
 
-bool handle_user_split_lock(struct pt_regs *regs, long error_code)
+static void split_lock_warn(unsigned long ip)
 {
-       if ((regs->flags & X86_EFLAGS_AC) || sld_state == sld_fatal)
-               return false;
-
        pr_warn_ratelimited("#AC: %s/%d took a split_lock trap at address: 0x%lx\n",
-                           current->comm, current->pid, regs->ip);
+                           current->comm, current->pid, ip);
 
        /*
         * Disable the split lock detection for this task so it can make
@@ -1081,6 +1079,31 @@ bool handle_user_split_lock(struct pt_regs *regs, long error_code)
         */
        sld_update_msr(false);
        set_tsk_thread_flag(current, TIF_SLD);
+}
+
+bool handle_guest_split_lock(unsigned long ip)
+{
+       if (sld_state == sld_warn) {
+               split_lock_warn(ip);
+               return true;
+       }
+
+       pr_warn_once("#AC: %s/%d %s split_lock trap at address: 0x%lx\n",
+                    current->comm, current->pid,
+                    sld_state == sld_fatal ? "fatal" : "bogus", ip);
+
+       current->thread.error_code = 0;
+       current->thread.trap_nr = X86_TRAP_AC;
+       force_sig_fault(SIGBUS, BUS_ADRALN, NULL);
+       return false;
+}
+EXPORT_SYMBOL_GPL(handle_guest_split_lock);
+
+bool handle_user_split_lock(struct pt_regs *regs, long error_code)
+{
+       if ((regs->flags & X86_EFLAGS_AC) || sld_state == sld_fatal)
+               return false;
+       split_lock_warn(regs->ip);
        return true;
 }
 
@@ -1096,35 +1119,53 @@ void switch_to_sld(unsigned long tifn)
        sld_update_msr(!(tifn & _TIF_SLD));
 }
 
-#define SPLIT_LOCK_CPU(model) {X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY}
-
 /*
- * The following processors have the split lock detection feature. But
- * since they don't have the IA32_CORE_CAPABILITIES MSR, the feature cannot
- * be enumerated. Enable it by family and model matching on these
- * processors.
+ * Bits in the IA32_CORE_CAPABILITIES are not architectural, so they should
+ * only be trusted if it is confirmed that a CPU model implements a
+ * specific feature at a particular bit position.
+ *
+ * The possible driver data field values:
+ *
+ * - 0: CPU models that are known to have the per-core split-lock detection
+ *     feature even though they do not enumerate IA32_CORE_CAPABILITIES.
+ *
+ * - 1: CPU models which may enumerate IA32_CORE_CAPABILITIES and if so use
+ *      bit 5 to enumerate the per-core split-lock detection feature.
  */
 static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = {
-       SPLIT_LOCK_CPU(INTEL_FAM6_ICELAKE_X),
-       SPLIT_LOCK_CPU(INTEL_FAM6_ICELAKE_L),
+       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,           0),
+       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L,           0),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT,        1),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,      1),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L,      1),
        {}
 };
 
 void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c)
 {
-       u64 ia32_core_caps = 0;
+       const struct x86_cpu_id *m;
+       u64 ia32_core_caps;
 
-       if (c->x86_vendor != X86_VENDOR_INTEL)
+       if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
                return;
-       if (cpu_has(c, X86_FEATURE_CORE_CAPABILITIES)) {
-               /* Enumerate features reported in IA32_CORE_CAPABILITIES MSR. */
+
+       m = x86_match_cpu(split_lock_cpu_ids);
+       if (!m)
+               return;
+
+       switch (m->driver_data) {
+       case 0:
+               break;
+       case 1:
+               if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES))
+                       return;
                rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps);
-       } else if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
-               /* Enumerate split lock detection by family and model. */
-               if (x86_match_cpu(split_lock_cpu_ids))
-                       ia32_core_caps |= MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT;
+               if (!(ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT))
+                       return;
+               break;
+       default:
+               return;
        }
 
-       if (ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT)
-               split_lock_setup();
+       split_lock_setup();
 }