77#include <linux/smp.h>
88#include <linux/sched.h>
99#include <linux/sched/clock.h>
10+ #include <linux/semaphore.h>
1011#include <linux/thread_info.h>
1112#include <linux/init.h>
1213#include <linux/uaccess.h>
14+ #include <linux/workqueue.h>
1315#include <linux/delay.h>
16+ #include <linux/cpuhotplug.h>
1417
1518#include <asm/cpufeature.h>
1619#include <asm/msr.h>
@@ -999,6 +1002,8 @@ static const struct {
9991002
10001003static struct ratelimit_state bld_ratelimit ;
10011004
1005+ static DEFINE_SEMAPHORE (buslock_sem );
1006+
10021007static inline bool match_option (const char * arg , int arglen , const char * opt )
10031008{
10041009 int len = strlen (opt ), ratelimit ;
@@ -1109,18 +1114,52 @@ static void split_lock_init(void)
11091114 split_lock_verify_msr (sld_state != sld_off );
11101115}
11111116
1117+ static void __split_lock_reenable (struct work_struct * work )
1118+ {
1119+ sld_update_msr (true);
1120+ up (& buslock_sem );
1121+ }
1122+
1123+ /*
1124+ * If a CPU goes offline with pending delayed work to re-enable split lock
1125+ * detection then the delayed work will be executed on some other CPU. That
1126+ * handles releasing the buslock_sem, but because it executes on a
1127+ * different CPU probably won't re-enable split lock detection. This is a
1128+ * problem on HT systems since the sibling CPU on the same core may then be
1129+ * left running with split lock detection disabled.
1130+ *
1131+ * Unconditionally re-enable detection here.
1132+ */
1133+ static int splitlock_cpu_offline (unsigned int cpu )
1134+ {
1135+ sld_update_msr (true);
1136+
1137+ return 0 ;
1138+ }
1139+
1140+ static DECLARE_DELAYED_WORK (split_lock_reenable , __split_lock_reenable ) ;
1141+
11121142static void split_lock_warn (unsigned long ip )
11131143{
1114- pr_warn_ratelimited ("#AC: %s/%d took a split_lock trap at address: 0x%lx\n" ,
1115- current -> comm , current -> pid , ip );
1144+ int cpu ;
11161145
1117- /*
1118- * Disable the split lock detection for this task so it can make
1119- * progress and set TIF_SLD so the detection is re-enabled via
1120- * switch_to_sld() when the task is scheduled out.
1121- */
1146+ if (!current -> reported_split_lock )
1147+ pr_warn_ratelimited ("#AC: %s/%d took a split_lock trap at address: 0x%lx\n" ,
1148+ current -> comm , current -> pid , ip );
1149+ current -> reported_split_lock = 1 ;
1150+
1151+ /* misery factor #1, sleep 10ms before trying to execute split lock */
1152+ if (msleep_interruptible (10 ) > 0 )
1153+ return ;
1154+ /* Misery factor #2, only allow one buslocked disabled core at a time */
1155+ if (down_interruptible (& buslock_sem ) == - EINTR )
1156+ return ;
1157+ cpu = get_cpu ();
1158+ schedule_delayed_work_on (cpu , & split_lock_reenable , 2 );
1159+
1160+ /* Disable split lock detection on this CPU to make progress */
11221161 sld_update_msr (false);
1123- set_tsk_thread_flag ( current , TIF_SLD );
1162+ put_cpu ( );
11241163}
11251164
11261165bool handle_guest_split_lock (unsigned long ip )
@@ -1193,18 +1232,6 @@ void handle_bus_lock(struct pt_regs *regs)
11931232 }
11941233}
11951234
1196- /*
1197- * This function is called only when switching between tasks with
1198- * different split-lock detection modes. It sets the MSR for the
1199- * mode of the new task. This is right most of the time, but since
1200- * the MSR is shared by hyperthreads on a physical core there can
1201- * be glitches when the two threads need different modes.
1202- */
1203- void switch_to_sld (unsigned long tifn )
1204- {
1205- sld_update_msr (!(tifn & _TIF_SLD ));
1206- }
1207-
12081235/*
12091236 * Bits in the IA32_CORE_CAPABILITIES are not architectural, so they should
12101237 * only be trusted if it is confirmed that a CPU model implements a
@@ -1230,6 +1257,7 @@ static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = {
12301257 X86_MATCH_INTEL_FAM6_MODEL (SAPPHIRERAPIDS_X , 1 ),
12311258 X86_MATCH_INTEL_FAM6_MODEL (ALDERLAKE , 1 ),
12321259 X86_MATCH_INTEL_FAM6_MODEL (ALDERLAKE_L , 1 ),
1260+ X86_MATCH_INTEL_FAM6_MODEL (RAPTORLAKE , 1 ),
12331261 {}
12341262};
12351263
@@ -1274,10 +1302,14 @@ static void sld_state_show(void)
12741302 pr_info ("disabled\n" );
12751303 break ;
12761304 case sld_warn :
1277- if (boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT ))
1305+ if (boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT )) {
12781306 pr_info ("#AC: crashing the kernel on kernel split_locks and warning on user-space split_locks\n" );
1279- else if (boot_cpu_has (X86_FEATURE_BUS_LOCK_DETECT ))
1307+ if (cpuhp_setup_state (CPUHP_AP_ONLINE_DYN ,
1308+ "x86/splitlock" , NULL , splitlock_cpu_offline ) < 0 )
1309+ pr_warn ("No splitlock CPU offline handler\n" );
1310+ } else if (boot_cpu_has (X86_FEATURE_BUS_LOCK_DETECT )) {
12801311 pr_info ("#DB: warning on user-space bus_locks\n" );
1312+ }
12811313 break ;
12821314 case sld_fatal :
12831315 if (boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT )) {
0 commit comments