Skip to content

Commit a16afcc

Browse files
bwicaksononvnamhyung
authored andcommitted
perf cs-etm: Fix incorrect or missing decoder for raw trace
The decoder creation for raw trace uses metadata from the first CPU. On per-cpu mode, this metadata is incorrectly used for every decoder. On per-process/per-thread traces, the first CPU is CPU0. If CPU0 trace is not enabled, its metadata will be marked unused and the decoder is not created. Perf report dump skips the decoding part because the decoder is missing. To fix this, use metadata of the CPU associated with sample object. Signed-off-by: Besar Wicaksono <[email protected]> Reviewed-by: James Clark <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Namhyung Kim <[email protected]>
1 parent b84b3f4 commit a16afcc

File tree

1 file changed

+65
-41
lines changed

1 file changed

+65
-41
lines changed

tools/perf/util/cs-etm.c

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -283,22 +283,31 @@ static int cs_etm__metadata_set_trace_id(u8 trace_chan_id, u64 *cpu_metadata)
283283
}
284284

285285
/*
286-
* Get a metadata for a specific cpu from an array.
286+
* Get a metadata index for a specific cpu from an array.
287287
*
288288
*/
289-
static u64 *get_cpu_data(struct cs_etm_auxtrace *etm, int cpu)
289+
static int get_cpu_data_idx(struct cs_etm_auxtrace *etm, int cpu)
290290
{
291291
int i;
292-
u64 *metadata = NULL;
293292

294293
for (i = 0; i < etm->num_cpu; i++) {
295294
if (etm->metadata[i][CS_ETM_CPU] == (u64)cpu) {
296-
metadata = etm->metadata[i];
297-
break;
295+
return i;
298296
}
299297
}
300298

301-
return metadata;
299+
return -1;
300+
}
301+
302+
/*
303+
* Get a metadata for a specific cpu from an array.
304+
*
305+
*/
306+
static u64 *get_cpu_data(struct cs_etm_auxtrace *etm, int cpu)
307+
{
308+
int idx = get_cpu_data_idx(etm, cpu);
309+
310+
return (idx != -1) ? etm->metadata[idx] : NULL;
302311
}
303312

304313
/*
@@ -641,66 +650,80 @@ static void cs_etm__packet_dump(const char *pkt_string)
641650
}
642651

643652
static void cs_etm__set_trace_param_etmv3(struct cs_etm_trace_params *t_params,
644-
struct cs_etm_auxtrace *etm, int idx,
645-
u32 etmidr)
653+
struct cs_etm_auxtrace *etm, int t_idx,
654+
int m_idx, u32 etmidr)
646655
{
647656
u64 **metadata = etm->metadata;
648657

649-
t_params[idx].protocol = cs_etm__get_v7_protocol_version(etmidr);
650-
t_params[idx].etmv3.reg_ctrl = metadata[idx][CS_ETM_ETMCR];
651-
t_params[idx].etmv3.reg_trc_id = metadata[idx][CS_ETM_ETMTRACEIDR];
658+
t_params[t_idx].protocol = cs_etm__get_v7_protocol_version(etmidr);
659+
t_params[t_idx].etmv3.reg_ctrl = metadata[m_idx][CS_ETM_ETMCR];
660+
t_params[t_idx].etmv3.reg_trc_id = metadata[m_idx][CS_ETM_ETMTRACEIDR];
652661
}
653662

654663
static void cs_etm__set_trace_param_etmv4(struct cs_etm_trace_params *t_params,
655-
struct cs_etm_auxtrace *etm, int idx)
664+
struct cs_etm_auxtrace *etm, int t_idx,
665+
int m_idx)
656666
{
657667
u64 **metadata = etm->metadata;
658668

659-
t_params[idx].protocol = CS_ETM_PROTO_ETMV4i;
660-
t_params[idx].etmv4.reg_idr0 = metadata[idx][CS_ETMV4_TRCIDR0];
661-
t_params[idx].etmv4.reg_idr1 = metadata[idx][CS_ETMV4_TRCIDR1];
662-
t_params[idx].etmv4.reg_idr2 = metadata[idx][CS_ETMV4_TRCIDR2];
663-
t_params[idx].etmv4.reg_idr8 = metadata[idx][CS_ETMV4_TRCIDR8];
664-
t_params[idx].etmv4.reg_configr = metadata[idx][CS_ETMV4_TRCCONFIGR];
665-
t_params[idx].etmv4.reg_traceidr = metadata[idx][CS_ETMV4_TRCTRACEIDR];
669+
t_params[t_idx].protocol = CS_ETM_PROTO_ETMV4i;
670+
t_params[t_idx].etmv4.reg_idr0 = metadata[m_idx][CS_ETMV4_TRCIDR0];
671+
t_params[t_idx].etmv4.reg_idr1 = metadata[m_idx][CS_ETMV4_TRCIDR1];
672+
t_params[t_idx].etmv4.reg_idr2 = metadata[m_idx][CS_ETMV4_TRCIDR2];
673+
t_params[t_idx].etmv4.reg_idr8 = metadata[m_idx][CS_ETMV4_TRCIDR8];
674+
t_params[t_idx].etmv4.reg_configr = metadata[m_idx][CS_ETMV4_TRCCONFIGR];
675+
t_params[t_idx].etmv4.reg_traceidr = metadata[m_idx][CS_ETMV4_TRCTRACEIDR];
666676
}
667677

668678
static void cs_etm__set_trace_param_ete(struct cs_etm_trace_params *t_params,
669-
struct cs_etm_auxtrace *etm, int idx)
679+
struct cs_etm_auxtrace *etm, int t_idx,
680+
int m_idx)
670681
{
671682
u64 **metadata = etm->metadata;
672683

673-
t_params[idx].protocol = CS_ETM_PROTO_ETE;
674-
t_params[idx].ete.reg_idr0 = metadata[idx][CS_ETE_TRCIDR0];
675-
t_params[idx].ete.reg_idr1 = metadata[idx][CS_ETE_TRCIDR1];
676-
t_params[idx].ete.reg_idr2 = metadata[idx][CS_ETE_TRCIDR2];
677-
t_params[idx].ete.reg_idr8 = metadata[idx][CS_ETE_TRCIDR8];
678-
t_params[idx].ete.reg_configr = metadata[idx][CS_ETE_TRCCONFIGR];
679-
t_params[idx].ete.reg_traceidr = metadata[idx][CS_ETE_TRCTRACEIDR];
680-
t_params[idx].ete.reg_devarch = metadata[idx][CS_ETE_TRCDEVARCH];
684+
t_params[t_idx].protocol = CS_ETM_PROTO_ETE;
685+
t_params[t_idx].ete.reg_idr0 = metadata[m_idx][CS_ETE_TRCIDR0];
686+
t_params[t_idx].ete.reg_idr1 = metadata[m_idx][CS_ETE_TRCIDR1];
687+
t_params[t_idx].ete.reg_idr2 = metadata[m_idx][CS_ETE_TRCIDR2];
688+
t_params[t_idx].ete.reg_idr8 = metadata[m_idx][CS_ETE_TRCIDR8];
689+
t_params[t_idx].ete.reg_configr = metadata[m_idx][CS_ETE_TRCCONFIGR];
690+
t_params[t_idx].ete.reg_traceidr = metadata[m_idx][CS_ETE_TRCTRACEIDR];
691+
t_params[t_idx].ete.reg_devarch = metadata[m_idx][CS_ETE_TRCDEVARCH];
681692
}
682693

683694
static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params,
684695
struct cs_etm_auxtrace *etm,
696+
bool formatted,
697+
int sample_cpu,
685698
int decoders)
686699
{
687-
int i;
700+
int t_idx, m_idx;
688701
u32 etmidr;
689702
u64 architecture;
690703

691-
for (i = 0; i < decoders; i++) {
692-
architecture = etm->metadata[i][CS_ETM_MAGIC];
704+
for (t_idx = 0; t_idx < decoders; t_idx++) {
705+
if (formatted)
706+
m_idx = t_idx;
707+
else {
708+
m_idx = get_cpu_data_idx(etm, sample_cpu);
709+
if (m_idx == -1) {
710+
pr_warning("CS_ETM: unknown CPU, falling back to first metadata\n");
711+
m_idx = 0;
712+
}
713+
}
714+
715+
architecture = etm->metadata[m_idx][CS_ETM_MAGIC];
693716

694717
switch (architecture) {
695718
case __perf_cs_etmv3_magic:
696-
etmidr = etm->metadata[i][CS_ETM_ETMIDR];
697-
cs_etm__set_trace_param_etmv3(t_params, etm, i, etmidr);
719+
etmidr = etm->metadata[m_idx][CS_ETM_ETMIDR];
720+
cs_etm__set_trace_param_etmv3(t_params, etm, t_idx, m_idx, etmidr);
698721
break;
699722
case __perf_cs_etmv4_magic:
700-
cs_etm__set_trace_param_etmv4(t_params, etm, i);
723+
cs_etm__set_trace_param_etmv4(t_params, etm, t_idx, m_idx);
701724
break;
702725
case __perf_cs_ete_magic:
703-
cs_etm__set_trace_param_ete(t_params, etm, i);
726+
cs_etm__set_trace_param_ete(t_params, etm, t_idx, m_idx);
704727
break;
705728
default:
706729
return -EINVAL;
@@ -1016,7 +1039,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
10161039
}
10171040

10181041
static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
1019-
bool formatted)
1042+
bool formatted, int sample_cpu)
10201043
{
10211044
struct cs_etm_decoder_params d_params;
10221045
struct cs_etm_trace_params *t_params = NULL;
@@ -1041,7 +1064,7 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
10411064
if (!t_params)
10421065
goto out_free;
10431066

1044-
if (cs_etm__init_trace_params(t_params, etm, decoders))
1067+
if (cs_etm__init_trace_params(t_params, etm, formatted, sample_cpu, decoders))
10451068
goto out_free;
10461069

10471070
/* Set decoder parameters to decode trace packets */
@@ -1081,14 +1104,15 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
10811104
static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
10821105
struct auxtrace_queue *queue,
10831106
unsigned int queue_nr,
1084-
bool formatted)
1107+
bool formatted,
1108+
int sample_cpu)
10851109
{
10861110
struct cs_etm_queue *etmq = queue->priv;
10871111

10881112
if (list_empty(&queue->head) || etmq)
10891113
return 0;
10901114

1091-
etmq = cs_etm__alloc_queue(etm, formatted);
1115+
etmq = cs_etm__alloc_queue(etm, formatted, sample_cpu);
10921116

10931117
if (!etmq)
10941118
return -ENOMEM;
@@ -2816,7 +2840,7 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session,
28162840
* formatted in piped mode (true).
28172841
*/
28182842
err = cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
2819-
idx, true);
2843+
idx, true, -1);
28202844
if (err)
28212845
return err;
28222846

@@ -3022,7 +3046,7 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o
30223046
idx = auxtrace_event->idx;
30233047
formatted = !(aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW);
30243048
return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
3025-
idx, formatted);
3049+
idx, formatted, sample->cpu);
30263050
}
30273051

30283052
/* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */

0 commit comments

Comments
 (0)