[PATCH v6 13/20] x86/split_lock: Enable split lock detection by default

From: Fenghua Yu
Date: Wed Apr 03 2019 - 17:30:54 EST


A split locked access locks bus and degrades overall memory access
performance. When split lock detection feature is enumerated, enable
the feature by default to find any split lock issue and then fix
the issue.

Signed-off-by: Fenghua Yu <fenghua.yu@xxxxxxxxx>
---
arch/x86/kernel/cpu/intel.c | 42 +++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)

diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 7f6943af35dc..ae3e327d5e35 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -31,6 +31,12 @@
#include <asm/apic.h>
#endif

+#define DISABLE_SPLIT_LOCK_DETECT 0
+#define ENABLE_SPLIT_LOCK_DETECT 1
+
+static DEFINE_MUTEX(split_lock_detect_mutex);
+static int split_lock_detect_val;
+
/*
* Just in case our CPU detection goes bad, or you have a weird system,
* allow a way to override the automatic disabling of MPX.
@@ -161,10 +167,45 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
return false;
}

+static u32 new_sp_test_ctl_val(u32 test_ctl_val)
+{
+ /* Change the split lock setting. */
+ if (READ_ONCE(split_lock_detect_val) == DISABLE_SPLIT_LOCK_DETECT)
+ test_ctl_val &= ~TEST_CTL_ENABLE_SPLIT_LOCK_DETECT;
+ else
+ test_ctl_val |= TEST_CTL_ENABLE_SPLIT_LOCK_DETECT;
+
+ return test_ctl_val;
+}
+
+static inline void show_split_lock_detection_info(void)
+{
+ if (READ_ONCE(split_lock_detect_val))
+ pr_info_once("x86/split_lock: split lock detection enabled\n");
+ else
+ pr_info_once("x86/split_lock: split lock detection disabled\n");
+}
+
+static void init_split_lock_detect(struct cpuinfo_x86 *c)
+{
+ if (cpu_has(c, X86_FEATURE_SPLIT_LOCK_DETECT)) {
+ u32 l, h;
+
+ mutex_lock(&split_lock_detect_mutex);
+ rdmsr(MSR_TEST_CTL, l, h);
+ l = new_sp_test_ctl_val(l);
+ wrmsr(MSR_TEST_CTL, l, h);
+ show_split_lock_detection_info();
+ mutex_unlock(&split_lock_detect_mutex);
+ }
+}
+
static void early_init_intel(struct cpuinfo_x86 *c)
{
u64 misc_enable;

+ init_split_lock_detect(c);
+
/* Unmask CPUID levels if masked: */
if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
if (msr_clear_bit(MSR_IA32_MISC_ENABLE,
@@ -1032,6 +1073,7 @@ cpu_dev_register(intel_cpu_dev);
static void __init set_split_lock_detect(void)
{
setup_force_cpu_cap(X86_FEATURE_SPLIT_LOCK_DETECT);
+ split_lock_detect_val = 1;
}

void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c)
--
2.19.1