Subject: Re: [PATCH v6 6/8] perf cs-etm: Filter synthesized branch samples

From: James Clark <[email-masked]>
Date: Thu, 4 Jun 2026 15:42:32 +0100

On 26/05/2026 5:59 pm, Leo Yan wrote:
> From: Leo Yan <[email-masked]>
> 
> CS ETM currently emits branch samples for every decoded branch when
> branch synthesis is enabled. This delivers redundant info when users
> request only call or return branches.
> 
> Add a branch filter derived from the itrace "calls" and "returns" options.
> When no filter is set, keep the existing behavior and emit all branch
> samples. When call or return filtering is requested, only synthesize branch
> samples whose flags match the selected branch types, including trace
> begin and end markers.
> 
> Before:
> 
>    perf script -F +callindent
> 
>    callchain_test    9187 [002] 599611.826599:          1 branches:             main                                                     ffff83312258 __libc_start_call_main+0x78 (/usr/lib/aarch64-linux-gnu/libc.so.6)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                 foo                                                  aaaae3ed07c4 main+0x8 (/home/kernel/leoy/test_cs_callchain/callchain_test)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                     print                                            aaaae3ed07ac foo+0x8 (/home/kernel/leoy/test_cs_callchain/callchain_test)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                         do_svc                                       aaaae3ed0794 print+0x8 (/home/kernel/leoy/test_cs_callchain/callchain_test)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                                                                      aaaae3ed077c do_svc+0x14 (/home/kernel/leoy/test_cs_callchain/callchain_test)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                             vectors                                  aaaae3ed0780 do_svc+0x18 (/home/kernel/leoy/test_cs_callchain/callchain_test)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                                                                  ffff800080010c00 vectors+0x400 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826600:          1 branches:                                                                  ffff800080010c24 vectors+0x424 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826600:          1 branches:                                                                  ffff8000800114dc el0t_64_sync+0xd4 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826600:          1 branches:                                                                  ffff8000800114f8 el0t_64_sync+0xf0 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826600:          1 branches:                                                                  ffff800080011528 el0t_64_sync+0x120 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826600:          1 branches:                                                                  ffff800080011538 el0t_64_sync+0x130 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826601:          1 branches:                                                                  ffff800080011568 el0t_64_sync+0x160 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826601:          1 branches:                                 el0t_64_sync_handler             ffff80008001159c el0t_64_sync+0x194 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826601:          1 branches:                                                                  ffff800081829110 el0t_64_sync_handler+0x18 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826601:          1 branches:                                     el0t_64_sync_handler         ffff800081829140 el0t_64_sync_handler+0x48 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826601:          1 branches:                                     el0_svc                      ffff800081829194 el0t_64_sync_handler+0x9c ([kernel.kallsyms])
> 
> After:
> 
>    callchain_test    9187 [002] 599611.826599:          1 branches:             main                                                     ffff83312258 __libc_start_call_main+0x78 (/usr/lib/aarch64-linux-gnu/libc.so.6)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                 foo                                                  aaaae3ed07c4 main+0x8 (/home/kernel/leoy/test_cs_callchain/callchain_test)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                     print                                            aaaae3ed07ac foo+0x8 (/home/kernel/leoy/test_cs_callchain/callchain_test)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                         do_svc                                       aaaae3ed0794 print+0x8 (/home/kernel/leoy/test_cs_callchain/callchain_test)
>    callchain_test    9187 [002] 599611.826599:          1 branches:                             vectors                                  aaaae3ed0780 do_svc+0x18 (/home/kernel/leoy/test_cs_callchain/callchain_test)
>    callchain_test    9187 [002] 599611.826601:          1 branches:                                 el0t_64_sync_handler             ffff80008001159c el0t_64_sync+0x194 ([kernel.kallsyms])
>    callchain_test    9187 [002] 599611.826601:          1 branches:                                     el0_svc                      ffff800081829194 el0t_64_sync_handler+0x9c ([kernel.kallsyms])
> 
> Signed-off-by: Leo Yan <[email-masked]>
> Signed-off-by: Leo Yan <[email-masked]>
> ---
>   tools/perf/util/cs-etm.c | 15 +++++++++++++++
>   1 file changed, 15 insertions(+)
> 
> diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> index b31d0dd46a45dc365edd7c2f9e9b2eb077ca23db..8d98e772ecb307381b5ed1b4bbc4056e8779b261 100644
> --- a/tools/perf/util/cs-etm.c
> +++ b/tools/perf/util/cs-etm.c
> @@ -71,6 +71,7 @@ struct cs_etm_auxtrace {
>   	int num_cpu;
>   	u64 latest_kernel_timestamp;
>   	u32 auxtrace_type;
> +	u32 branches_filter;
>   	u64 branches_sample_type;
>   	u64 branches_id;
>   	u64 instructions_sample_type;
> @@ -1596,6 +1597,10 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq,
>   	} dummy_bs;
>   	u64 ip;
>   
> +	if (etm->branches_filter &&
> +		!(etm->branches_filter & tidq->prev_packet->flags))
> +		return 0;
> +
>   	ip = cs_etm__last_executed_instr(tidq->prev_packet);
>   
>   	event->sample.header.type = PERF_RECORD_SAMPLE;
> @@ -3442,6 +3447,16 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event,
>   		etm->synth_opts.thread_stack = session->itrace_synth_opts->thread_stack;
>   	}
>   
> +	if (etm->synth_opts.calls)
> +		etm->branches_filter |= PERF_IP_FLAG_CALL |
> +					PERF_IP_FLAG_TRACE_BEGIN |
> +					PERF_IP_FLAG_TRACE_END;
> +
> +	if (etm->synth_opts.returns)
> +		etm->branches_filter |= PERF_IP_FLAG_RETURN |
> +					PERF_IP_FLAG_TRACE_BEGIN |
> +					PERF_IP_FLAG_TRACE_END;
> +

This changes the default "perf script" output quite significantly and 
will possibly break people's workflows. synth_opts.calls is true by 
default but synth_opts.returns is false so we lose all the returns that 
we used to have. Not sure if the new behavior is more consistent with 
other tools so we can justify changing it? Personally I think including 
returns by default made more sense, and it's a more literal 
representation of the flow.

itrace.txt says the default is "all events i.e. the same as 
--itrace=iybxwpe", but I thought the default was branches? At least for 
Coresight it is, so I'm a bit confused.

>   	etm->session = session;
>   	etm->num_cpu = num_cpu;