@@ -1145,11 +1145,13 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1145
1145
return 0 ;
1146
1146
}
1147
1147
1148
- static u64 intel_pt_switch_ip (struct machine * machine , u64 * ptss_ip )
1148
+ static u64 intel_pt_switch_ip (struct intel_pt * pt , u64 * ptss_ip )
1149
1149
{
1150
+ struct machine * machine = pt -> machine ;
1150
1151
struct map * map ;
1151
1152
struct symbol * sym , * start ;
1152
1153
u64 ip , switch_ip = 0 ;
1154
+ const char * ptss ;
1153
1155
1154
1156
if (ptss_ip )
1155
1157
* ptss_ip = 0 ;
@@ -1177,8 +1179,13 @@ static u64 intel_pt_switch_ip(struct machine *machine, u64 *ptss_ip)
1177
1179
if (!switch_ip || !ptss_ip )
1178
1180
return 0 ;
1179
1181
1182
+ if (pt -> have_sched_switch == 1 )
1183
+ ptss = "perf_trace_sched_switch" ;
1184
+ else
1185
+ ptss = "__perf_event_task_sched_out" ;
1186
+
1180
1187
for (sym = start ; sym ; sym = dso__next_symbol (sym )) {
1181
- if (!strcmp (sym -> name , "perf_trace_sched_switch" )) {
1188
+ if (!strcmp (sym -> name , ptss )) {
1182
1189
ip = map -> unmap_ip (map , sym -> start );
1183
1190
if (ip >= map -> start && ip < map -> end ) {
1184
1191
* ptss_ip = ip ;
@@ -1198,11 +1205,11 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1198
1205
1199
1206
if (!pt -> kernel_start ) {
1200
1207
pt -> kernel_start = machine__kernel_start (pt -> machine );
1201
- if (pt -> per_cpu_mmaps && pt -> have_sched_switch &&
1208
+ if (pt -> per_cpu_mmaps &&
1209
+ (pt -> have_sched_switch == 1 || pt -> have_sched_switch == 3 ) &&
1202
1210
!pt -> timeless_decoding && intel_pt_tracing_kernel (pt ) &&
1203
1211
!pt -> sampling_mode ) {
1204
- pt -> switch_ip = intel_pt_switch_ip (pt -> machine ,
1205
- & pt -> ptss_ip );
1212
+ pt -> switch_ip = intel_pt_switch_ip (pt , & pt -> ptss_ip );
1206
1213
if (pt -> switch_ip ) {
1207
1214
intel_pt_log ("switch_ip: %" PRIx64 " ptss_ip: %" PRIx64 "\n" ,
1208
1215
pt -> switch_ip , pt -> ptss_ip );
@@ -1387,31 +1394,18 @@ static struct intel_pt_queue *intel_pt_cpu_to_ptq(struct intel_pt *pt, int cpu)
1387
1394
return NULL ;
1388
1395
}
1389
1396
1390
- static int intel_pt_process_switch (struct intel_pt * pt ,
1391
- struct perf_sample * sample )
1397
+ static int intel_pt_sync_switch (struct intel_pt * pt , int cpu , pid_t tid ,
1398
+ u64 timestamp )
1392
1399
{
1393
1400
struct intel_pt_queue * ptq ;
1394
- struct perf_evsel * evsel ;
1395
- pid_t tid ;
1396
- int cpu , err ;
1397
-
1398
- evsel = perf_evlist__id2evsel (pt -> session -> evlist , sample -> id );
1399
- if (evsel != pt -> switch_evsel )
1400
- return 0 ;
1401
-
1402
- tid = perf_evsel__intval (evsel , sample , "next_pid" );
1403
- cpu = sample -> cpu ;
1404
-
1405
- intel_pt_log ("sched_switch: cpu %d tid %d time %" PRIu64 " tsc %#" PRIx64 "\n" ,
1406
- cpu , tid , sample -> time , perf_time_to_tsc (sample -> time ,
1407
- & pt -> tc ));
1401
+ int err ;
1408
1402
1409
1403
if (!pt -> sync_switch )
1410
- goto out ;
1404
+ return 1 ;
1411
1405
1412
1406
ptq = intel_pt_cpu_to_ptq (pt , cpu );
1413
1407
if (!ptq )
1414
- goto out ;
1408
+ return 1 ;
1415
1409
1416
1410
switch (ptq -> switch_state ) {
1417
1411
case INTEL_PT_SS_NOT_TRACING :
@@ -1424,7 +1418,7 @@ static int intel_pt_process_switch(struct intel_pt *pt,
1424
1418
return 0 ;
1425
1419
case INTEL_PT_SS_EXPECTING_SWITCH_EVENT :
1426
1420
if (!ptq -> on_heap ) {
1427
- ptq -> timestamp = perf_time_to_tsc (sample -> time ,
1421
+ ptq -> timestamp = perf_time_to_tsc (timestamp ,
1428
1422
& pt -> tc );
1429
1423
err = auxtrace_heap__add (& pt -> heap , ptq -> queue_nr ,
1430
1424
ptq -> timestamp );
@@ -1441,10 +1435,76 @@ static int intel_pt_process_switch(struct intel_pt *pt,
1441
1435
default :
1442
1436
break ;
1443
1437
}
1444
- out :
1438
+
1439
+ return 1 ;
1440
+ }
1441
+
1442
+ static int intel_pt_process_switch (struct intel_pt * pt ,
1443
+ struct perf_sample * sample )
1444
+ {
1445
+ struct perf_evsel * evsel ;
1446
+ pid_t tid ;
1447
+ int cpu , ret ;
1448
+
1449
+ evsel = perf_evlist__id2evsel (pt -> session -> evlist , sample -> id );
1450
+ if (evsel != pt -> switch_evsel )
1451
+ return 0 ;
1452
+
1453
+ tid = perf_evsel__intval (evsel , sample , "next_pid" );
1454
+ cpu = sample -> cpu ;
1455
+
1456
+ intel_pt_log ("sched_switch: cpu %d tid %d time %" PRIu64 " tsc %#" PRIx64 "\n" ,
1457
+ cpu , tid , sample -> time , perf_time_to_tsc (sample -> time ,
1458
+ & pt -> tc ));
1459
+
1460
+ ret = intel_pt_sync_switch (pt , cpu , tid , sample -> time );
1461
+ if (ret <= 0 )
1462
+ return ret ;
1463
+
1445
1464
return machine__set_current_tid (pt -> machine , cpu , -1 , tid );
1446
1465
}
1447
1466
1467
+ static int intel_pt_context_switch (struct intel_pt * pt , union perf_event * event ,
1468
+ struct perf_sample * sample )
1469
+ {
1470
+ bool out = event -> header .misc & PERF_RECORD_MISC_SWITCH_OUT ;
1471
+ pid_t pid , tid ;
1472
+ int cpu , ret ;
1473
+
1474
+ cpu = sample -> cpu ;
1475
+
1476
+ if (pt -> have_sched_switch == 3 ) {
1477
+ if (!out )
1478
+ return 0 ;
1479
+ if (event -> header .type != PERF_RECORD_SWITCH_CPU_WIDE ) {
1480
+ pr_err ("Expecting CPU-wide context switch event\n" );
1481
+ return - EINVAL ;
1482
+ }
1483
+ pid = event -> context_switch .next_prev_pid ;
1484
+ tid = event -> context_switch .next_prev_tid ;
1485
+ } else {
1486
+ if (out )
1487
+ return 0 ;
1488
+ pid = sample -> pid ;
1489
+ tid = sample -> tid ;
1490
+ }
1491
+
1492
+ if (tid == -1 ) {
1493
+ pr_err ("context_switch event has no tid\n" );
1494
+ return - EINVAL ;
1495
+ }
1496
+
1497
+ intel_pt_log ("context_switch: cpu %d pid %d tid %d time %" PRIu64 " tsc %#" PRIx64 "\n" ,
1498
+ cpu , pid , tid , sample -> time , perf_time_to_tsc (sample -> time ,
1499
+ & pt -> tc ));
1500
+
1501
+ ret = intel_pt_sync_switch (pt , cpu , tid , sample -> time );
1502
+ if (ret <= 0 )
1503
+ return ret ;
1504
+
1505
+ return machine__set_current_tid (pt -> machine , cpu , pid , tid );
1506
+ }
1507
+
1448
1508
static int intel_pt_process_itrace_start (struct intel_pt * pt ,
1449
1509
union perf_event * event ,
1450
1510
struct perf_sample * sample )
@@ -1515,6 +1575,9 @@ static int intel_pt_process_event(struct perf_session *session,
1515
1575
err = intel_pt_process_switch (pt , sample );
1516
1576
else if (event -> header .type == PERF_RECORD_ITRACE_START )
1517
1577
err = intel_pt_process_itrace_start (pt , event , sample );
1578
+ else if (event -> header .type == PERF_RECORD_SWITCH ||
1579
+ event -> header .type == PERF_RECORD_SWITCH_CPU_WIDE )
1580
+ err = intel_pt_context_switch (pt , event , sample );
1518
1581
1519
1582
intel_pt_log ("event %s (%u): cpu %d time %" PRIu64 " tsc %#" PRIx64 "\n" ,
1520
1583
perf_event__name (event -> header .type ), event -> header .type ,
@@ -1777,6 +1840,18 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist)
1777
1840
return NULL ;
1778
1841
}
1779
1842
1843
+ static bool intel_pt_find_switch (struct perf_evlist * evlist )
1844
+ {
1845
+ struct perf_evsel * evsel ;
1846
+
1847
+ evlist__for_each (evlist , evsel ) {
1848
+ if (evsel -> attr .context_switch )
1849
+ return true;
1850
+ }
1851
+
1852
+ return false;
1853
+ }
1854
+
1780
1855
static const char * const intel_pt_info_fmts [] = {
1781
1856
[INTEL_PT_PMU_TYPE ] = " PMU Type %" PRId64 "\n" ,
1782
1857
[INTEL_PT_TIME_SHIFT ] = " Time Shift %" PRIu64 "\n" ,
@@ -1888,6 +1963,10 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
1888
1963
pr_err ("%s: missing sched_switch event\n" , __func__ );
1889
1964
goto err_delete_thread ;
1890
1965
}
1966
+ } else if (pt -> have_sched_switch == 2 &&
1967
+ !intel_pt_find_switch (session -> evlist )) {
1968
+ pr_err ("%s: missing context_switch attribute flag\n" , __func__ );
1969
+ goto err_delete_thread ;
1891
1970
}
1892
1971
1893
1972
if (session -> itrace_synth_opts && session -> itrace_synth_opts -> set ) {
0 commit comments