7
7
#include <linux/smp.h>
8
8
#include <linux/sched.h>
9
9
#include <linux/sched/clock.h>
10
+ #include <linux/semaphore.h>
10
11
#include <linux/thread_info.h>
11
12
#include <linux/init.h>
12
13
#include <linux/uaccess.h>
14
+ #include <linux/workqueue.h>
13
15
#include <linux/delay.h>
16
+ #include <linux/cpuhotplug.h>
14
17
15
18
#include <asm/cpufeature.h>
16
19
#include <asm/msr.h>
@@ -999,6 +1002,8 @@ static const struct {
999
1002
1000
1003
static struct ratelimit_state bld_ratelimit ;
1001
1004
1005
+ static DEFINE_SEMAPHORE (buslock_sem );
1006
+
1002
1007
static inline bool match_option (const char * arg , int arglen , const char * opt )
1003
1008
{
1004
1009
int len = strlen (opt ), ratelimit ;
@@ -1109,18 +1114,52 @@ static void split_lock_init(void)
1109
1114
split_lock_verify_msr (sld_state != sld_off );
1110
1115
}
1111
1116
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
+
1112
1142
static void split_lock_warn (unsigned long ip )
1113
1143
{
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 ;
1116
1145
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 */
1122
1161
sld_update_msr (false);
1123
- set_tsk_thread_flag ( current , TIF_SLD );
1162
+ put_cpu ( );
1124
1163
}
1125
1164
1126
1165
bool handle_guest_split_lock (unsigned long ip )
@@ -1193,18 +1232,6 @@ void handle_bus_lock(struct pt_regs *regs)
1193
1232
}
1194
1233
}
1195
1234
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
-
1208
1235
/*
1209
1236
* Bits in the IA32_CORE_CAPABILITIES are not architectural, so they should
1210
1237
* 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 = {
1230
1257
X86_MATCH_INTEL_FAM6_MODEL (SAPPHIRERAPIDS_X , 1 ),
1231
1258
X86_MATCH_INTEL_FAM6_MODEL (ALDERLAKE , 1 ),
1232
1259
X86_MATCH_INTEL_FAM6_MODEL (ALDERLAKE_L , 1 ),
1260
+ X86_MATCH_INTEL_FAM6_MODEL (RAPTORLAKE , 1 ),
1233
1261
{}
1234
1262
};
1235
1263
@@ -1274,10 +1302,14 @@ static void sld_state_show(void)
1274
1302
pr_info ("disabled\n" );
1275
1303
break ;
1276
1304
case sld_warn :
1277
- if (boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT ))
1305
+ if (boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT )) {
1278
1306
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 )) {
1280
1311
pr_info ("#DB: warning on user-space bus_locks\n" );
1312
+ }
1281
1313
break ;
1282
1314
case sld_fatal :
1283
1315
if (boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT )) {
0 commit comments