Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf cs-etm: Support sample flags 'insn' and 'insnlen'

The synthetic branch and instruction samples are missed to set
instruction related info, thus the perf tool fails to display samples
with flags '-F,+insn,+insnlen'.

The CoreSight trace decoder provides sufficient information to decide
the instruction size based on the ISA type: A64/A32 instructions are
32-bit size, but one exception is the T32 instruction size, which might
be 32-bit or 16-bit.

This patch handles these cases and it reads the instruction values from
DSO file; thus can support the flags '-F,+insn,+insnlen'.

Before:

# perf script -F,insn,insnlen,ip,sym
0 [unknown] ilen: 0
ffff97174044 _start ilen: 0
ffff97174938 _dl_start ilen: 0
ffff97174938 _dl_start ilen: 0
ffff97174938 _dl_start ilen: 0
ffff97174938 _dl_start ilen: 0
ffff97174938 _dl_start ilen: 0
ffff97174938 _dl_start ilen: 0
ffff97174938 _dl_start ilen: 0
ffff97174938 _dl_start ilen: 0

[...]

After:

# perf script -F,insn,insnlen,ip,sym
0 [unknown] ilen: 0
ffff97174044 _start ilen: 4 insn: 2f 02 00 94
ffff97174938 _dl_start ilen: 4 insn: c1 ff ff 54
ffff97174938 _dl_start ilen: 4 insn: c1 ff ff 54
ffff97174938 _dl_start ilen: 4 insn: c1 ff ff 54
ffff97174938 _dl_start ilen: 4 insn: c1 ff ff 54
ffff97174938 _dl_start ilen: 4 insn: c1 ff ff 54
ffff97174938 _dl_start ilen: 4 insn: c1 ff ff 54
ffff97174938 _dl_start ilen: 4 insn: c1 ff ff 54
ffff97174938 _dl_start ilen: 4 insn: c1 ff ff 54

[...]

Signed-off-by: Leo Yan <leo.yan@linaro.org>
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Tested-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Robert Walker <robert.walker@arm.com>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Link: http://lkml.kernel.org/r/20190815082854.18191-1-leo.yan@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Leo Yan and committed by
Arnaldo Carvalho de Melo
a4973d8f 10ccbc1c

+34 -1
+34 -1
tools/perf/util/cs-etm.c
··· 1076 1076 return !!etmq->etm->timeless_decoding; 1077 1077 } 1078 1078 1079 + static void cs_etm__copy_insn(struct cs_etm_queue *etmq, 1080 + u64 trace_chan_id, 1081 + const struct cs_etm_packet *packet, 1082 + struct perf_sample *sample) 1083 + { 1084 + /* 1085 + * It's pointless to read instructions for the CS_ETM_DISCONTINUITY 1086 + * packet, so directly bail out with 'insn_len' = 0. 1087 + */ 1088 + if (packet->sample_type == CS_ETM_DISCONTINUITY) { 1089 + sample->insn_len = 0; 1090 + return; 1091 + } 1092 + 1093 + /* 1094 + * T32 instruction size might be 32-bit or 16-bit, decide by calling 1095 + * cs_etm__t32_instr_size(). 1096 + */ 1097 + if (packet->isa == CS_ETM_ISA_T32) 1098 + sample->insn_len = cs_etm__t32_instr_size(etmq, trace_chan_id, 1099 + sample->ip); 1100 + /* Otherwise, A64 and A32 instruction size are always 32-bit. */ 1101 + else 1102 + sample->insn_len = 4; 1103 + 1104 + cs_etm__mem_access(etmq, trace_chan_id, sample->ip, 1105 + sample->insn_len, (void *)sample->insn); 1106 + } 1107 + 1079 1108 static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq, 1080 1109 struct cs_etm_traceid_queue *tidq, 1081 1110 u64 addr, u64 period) ··· 1126 1097 sample.period = period; 1127 1098 sample.cpu = tidq->packet->cpu; 1128 1099 sample.flags = tidq->prev_packet->flags; 1129 - sample.insn_len = 1; 1130 1100 sample.cpumode = event->sample.header.misc; 1101 + 1102 + cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->packet, &sample); 1131 1103 1132 1104 if (etm->synth_opts.last_branch) { 1133 1105 cs_etm__copy_last_branch_rb(etmq, tidq); ··· 1188 1158 sample.cpu = tidq->packet->cpu; 1189 1159 sample.flags = tidq->prev_packet->flags; 1190 1160 sample.cpumode = event->sample.header.misc; 1161 + 1162 + cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->prev_packet, 1163 + &sample); 1191 1164 1192 1165 /* 1193 1166 * perf report cannot handle events without a branch stack