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