Skip to content

Commit

Permalink
perf arm-spe: Support hardware-based PID tracing
Browse files Browse the repository at this point in the history
If ARM SPE traces contains CONTEXT packets with TID info, use these
values for tracking the TID of samples. Otherwise fall back to using
context switch events and display a message warning to the user of
possible timing inaccuracies [1].

[1] https://lore.kernel.org/lkml/[email protected]/

Signed-off-by: German Gomez <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: John Garry <[email protected]>
Cc: Leo Yan <[email protected]>
Cc: Mark Rutland <[email protected]>
Cc: Mathieu Poirier <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: [email protected]
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
German Gomez authored and acmel committed Nov 13, 2021
1 parent 169de64 commit 27d113c
Showing 1 changed file with 70 additions and 29 deletions.
99 changes: 70 additions & 29 deletions tools/perf/util/arm-spe.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ struct arm_spe {
u64 kernel_start;

unsigned long num_events;
u8 use_ctx_pkt_for_pid;
};

struct arm_spe_queue {
Expand Down Expand Up @@ -226,6 +227,44 @@ static inline u8 arm_spe_cpumode(struct arm_spe *spe, u64 ip)
PERF_RECORD_MISC_USER;
}

static void arm_spe_set_pid_tid_cpu(struct arm_spe *spe,
struct auxtrace_queue *queue)
{
struct arm_spe_queue *speq = queue->priv;
pid_t tid;

tid = machine__get_current_tid(spe->machine, speq->cpu);
if (tid != -1) {
speq->tid = tid;
thread__zput(speq->thread);
} else
speq->tid = queue->tid;

if ((!speq->thread) && (speq->tid != -1)) {
speq->thread = machine__find_thread(spe->machine, -1,
speq->tid);
}

if (speq->thread) {
speq->pid = speq->thread->pid_;
if (queue->cpu == -1)
speq->cpu = speq->thread->cpu;
}
}

static int arm_spe_set_tid(struct arm_spe_queue *speq, pid_t tid)
{
struct arm_spe *spe = speq->spe;
int err = machine__set_current_tid(spe->machine, speq->cpu, -1, tid);

if (err)
return err;

arm_spe_set_pid_tid_cpu(spe, &spe->queues.queue_array[speq->queue_nr]);

return 0;
}

static void arm_spe_prep_sample(struct arm_spe *spe,
struct arm_spe_queue *speq,
union perf_event *event,
Expand Down Expand Up @@ -460,6 +499,19 @@ static int arm_spe_run_decoder(struct arm_spe_queue *speq, u64 *timestamp)
* can correlate samples between Arm SPE trace data and other
* perf events with correct time ordering.
*/

/*
* Update pid/tid info.
*/
record = &speq->decoder->record;
if (!spe->timeless_decoding && record->context_id != (u64)-1) {
ret = arm_spe_set_tid(speq, record->context_id);
if (ret)
return ret;

spe->use_ctx_pkt_for_pid = true;
}

ret = arm_spe_sample(speq);
if (ret)
return ret;
Expand Down Expand Up @@ -586,31 +638,6 @@ static bool arm_spe__is_timeless_decoding(struct arm_spe *spe)
return timeless_decoding;
}

static void arm_spe_set_pid_tid_cpu(struct arm_spe *spe,
struct auxtrace_queue *queue)
{
struct arm_spe_queue *speq = queue->priv;
pid_t tid;

tid = machine__get_current_tid(spe->machine, speq->cpu);
if (tid != -1) {
speq->tid = tid;
thread__zput(speq->thread);
} else
speq->tid = queue->tid;

if ((!speq->thread) && (speq->tid != -1)) {
speq->thread = machine__find_thread(spe->machine, -1,
speq->tid);
}

if (speq->thread) {
speq->pid = speq->thread->pid_;
if (queue->cpu == -1)
speq->cpu = speq->thread->cpu;
}
}

static int arm_spe_process_queues(struct arm_spe *spe, u64 timestamp)
{
unsigned int queue_nr;
Expand Down Expand Up @@ -641,7 +668,12 @@ static int arm_spe_process_queues(struct arm_spe *spe, u64 timestamp)
ts = timestamp;
}

arm_spe_set_pid_tid_cpu(spe, queue);
/*
* A previous context-switch event has set pid/tid in the machine's context, so
* here we need to update the pid/tid in the thread and SPE queue.
*/
if (!spe->use_ctx_pkt_for_pid)
arm_spe_set_pid_tid_cpu(spe, queue);

ret = arm_spe_run_decoder(speq, &ts);
if (ret < 0) {
Expand Down Expand Up @@ -740,8 +772,9 @@ static int arm_spe_process_event(struct perf_session *session,
if (err)
return err;

if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE ||
event->header.type == PERF_RECORD_SWITCH)
if (!spe->use_ctx_pkt_for_pid &&
(event->header.type == PERF_RECORD_SWITCH_CPU_WIDE ||
event->header.type == PERF_RECORD_SWITCH))
err = arm_spe_context_switch(spe, event, sample);
}

Expand Down Expand Up @@ -808,7 +841,15 @@ static int arm_spe_flush(struct perf_session *session __maybe_unused,
return arm_spe_process_timeless_queues(spe, -1,
MAX_TIMESTAMP - 1);

return arm_spe_process_queues(spe, MAX_TIMESTAMP);
ret = arm_spe_process_queues(spe, MAX_TIMESTAMP);
if (ret)
return ret;

if (!spe->use_ctx_pkt_for_pid)
ui__warning("Arm SPE CONTEXT packets not found in the traces.\n"
"Matching of TIDs to SPE events could be inaccurate.\n");

return 0;
}

static void arm_spe_free_queue(void *priv)
Expand Down

0 comments on commit 27d113c

Please sign in to comment.