@@ -1229,20 +1229,22 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
1229
1229
struct perf_event * event , bool add )
1230
1230
{
1231
1231
struct pmu * pmu = event -> pmu ;
1232
+
1232
1233
/*
1233
1234
* Make sure we get updated with the first PEBS
1234
1235
* event. It will trigger also during removal, but
1235
1236
* that does not hurt:
1236
1237
*/
1237
- bool update = cpuc -> n_pebs == 1 ;
1238
+ if (cpuc -> n_pebs == 1 )
1239
+ cpuc -> pebs_data_cfg = PEBS_UPDATE_DS_SW ;
1238
1240
1239
1241
if (needed_cb != pebs_needs_sched_cb (cpuc )) {
1240
1242
if (!needed_cb )
1241
1243
perf_sched_cb_inc (pmu );
1242
1244
else
1243
1245
perf_sched_cb_dec (pmu );
1244
1246
1245
- update = true ;
1247
+ cpuc -> pebs_data_cfg |= PEBS_UPDATE_DS_SW ;
1246
1248
}
1247
1249
1248
1250
/*
@@ -1252,24 +1254,13 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
1252
1254
if (x86_pmu .intel_cap .pebs_baseline && add ) {
1253
1255
u64 pebs_data_cfg ;
1254
1256
1255
- /* Clear pebs_data_cfg and pebs_record_size for first PEBS. */
1256
- if (cpuc -> n_pebs == 1 ) {
1257
- cpuc -> pebs_data_cfg = 0 ;
1258
- cpuc -> pebs_record_size = sizeof (struct pebs_basic );
1259
- }
1260
-
1261
1257
pebs_data_cfg = pebs_update_adaptive_cfg (event );
1262
-
1263
- /* Update pebs_record_size if new event requires more data. */
1264
- if (pebs_data_cfg & ~cpuc -> pebs_data_cfg ) {
1265
- cpuc -> pebs_data_cfg |= pebs_data_cfg ;
1266
- adaptive_pebs_record_size_update ();
1267
- update = true;
1268
- }
1258
+ /*
1259
+ * Be sure to update the thresholds when we change the record.
1260
+ */
1261
+ if (pebs_data_cfg & ~cpuc -> pebs_data_cfg )
1262
+ cpuc -> pebs_data_cfg |= pebs_data_cfg | PEBS_UPDATE_DS_SW ;
1269
1263
}
1270
-
1271
- if (update )
1272
- pebs_update_threshold (cpuc );
1273
1264
}
1274
1265
1275
1266
void intel_pmu_pebs_add (struct perf_event * event )
@@ -1326,9 +1317,17 @@ static void intel_pmu_pebs_via_pt_enable(struct perf_event *event)
1326
1317
wrmsrl (base + idx , value );
1327
1318
}
1328
1319
1320
+ static inline void intel_pmu_drain_large_pebs (struct cpu_hw_events * cpuc )
1321
+ {
1322
+ if (cpuc -> n_pebs == cpuc -> n_large_pebs &&
1323
+ cpuc -> n_pebs != cpuc -> n_pebs_via_pt )
1324
+ intel_pmu_drain_pebs_buffer ();
1325
+ }
1326
+
1329
1327
void intel_pmu_pebs_enable (struct perf_event * event )
1330
1328
{
1331
1329
struct cpu_hw_events * cpuc = this_cpu_ptr (& cpu_hw_events );
1330
+ u64 pebs_data_cfg = cpuc -> pebs_data_cfg & ~PEBS_UPDATE_DS_SW ;
1332
1331
struct hw_perf_event * hwc = & event -> hw ;
1333
1332
struct debug_store * ds = cpuc -> ds ;
1334
1333
unsigned int idx = hwc -> idx ;
@@ -1344,11 +1343,22 @@ void intel_pmu_pebs_enable(struct perf_event *event)
1344
1343
1345
1344
if (x86_pmu .intel_cap .pebs_baseline ) {
1346
1345
hwc -> config |= ICL_EVENTSEL_ADAPTIVE ;
1347
- if (cpuc -> pebs_data_cfg != cpuc -> active_pebs_data_cfg ) {
1348
- wrmsrl (MSR_PEBS_DATA_CFG , cpuc -> pebs_data_cfg );
1349
- cpuc -> active_pebs_data_cfg = cpuc -> pebs_data_cfg ;
1346
+ if (pebs_data_cfg != cpuc -> active_pebs_data_cfg ) {
1347
+ /*
1348
+ * drain_pebs() assumes uniform record size;
1349
+ * hence we need to drain when changing said
1350
+ * size.
1351
+ */
1352
+ intel_pmu_drain_large_pebs (cpuc );
1353
+ adaptive_pebs_record_size_update ();
1354
+ wrmsrl (MSR_PEBS_DATA_CFG , pebs_data_cfg );
1355
+ cpuc -> active_pebs_data_cfg = pebs_data_cfg ;
1350
1356
}
1351
1357
}
1358
+ if (cpuc -> pebs_data_cfg & PEBS_UPDATE_DS_SW ) {
1359
+ cpuc -> pebs_data_cfg = pebs_data_cfg ;
1360
+ pebs_update_threshold (cpuc );
1361
+ }
1352
1362
1353
1363
if (idx >= INTEL_PMC_IDX_FIXED ) {
1354
1364
if (x86_pmu .intel_cap .pebs_format < 5 )
@@ -1391,9 +1401,7 @@ void intel_pmu_pebs_disable(struct perf_event *event)
1391
1401
struct cpu_hw_events * cpuc = this_cpu_ptr (& cpu_hw_events );
1392
1402
struct hw_perf_event * hwc = & event -> hw ;
1393
1403
1394
- if (cpuc -> n_pebs == cpuc -> n_large_pebs &&
1395
- cpuc -> n_pebs != cpuc -> n_pebs_via_pt )
1396
- intel_pmu_drain_pebs_buffer ();
1404
+ intel_pmu_drain_large_pebs (cpuc );
1397
1405
1398
1406
cpuc -> pebs_enabled &= ~(1ULL << hwc -> idx );
1399
1407
0 commit comments