An exception can transfer execution to the kernel after any instruction. When this creates a trace boundary, perf may attribute the trace-end sample to the last instruction in the range. If that instruction is an untaken branch, reporting only its branch type can make the transfer look like a taken branch.
Set PERF_IP_FLAG_NOT_TAKEN for branch ranges when last_instr_taken_branch is false. This records the decoded branch outcome independently of exception entry.
For a discontinuity without an exception element, perf script previously reported an untaken B.LS as:
tr end jcc 4000f8 => 0 b.ls #0x400118 tr strt jmp 0 => 4000fc
With the not-taken flag set:
tr end jcc/not_taken/ 4000f8 => 0 b.ls #0x400118 tr strt jmp 0 => 4000fc
Here, 4000f8 remains the last traced instruction and 4000fc is the trace restart address. These boundary samples do not establish an IRQ entry or an exception return; the not_taken flag records only the branch outcome.
Assisted-by: Codex:gpt-6 Signed-off-by: Leo Yan leo.yan@arm.com --- tools/perf/util/cs-etm.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 0163d93ac2d537a2190536e77d24628b4d707751..c54218aeef53e8420447e9a2bee6e98d8225e335 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -2415,6 +2415,11 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq, packet->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN;
+ /* Report branch that is not taken */ + if ((packet->flags & PERF_IP_FLAG_BRANCH) && + !packet->last_instr_taken_branch) + packet->flags |= PERF_IP_FLAG_NOT_TAKEN; + /* * Decoder might insert a discontinuity in the middle of * instruction packets, fixup prev_packet with flag