aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeo Yan <leo.yan@linaro.org>2019-01-29 07:28:41 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-02-06 08:00:40 -0500
commit96dce7f4f38793b80b1ddfa48d5dbc1aba40df84 (patch)
tree77e1c921fd4301ca94321cf6fa7356085ae40a54
parent03919e526b29be8d0c77142e008b397a2c089398 (diff)
perf cs-etm: Set sample flags for exception packet
The exception taken and returning are typical flow for instruction jump but it needs to be handled with exception packets. This patch is to set sample flags for exception packet. Since the exception packet contains the exception number, according to the exception number this patch makes decision for belonging to which exception types. The decoder have defined different exception number for ETMv3 and ETMv4 separately, hence this patch needs firstly decide the ETM version by using the metadata magic number, and this patch adds helper function cs_etm__get_magic() for easily getting magic number. Based on different ETM version, the exception packet contains the exception number, according to the exception number this patch makes decision for the exception belonging to which exception types. In this patch, it introduces helper function cs_etm__is_svc_instr(); for ETMv4 CS_ETMV4_EXC_CALL covers SVC, SMC and HVC cases in the single exception number, thus need to use cs_etm__is_svc_instr() to decide an exception taken for system call. Signed-off-by: Leo Yan <leo.yan@linaro.org> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org> Reviewed-by: Robert Walker <robert.walker@arm.com> 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: Suzuki K Poulouse <suzuki.poulose@arm.com> Cc: coresight ml <coresight@lists.linaro.org> Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/20190129122842.32041-8-leo.yan@linaro.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/cs-etm.c215
-rw-r--r--tools/perf/util/cs-etm.h44
2 files changed, 259 insertions, 0 deletions
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index a5497a761db7..a714b31656ea 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -97,6 +97,20 @@ static u32 cs_etm__get_v7_protocol_version(u32 etmidr)
97 return CS_ETM_PROTO_ETMV3; 97 return CS_ETM_PROTO_ETMV3;
98} 98}
99 99
100static int cs_etm__get_magic(u8 trace_chan_id, u64 *magic)
101{
102 struct int_node *inode;
103 u64 *metadata;
104
105 inode = intlist__find(traceid_list, trace_chan_id);
106 if (!inode)
107 return -EINVAL;
108
109 metadata = inode->priv;
110 *magic = metadata[CS_ETM_MAGIC];
111 return 0;
112}
113
100int cs_etm__get_cpu(u8 trace_chan_id, int *cpu) 114int cs_etm__get_cpu(u8 trace_chan_id, int *cpu)
101{ 115{
102 struct int_node *inode; 116 struct int_node *inode;
@@ -1122,10 +1136,174 @@ static int cs_etm__end_block(struct cs_etm_queue *etmq)
1122 return 0; 1136 return 0;
1123} 1137}
1124 1138
1139static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq,
1140 struct cs_etm_packet *packet,
1141 u64 end_addr)
1142{
1143 u16 instr16;
1144 u32 instr32;
1145 u64 addr;
1146
1147 switch (packet->isa) {
1148 case CS_ETM_ISA_T32:
1149 /*
1150 * The SVC of T32 is defined in ARM DDI 0487D.a, F5.1.247:
1151 *
1152 * b'15 b'8
1153 * +-----------------+--------+
1154 * | 1 1 0 1 1 1 1 1 | imm8 |
1155 * +-----------------+--------+
1156 *
1157 * According to the specifiction, it only defines SVC for T32
1158 * with 16 bits instruction and has no definition for 32bits;
1159 * so below only read 2 bytes as instruction size for T32.
1160 */
1161 addr = end_addr - 2;
1162 cs_etm__mem_access(etmq, addr, sizeof(instr16), (u8 *)&instr16);
1163 if ((instr16 & 0xFF00) == 0xDF00)
1164 return true;
1165
1166 break;
1167 case CS_ETM_ISA_A32:
1168 /*
1169 * The SVC of A32 is defined in ARM DDI 0487D.a, F5.1.247:
1170 *
1171 * b'31 b'28 b'27 b'24
1172 * +---------+---------+-------------------------+
1173 * | !1111 | 1 1 1 1 | imm24 |
1174 * +---------+---------+-------------------------+
1175 */
1176 addr = end_addr - 4;
1177 cs_etm__mem_access(etmq, addr, sizeof(instr32), (u8 *)&instr32);
1178 if ((instr32 & 0x0F000000) == 0x0F000000 &&
1179 (instr32 & 0xF0000000) != 0xF0000000)
1180 return true;
1181
1182 break;
1183 case CS_ETM_ISA_A64:
1184 /*
1185 * The SVC of A64 is defined in ARM DDI 0487D.a, C6.2.294:
1186 *
1187 * b'31 b'21 b'4 b'0
1188 * +-----------------------+---------+-----------+
1189 * | 1 1 0 1 0 1 0 0 0 0 0 | imm16 | 0 0 0 0 1 |
1190 * +-----------------------+---------+-----------+
1191 */
1192 addr = end_addr - 4;
1193 cs_etm__mem_access(etmq, addr, sizeof(instr32), (u8 *)&instr32);
1194 if ((instr32 & 0xFFE0001F) == 0xd4000001)
1195 return true;
1196
1197 break;
1198 case CS_ETM_ISA_UNKNOWN:
1199 default:
1200 break;
1201 }
1202
1203 return false;
1204}
1205
1206static bool cs_etm__is_syscall(struct cs_etm_queue *etmq, u64 magic)
1207{
1208 struct cs_etm_packet *packet = etmq->packet;
1209 struct cs_etm_packet *prev_packet = etmq->prev_packet;
1210
1211 if (magic == __perf_cs_etmv3_magic)
1212 if (packet->exception_number == CS_ETMV3_EXC_SVC)
1213 return true;
1214
1215 /*
1216 * ETMv4 exception type CS_ETMV4_EXC_CALL covers SVC, SMC and
1217 * HVC cases; need to check if it's SVC instruction based on
1218 * packet address.
1219 */
1220 if (magic == __perf_cs_etmv4_magic) {
1221 if (packet->exception_number == CS_ETMV4_EXC_CALL &&
1222 cs_etm__is_svc_instr(etmq, prev_packet,
1223 prev_packet->end_addr))
1224 return true;
1225 }
1226
1227 return false;
1228}
1229
1230static bool cs_etm__is_async_exception(struct cs_etm_queue *etmq, u64 magic)
1231{
1232 struct cs_etm_packet *packet = etmq->packet;
1233
1234 if (magic == __perf_cs_etmv3_magic)
1235 if (packet->exception_number == CS_ETMV3_EXC_DEBUG_HALT ||
1236 packet->exception_number == CS_ETMV3_EXC_ASYNC_DATA_ABORT ||
1237 packet->exception_number == CS_ETMV3_EXC_PE_RESET ||
1238 packet->exception_number == CS_ETMV3_EXC_IRQ ||
1239 packet->exception_number == CS_ETMV3_EXC_FIQ)
1240 return true;
1241
1242 if (magic == __perf_cs_etmv4_magic)
1243 if (packet->exception_number == CS_ETMV4_EXC_RESET ||
1244 packet->exception_number == CS_ETMV4_EXC_DEBUG_HALT ||
1245 packet->exception_number == CS_ETMV4_EXC_SYSTEM_ERROR ||
1246 packet->exception_number == CS_ETMV4_EXC_INST_DEBUG ||
1247 packet->exception_number == CS_ETMV4_EXC_DATA_DEBUG ||
1248 packet->exception_number == CS_ETMV4_EXC_IRQ ||
1249 packet->exception_number == CS_ETMV4_EXC_FIQ)
1250 return true;
1251
1252 return false;
1253}
1254
1255static bool cs_etm__is_sync_exception(struct cs_etm_queue *etmq, u64 magic)
1256{
1257 struct cs_etm_packet *packet = etmq->packet;
1258 struct cs_etm_packet *prev_packet = etmq->prev_packet;
1259
1260 if (magic == __perf_cs_etmv3_magic)
1261 if (packet->exception_number == CS_ETMV3_EXC_SMC ||
1262 packet->exception_number == CS_ETMV3_EXC_HYP ||
1263 packet->exception_number == CS_ETMV3_EXC_JAZELLE_THUMBEE ||
1264 packet->exception_number == CS_ETMV3_EXC_UNDEFINED_INSTR ||
1265 packet->exception_number == CS_ETMV3_EXC_PREFETCH_ABORT ||
1266 packet->exception_number == CS_ETMV3_EXC_DATA_FAULT ||
1267 packet->exception_number == CS_ETMV3_EXC_GENERIC)
1268 return true;
1269
1270 if (magic == __perf_cs_etmv4_magic) {
1271 if (packet->exception_number == CS_ETMV4_EXC_TRAP ||
1272 packet->exception_number == CS_ETMV4_EXC_ALIGNMENT ||
1273 packet->exception_number == CS_ETMV4_EXC_INST_FAULT ||
1274 packet->exception_number == CS_ETMV4_EXC_DATA_FAULT)
1275 return true;
1276
1277 /*
1278 * For CS_ETMV4_EXC_CALL, except SVC other instructions
1279 * (SMC, HVC) are taken as sync exceptions.
1280 */
1281 if (packet->exception_number == CS_ETMV4_EXC_CALL &&
1282 !cs_etm__is_svc_instr(etmq, prev_packet,
1283 prev_packet->end_addr))
1284 return true;
1285
1286 /*
1287 * ETMv4 has 5 bits for exception number; if the numbers
1288 * are in the range ( CS_ETMV4_EXC_FIQ, CS_ETMV4_EXC_END ]
1289 * they are implementation defined exceptions.
1290 *
1291 * For this case, simply take it as sync exception.
1292 */
1293 if (packet->exception_number > CS_ETMV4_EXC_FIQ &&
1294 packet->exception_number <= CS_ETMV4_EXC_END)
1295 return true;
1296 }
1297
1298 return false;
1299}
1300
1125static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq) 1301static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq)
1126{ 1302{
1127 struct cs_etm_packet *packet = etmq->packet; 1303 struct cs_etm_packet *packet = etmq->packet;
1128 struct cs_etm_packet *prev_packet = etmq->prev_packet; 1304 struct cs_etm_packet *prev_packet = etmq->prev_packet;
1305 u64 magic;
1306 int ret;
1129 1307
1130 switch (packet->sample_type) { 1308 switch (packet->sample_type) {
1131 case CS_ETM_RANGE: 1309 case CS_ETM_RANGE:
@@ -1206,6 +1384,43 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq)
1206 PERF_IP_FLAG_TRACE_END; 1384 PERF_IP_FLAG_TRACE_END;
1207 break; 1385 break;
1208 case CS_ETM_EXCEPTION: 1386 case CS_ETM_EXCEPTION:
1387 ret = cs_etm__get_magic(packet->trace_chan_id, &magic);
1388 if (ret)
1389 return ret;
1390
1391 /* The exception is for system call. */
1392 if (cs_etm__is_syscall(etmq, magic))
1393 packet->flags = PERF_IP_FLAG_BRANCH |
1394 PERF_IP_FLAG_CALL |
1395 PERF_IP_FLAG_SYSCALLRET;
1396 /*
1397 * The exceptions are triggered by external signals from bus,
1398 * interrupt controller, debug module, PE reset or halt.
1399 */
1400 else if (cs_etm__is_async_exception(etmq, magic))
1401 packet->flags = PERF_IP_FLAG_BRANCH |
1402 PERF_IP_FLAG_CALL |
1403 PERF_IP_FLAG_ASYNC |
1404 PERF_IP_FLAG_INTERRUPT;
1405 /*
1406 * Otherwise, exception is caused by trap, instruction &
1407 * data fault, or alignment errors.
1408 */
1409 else if (cs_etm__is_sync_exception(etmq, magic))
1410 packet->flags = PERF_IP_FLAG_BRANCH |
1411 PERF_IP_FLAG_CALL |
1412 PERF_IP_FLAG_INTERRUPT;
1413
1414 /*
1415 * When the exception packet is inserted, since exception
1416 * packet is not used standalone for generating samples
1417 * and it's affiliation to the previous instruction range
1418 * packet; so set previous range packet flags to tell perf
1419 * it is an exception taken branch.
1420 */
1421 if (prev_packet->sample_type == CS_ETM_RANGE)
1422 prev_packet->flags = packet->flags;
1423 break;
1209 case CS_ETM_EXCEPTION_RET: 1424 case CS_ETM_EXCEPTION_RET:
1210 case CS_ETM_EMPTY: 1425 case CS_ETM_EMPTY:
1211 default: 1426 default:
diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
index fb5fc6538b7f..d76126e0e3d0 100644
--- a/tools/perf/util/cs-etm.h
+++ b/tools/perf/util/cs-etm.h
@@ -53,6 +53,50 @@ enum {
53 CS_ETMV4_PRIV_MAX, 53 CS_ETMV4_PRIV_MAX,
54}; 54};
55 55
56/*
57 * ETMv3 exception encoding number:
58 * See Embedded Trace Macrocell spcification (ARM IHI 0014Q)
59 * table 7-12 Encoding of Exception[3:0] for non-ARMv7-M processors.
60 */
61enum {
62 CS_ETMV3_EXC_NONE = 0,
63 CS_ETMV3_EXC_DEBUG_HALT = 1,
64 CS_ETMV3_EXC_SMC = 2,
65 CS_ETMV3_EXC_HYP = 3,
66 CS_ETMV3_EXC_ASYNC_DATA_ABORT = 4,
67 CS_ETMV3_EXC_JAZELLE_THUMBEE = 5,
68 CS_ETMV3_EXC_PE_RESET = 8,
69 CS_ETMV3_EXC_UNDEFINED_INSTR = 9,
70 CS_ETMV3_EXC_SVC = 10,
71 CS_ETMV3_EXC_PREFETCH_ABORT = 11,
72 CS_ETMV3_EXC_DATA_FAULT = 12,
73 CS_ETMV3_EXC_GENERIC = 13,
74 CS_ETMV3_EXC_IRQ = 14,
75 CS_ETMV3_EXC_FIQ = 15,
76};
77
78/*
79 * ETMv4 exception encoding number:
80 * See ARM Embedded Trace Macrocell Architecture Specification (ARM IHI 0064D)
81 * table 6-12 Possible values for the TYPE field in an Exception instruction
82 * trace packet, for ARMv7-A/R and ARMv8-A/R PEs.
83 */
84enum {
85 CS_ETMV4_EXC_RESET = 0,
86 CS_ETMV4_EXC_DEBUG_HALT = 1,
87 CS_ETMV4_EXC_CALL = 2,
88 CS_ETMV4_EXC_TRAP = 3,
89 CS_ETMV4_EXC_SYSTEM_ERROR = 4,
90 CS_ETMV4_EXC_INST_DEBUG = 6,
91 CS_ETMV4_EXC_DATA_DEBUG = 7,
92 CS_ETMV4_EXC_ALIGNMENT = 10,
93 CS_ETMV4_EXC_INST_FAULT = 11,
94 CS_ETMV4_EXC_DATA_FAULT = 12,
95 CS_ETMV4_EXC_IRQ = 14,
96 CS_ETMV4_EXC_FIQ = 15,
97 CS_ETMV4_EXC_END = 31,
98};
99
56/* RB tree for quick conversion between traceID and metadata pointers */ 100/* RB tree for quick conversion between traceID and metadata pointers */
57struct intlist *traceid_list; 101struct intlist *traceid_list;
58 102