diff options
-rw-r--r-- | tools/perf/util/cs-etm.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index a714b31656ea..8b3f882d6e2f 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c | |||
@@ -1372,6 +1372,20 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq) | |||
1372 | if (prev_packet->sample_type == CS_ETM_DISCONTINUITY) | 1372 | if (prev_packet->sample_type == CS_ETM_DISCONTINUITY) |
1373 | prev_packet->flags |= PERF_IP_FLAG_BRANCH | | 1373 | prev_packet->flags |= PERF_IP_FLAG_BRANCH | |
1374 | PERF_IP_FLAG_TRACE_BEGIN; | 1374 | PERF_IP_FLAG_TRACE_BEGIN; |
1375 | |||
1376 | /* | ||
1377 | * If the previous packet is an exception return packet | ||
1378 | * and the return address just follows SVC instuction, | ||
1379 | * it needs to calibrate the previous packet sample flags | ||
1380 | * as PERF_IP_FLAG_SYSCALLRET. | ||
1381 | */ | ||
1382 | if (prev_packet->flags == (PERF_IP_FLAG_BRANCH | | ||
1383 | PERF_IP_FLAG_RETURN | | ||
1384 | PERF_IP_FLAG_INTERRUPT) && | ||
1385 | cs_etm__is_svc_instr(etmq, packet, packet->start_addr)) | ||
1386 | prev_packet->flags = PERF_IP_FLAG_BRANCH | | ||
1387 | PERF_IP_FLAG_RETURN | | ||
1388 | PERF_IP_FLAG_SYSCALLRET; | ||
1375 | break; | 1389 | break; |
1376 | case CS_ETM_DISCONTINUITY: | 1390 | case CS_ETM_DISCONTINUITY: |
1377 | /* | 1391 | /* |
@@ -1422,6 +1436,36 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq) | |||
1422 | prev_packet->flags = packet->flags; | 1436 | prev_packet->flags = packet->flags; |
1423 | break; | 1437 | break; |
1424 | case CS_ETM_EXCEPTION_RET: | 1438 | case CS_ETM_EXCEPTION_RET: |
1439 | /* | ||
1440 | * When the exception return packet is inserted, since | ||
1441 | * exception return packet is not used standalone for | ||
1442 | * generating samples and it's affiliation to the previous | ||
1443 | * instruction range packet; so set previous range packet | ||
1444 | * flags to tell perf it is an exception return branch. | ||
1445 | * | ||
1446 | * The exception return can be for either system call or | ||
1447 | * other exception types; unfortunately the packet doesn't | ||
1448 | * contain exception type related info so we cannot decide | ||
1449 | * the exception type purely based on exception return packet. | ||
1450 | * If we record the exception number from exception packet and | ||
1451 | * reuse it for excpetion return packet, this is not reliable | ||
1452 | * due the trace can be discontinuity or the interrupt can | ||
1453 | * be nested, thus the recorded exception number cannot be | ||
1454 | * used for exception return packet for these two cases. | ||
1455 | * | ||
1456 | * For exception return packet, we only need to distinguish the | ||
1457 | * packet is for system call or for other types. Thus the | ||
1458 | * decision can be deferred when receive the next packet which | ||
1459 | * contains the return address, based on the return address we | ||
1460 | * can read out the previous instruction and check if it's a | ||
1461 | * system call instruction and then calibrate the sample flag | ||
1462 | * as needed. | ||
1463 | */ | ||
1464 | if (prev_packet->sample_type == CS_ETM_RANGE) | ||
1465 | prev_packet->flags = PERF_IP_FLAG_BRANCH | | ||
1466 | PERF_IP_FLAG_RETURN | | ||
1467 | PERF_IP_FLAG_INTERRUPT; | ||
1468 | break; | ||
1425 | case CS_ETM_EMPTY: | 1469 | case CS_ETM_EMPTY: |
1426 | default: | 1470 | default: |
1427 | break; | 1471 | break; |