Skip to content

Commit 27d113c

Browse files
German Gomezacmel
authored andcommitted
perf arm-spe: Support hardware-based PID tracing
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/f877cfa6-9b25-6445-3806-ca44a4042eaf@arm.com/ Signed-off-by: German Gomez <german.gomez@arm.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: John Garry <john.garry@huawei.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Cc: Will Deacon <will@kernel.org> Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20211111133625.193568-5-german.gomez@arm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent 169de64 commit 27d113c

File tree

1 file changed

+70
-29
lines changed

1 file changed

+70
-29
lines changed

tools/perf/util/arm-spe.c

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ struct arm_spe {
7171
u64 kernel_start;
7272

7373
unsigned long num_events;
74+
u8 use_ctx_pkt_for_pid;
7475
};
7576

7677
struct arm_spe_queue {
@@ -226,6 +227,44 @@ static inline u8 arm_spe_cpumode(struct arm_spe *spe, u64 ip)
226227
PERF_RECORD_MISC_USER;
227228
}
228229

230+
static void arm_spe_set_pid_tid_cpu(struct arm_spe *spe,
231+
struct auxtrace_queue *queue)
232+
{
233+
struct arm_spe_queue *speq = queue->priv;
234+
pid_t tid;
235+
236+
tid = machine__get_current_tid(spe->machine, speq->cpu);
237+
if (tid != -1) {
238+
speq->tid = tid;
239+
thread__zput(speq->thread);
240+
} else
241+
speq->tid = queue->tid;
242+
243+
if ((!speq->thread) && (speq->tid != -1)) {
244+
speq->thread = machine__find_thread(spe->machine, -1,
245+
speq->tid);
246+
}
247+
248+
if (speq->thread) {
249+
speq->pid = speq->thread->pid_;
250+
if (queue->cpu == -1)
251+
speq->cpu = speq->thread->cpu;
252+
}
253+
}
254+
255+
static int arm_spe_set_tid(struct arm_spe_queue *speq, pid_t tid)
256+
{
257+
struct arm_spe *spe = speq->spe;
258+
int err = machine__set_current_tid(spe->machine, speq->cpu, -1, tid);
259+
260+
if (err)
261+
return err;
262+
263+
arm_spe_set_pid_tid_cpu(spe, &spe->queues.queue_array[speq->queue_nr]);
264+
265+
return 0;
266+
}
267+
229268
static void arm_spe_prep_sample(struct arm_spe *spe,
230269
struct arm_spe_queue *speq,
231270
union perf_event *event,
@@ -460,6 +499,19 @@ static int arm_spe_run_decoder(struct arm_spe_queue *speq, u64 *timestamp)
460499
* can correlate samples between Arm SPE trace data and other
461500
* perf events with correct time ordering.
462501
*/
502+
503+
/*
504+
* Update pid/tid info.
505+
*/
506+
record = &speq->decoder->record;
507+
if (!spe->timeless_decoding && record->context_id != (u64)-1) {
508+
ret = arm_spe_set_tid(speq, record->context_id);
509+
if (ret)
510+
return ret;
511+
512+
spe->use_ctx_pkt_for_pid = true;
513+
}
514+
463515
ret = arm_spe_sample(speq);
464516
if (ret)
465517
return ret;
@@ -586,31 +638,6 @@ static bool arm_spe__is_timeless_decoding(struct arm_spe *spe)
586638
return timeless_decoding;
587639
}
588640

589-
static void arm_spe_set_pid_tid_cpu(struct arm_spe *spe,
590-
struct auxtrace_queue *queue)
591-
{
592-
struct arm_spe_queue *speq = queue->priv;
593-
pid_t tid;
594-
595-
tid = machine__get_current_tid(spe->machine, speq->cpu);
596-
if (tid != -1) {
597-
speq->tid = tid;
598-
thread__zput(speq->thread);
599-
} else
600-
speq->tid = queue->tid;
601-
602-
if ((!speq->thread) && (speq->tid != -1)) {
603-
speq->thread = machine__find_thread(spe->machine, -1,
604-
speq->tid);
605-
}
606-
607-
if (speq->thread) {
608-
speq->pid = speq->thread->pid_;
609-
if (queue->cpu == -1)
610-
speq->cpu = speq->thread->cpu;
611-
}
612-
}
613-
614641
static int arm_spe_process_queues(struct arm_spe *spe, u64 timestamp)
615642
{
616643
unsigned int queue_nr;
@@ -641,7 +668,12 @@ static int arm_spe_process_queues(struct arm_spe *spe, u64 timestamp)
641668
ts = timestamp;
642669
}
643670

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

646678
ret = arm_spe_run_decoder(speq, &ts);
647679
if (ret < 0) {
@@ -740,8 +772,9 @@ static int arm_spe_process_event(struct perf_session *session,
740772
if (err)
741773
return err;
742774

743-
if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE ||
744-
event->header.type == PERF_RECORD_SWITCH)
775+
if (!spe->use_ctx_pkt_for_pid &&
776+
(event->header.type == PERF_RECORD_SWITCH_CPU_WIDE ||
777+
event->header.type == PERF_RECORD_SWITCH))
745778
err = arm_spe_context_switch(spe, event, sample);
746779
}
747780

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

811-
return arm_spe_process_queues(spe, MAX_TIMESTAMP);
844+
ret = arm_spe_process_queues(spe, MAX_TIMESTAMP);
845+
if (ret)
846+
return ret;
847+
848+
if (!spe->use_ctx_pkt_for_pid)
849+
ui__warning("Arm SPE CONTEXT packets not found in the traces.\n"
850+
"Matching of TIDs to SPE events could be inaccurate.\n");
851+
852+
return 0;
812853
}
813854

814855
static void arm_spe_free_queue(void *priv)

0 commit comments

Comments
 (0)