mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 03:35:32 -04:00
perf cs-etm: Flush thread stacks after decoder reset
Perf resets the CoreSight decoder when moving to a new AUX trace buffer, this causes trace discontinunity globally. For callchain synthesis, keeping thread-stack state after decoder reset can leave stale call/return history attached to threads that are decoded later, producing incorrect synthesized callchains. Flush all host thread stacks after a decoder reset. When virtualization is present, flush the guest thread stacks as well. Reviewed-by: James Clark <james.clark@linaro.org> Signed-off-by: Leo Yan <leo.yan@arm.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
@@ -2033,6 +2033,45 @@ static int cs_etm__end_block(struct cs_etm_queue *etmq,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs_etm__flush_stack_cb(struct thread *thread,
|
||||
void *data __maybe_unused)
|
||||
{
|
||||
thread_stack__flush(thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cs_etm__flush_machine_stack(struct cs_etm_queue *etmq, pid_t pid)
|
||||
{
|
||||
struct machine *machine;
|
||||
|
||||
machine = machines__find(&etmq->etm->session->machines, pid);
|
||||
if (machine)
|
||||
machine__for_each_thread(machine, cs_etm__flush_stack_cb, NULL);
|
||||
}
|
||||
|
||||
static void cs_etm__flush_all_stack(struct cs_etm_queue *etmq)
|
||||
{
|
||||
enum cs_etm_pid_fmt pid_fmt = cs_etm__get_pid_fmt(etmq);
|
||||
|
||||
if (!etmq->etm->synth_opts.last_branch)
|
||||
return;
|
||||
|
||||
switch (pid_fmt) {
|
||||
case CS_ETM_PIDFMT_CTXTID2:
|
||||
/* Clear the guest stack if virtualization is supported */
|
||||
cs_etm__flush_machine_stack(etmq, DEFAULT_GUEST_KERNEL_ID);
|
||||
fallthrough;
|
||||
case CS_ETM_PIDFMT_CTXTID:
|
||||
cs_etm__flush_machine_stack(etmq, HOST_KERNEL_ID);
|
||||
break;
|
||||
case CS_ETM_PIDFMT_NONE:
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* cs_etm__get_data_block: Fetch a block from the auxtrace_buffer queue
|
||||
* if need be.
|
||||
@@ -2055,6 +2094,12 @@ static int cs_etm__get_data_block(struct cs_etm_queue *etmq)
|
||||
ret = cs_etm_decoder__reset(etmq->decoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Since the decoder is reset, this causes a global trace
|
||||
* discontinuity. Flush all thread stacks.
|
||||
*/
|
||||
cs_etm__flush_all_stack(etmq);
|
||||
}
|
||||
|
||||
return etmq->buf_len;
|
||||
|
||||
Reference in New Issue
Block a user