When the host enables split lock detection feature, the split lock from guests (normal or TDX) triggers #AC. The #AC caused by split lock access within a normal guest triggers a VM Exit and is handled in the host. The #AC caused by split lock access within a TDX guest does not trigger a VM Exit and instead it's delivered to the guest self. The default "warning" mode of handling split lock depends on being able to temporarily disable detection to recover from the split lock event. But the MSR that disables detection is not accessible to a guest. This means that TDX guests today can not disable the feature or use the "warning" mode (which is the default). But, they can use the "fatal" mode. Force TDX guests to use the "fatal" mode. Signed-off-by: Xiaoyao Li --- arch/x86/kernel/cpu/bus_lock.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/bus_lock.c b/arch/x86/kernel/cpu/bus_lock.c index 981f8b1f0792..f278e4ea3dd4 100644 --- a/arch/x86/kernel/cpu/bus_lock.c +++ b/arch/x86/kernel/cpu/bus_lock.c @@ -315,9 +315,24 @@ void bus_lock_init(void) wrmsrq(MSR_IA32_DEBUGCTLMSR, val); } +static bool split_lock_fatal(void) +{ + if (sld_state == sld_fatal) + return true; + + /* + * TDX guests can not disable split lock detection. + * Force them into the fatal behavior. + */ + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return true; + + return false; +} + bool handle_user_split_lock(struct pt_regs *regs, long error_code) { - if ((regs->flags & X86_EFLAGS_AC) || sld_state == sld_fatal) + if ((regs->flags & X86_EFLAGS_AC) || split_lock_fatal()) return false; split_lock_warn(regs->ip); return true; -- 2.43.0 X86_FEATURE_HYPERVISOR and X86_FEATURE_BUS_LOCK_DETECT are always enumerated in a TDX guest because the corresponding CPUID values are fixed to 1 by the TDX module. Similar to a normal guest, a TDX guest never enumerates X86_FEATURE_SPLIT_LOCK_DETECT. When "split_lock_detect=off", the TDX guest kernel log shows: x86/split lock detection: disabled and with other settings, it shows: x86/split lock detection: #DB: ... However, if the host enables split lock detection, a TDX guest receives #AC regardless of its own "split_lock_detect" configuration. The actual behavior does not match what the kernel log claims. Call out the possible #AC behavior on TDX and highlight that this behavior depends on the host's enabling of split lock detection. Signed-off-by: Xiaoyao Li --- arch/x86/kernel/cpu/bus_lock.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/cpu/bus_lock.c b/arch/x86/kernel/cpu/bus_lock.c index f278e4ea3dd4..18695214d214 100644 --- a/arch/x86/kernel/cpu/bus_lock.c +++ b/arch/x86/kernel/cpu/bus_lock.c @@ -437,6 +437,9 @@ static void sld_state_show(void) pr_info("#DB: setting system wide bus lock rate limit to %u/sec\n", bld_ratelimit.burst); break; } + + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + pr_info("tdx: #AC depends on host configuration: crashing the kernel on kernel split_locks and sending SIGBUS on user-space split_locks\n"); } void __init sld_setup(struct cpuinfo_x86 *c) -- 2.43.0