[PATCH v5 3/9] x86/split_lock: Re-define the kernel param option for split_lock_detect

From: Xiaoyao Li
Date: Sun Mar 15 2020 - 01:23:10 EST


Change sld_off to sld_disable, which means disabling feature split lock
detection and it cannot be used in kernel nor can kvm expose it guest.
Of course, the X86_FEATURE_SPLIT_LOCK_DETECT is not set.

Add a new optioin sld_kvm_only, which means kernel turns split lock
detection off, but kvm can expose it to guest.

Signed-off-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx>
---
.../admin-guide/kernel-parameters.txt | 5 ++++-
arch/x86/kernel/cpu/intel.c | 22 ++++++++++++++-----
2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 1ee2d1e6d89a..2b922061ff08 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4666,7 +4666,10 @@
instructions that access data across cache line
boundaries will result in an alignment check exception.

- off - not enabled
+ disable - disabled, neither kernel nor kvm can use it.
+
+ kvm_only - off in kernel but kvm can expose it to
+ guest for debug/testing scenario.

warn - the kernel will emit rate limited warnings
about applications triggering the #AC
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 4b3245035b5a..3eeab717a0d0 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -35,7 +35,8 @@

enum split_lock_detect_state {
sld_not_exist = 0,
- sld_off,
+ sld_disable,
+ sld_kvm_only,
sld_warn,
sld_fatal,
};
@@ -973,7 +974,8 @@ static const struct {
const char *option;
enum split_lock_detect_state state;
} sld_options[] __initconst = {
- { "off", sld_off },
+ { "disable", sld_disable },
+ { "kvm_only", sld_kvm_only },
{ "warn", sld_warn },
{ "fatal", sld_fatal },
};
@@ -1004,10 +1006,14 @@ static void __init split_lock_setup(void)
}

switch (sld_state) {
- case sld_off:
+ case sld_disable:
pr_info("disabled\n");
break;

+ case sld_kvm_only:
+ pr_info("off in kernel, but kvm can expose it to guest\n");
+ break;
+
case sld_warn:
pr_info("warning about user-space split_locks\n");
break;
@@ -1062,7 +1068,13 @@ static void split_lock_init(struct cpuinfo_x86 *c)
test_ctrl_val = val;

switch (sld_state) {
- case sld_off:
+ case sld_disable:
+ if (wrmsrl_safe(MSR_TEST_CTRL, test_ctrl_val & ~MSR_TEST_CTRL_SPLIT_LOCK_DETECT))
+ goto msr_broken;
+ return;
+ case sld_kvm_only:
+ if (wrmsrl_safe(MSR_TEST_CTRL, test_ctrl_val | MSR_TEST_CTRL_SPLIT_LOCK_DETECT))
+ goto msr_broken;
if (wrmsrl_safe(MSR_TEST_CTRL, test_ctrl_val & ~MSR_TEST_CTRL_SPLIT_LOCK_DETECT))
goto msr_broken;
break;
@@ -1087,7 +1099,7 @@ static void split_lock_init(struct cpuinfo_x86 *c)
* funny things and you get to keep whatever pieces.
*/
pr_warn_once("MSR fail -- disabled\n");
- sld_state = sld_off;
+ sld_state = sld_disable;
}

bool handle_user_split_lock(struct pt_regs *regs, long error_code)
--
2.20.1