0001
0002
0003
0004
0005
0006
0007 #include <stdio.h>
0008 #include <string.h>
0009 #include <endian.h>
0010 #include <byteswap.h>
0011 #include <linux/bitops.h>
0012 #include <stdarg.h>
0013
0014 #include "arm-spe-pkt-decoder.h"
0015
0016 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
0017 #define le16_to_cpu bswap_16
0018 #define le32_to_cpu bswap_32
0019 #define le64_to_cpu bswap_64
0020 #define memcpy_le64(d, s, n) do { \
0021 memcpy((d), (s), (n)); \
0022 *(d) = le64_to_cpu(*(d)); \
0023 } while (0)
0024 #else
0025 #define le16_to_cpu
0026 #define le32_to_cpu
0027 #define le64_to_cpu
0028 #define memcpy_le64 memcpy
0029 #endif
0030
0031 static const char * const arm_spe_packet_name[] = {
0032 [ARM_SPE_PAD] = "PAD",
0033 [ARM_SPE_END] = "END",
0034 [ARM_SPE_TIMESTAMP] = "TS",
0035 [ARM_SPE_ADDRESS] = "ADDR",
0036 [ARM_SPE_COUNTER] = "LAT",
0037 [ARM_SPE_CONTEXT] = "CONTEXT",
0038 [ARM_SPE_OP_TYPE] = "OP-TYPE",
0039 [ARM_SPE_EVENTS] = "EVENTS",
0040 [ARM_SPE_DATA_SOURCE] = "DATA-SOURCE",
0041 };
0042
0043 const char *arm_spe_pkt_name(enum arm_spe_pkt_type type)
0044 {
0045 return arm_spe_packet_name[type];
0046 }
0047
0048
0049
0050
0051
0052
0053
0054
0055 static unsigned int arm_spe_payload_len(unsigned char hdr)
0056 {
0057 return 1U << ((hdr & GENMASK_ULL(5, 4)) >> 4);
0058 }
0059
0060 static int arm_spe_get_payload(const unsigned char *buf, size_t len,
0061 unsigned char ext_hdr,
0062 struct arm_spe_pkt *packet)
0063 {
0064 size_t payload_len = arm_spe_payload_len(buf[ext_hdr]);
0065
0066 if (len < 1 + ext_hdr + payload_len)
0067 return ARM_SPE_NEED_MORE_BYTES;
0068
0069 buf += 1 + ext_hdr;
0070
0071 switch (payload_len) {
0072 case 1: packet->payload = *(uint8_t *)buf; break;
0073 case 2: packet->payload = le16_to_cpu(*(uint16_t *)buf); break;
0074 case 4: packet->payload = le32_to_cpu(*(uint32_t *)buf); break;
0075 case 8: packet->payload = le64_to_cpu(*(uint64_t *)buf); break;
0076 default: return ARM_SPE_BAD_PACKET;
0077 }
0078
0079 return 1 + ext_hdr + payload_len;
0080 }
0081
0082 static int arm_spe_get_pad(struct arm_spe_pkt *packet)
0083 {
0084 packet->type = ARM_SPE_PAD;
0085 return 1;
0086 }
0087
0088 static int arm_spe_get_alignment(const unsigned char *buf, size_t len,
0089 struct arm_spe_pkt *packet)
0090 {
0091 unsigned int alignment = 1 << ((buf[0] & 0xf) + 1);
0092
0093 if (len < alignment)
0094 return ARM_SPE_NEED_MORE_BYTES;
0095
0096 packet->type = ARM_SPE_PAD;
0097 return alignment - (((uintptr_t)buf) & (alignment - 1));
0098 }
0099
0100 static int arm_spe_get_end(struct arm_spe_pkt *packet)
0101 {
0102 packet->type = ARM_SPE_END;
0103 return 1;
0104 }
0105
0106 static int arm_spe_get_timestamp(const unsigned char *buf, size_t len,
0107 struct arm_spe_pkt *packet)
0108 {
0109 packet->type = ARM_SPE_TIMESTAMP;
0110 return arm_spe_get_payload(buf, len, 0, packet);
0111 }
0112
0113 static int arm_spe_get_events(const unsigned char *buf, size_t len,
0114 struct arm_spe_pkt *packet)
0115 {
0116 packet->type = ARM_SPE_EVENTS;
0117
0118
0119
0120
0121
0122
0123 packet->index = arm_spe_payload_len(buf[0]);
0124
0125 return arm_spe_get_payload(buf, len, 0, packet);
0126 }
0127
0128 static int arm_spe_get_data_source(const unsigned char *buf, size_t len,
0129 struct arm_spe_pkt *packet)
0130 {
0131 packet->type = ARM_SPE_DATA_SOURCE;
0132 return arm_spe_get_payload(buf, len, 0, packet);
0133 }
0134
0135 static int arm_spe_get_context(const unsigned char *buf, size_t len,
0136 struct arm_spe_pkt *packet)
0137 {
0138 packet->type = ARM_SPE_CONTEXT;
0139 packet->index = SPE_CTX_PKT_HDR_INDEX(buf[0]);
0140 return arm_spe_get_payload(buf, len, 0, packet);
0141 }
0142
0143 static int arm_spe_get_op_type(const unsigned char *buf, size_t len,
0144 struct arm_spe_pkt *packet)
0145 {
0146 packet->type = ARM_SPE_OP_TYPE;
0147 packet->index = SPE_OP_PKT_HDR_CLASS(buf[0]);
0148 return arm_spe_get_payload(buf, len, 0, packet);
0149 }
0150
0151 static int arm_spe_get_counter(const unsigned char *buf, size_t len,
0152 const unsigned char ext_hdr, struct arm_spe_pkt *packet)
0153 {
0154 packet->type = ARM_SPE_COUNTER;
0155
0156 if (ext_hdr)
0157 packet->index = SPE_HDR_EXTENDED_INDEX(buf[0], buf[1]);
0158 else
0159 packet->index = SPE_HDR_SHORT_INDEX(buf[0]);
0160
0161 return arm_spe_get_payload(buf, len, ext_hdr, packet);
0162 }
0163
0164 static int arm_spe_get_addr(const unsigned char *buf, size_t len,
0165 const unsigned char ext_hdr, struct arm_spe_pkt *packet)
0166 {
0167 packet->type = ARM_SPE_ADDRESS;
0168
0169 if (ext_hdr)
0170 packet->index = SPE_HDR_EXTENDED_INDEX(buf[0], buf[1]);
0171 else
0172 packet->index = SPE_HDR_SHORT_INDEX(buf[0]);
0173
0174 return arm_spe_get_payload(buf, len, ext_hdr, packet);
0175 }
0176
0177 static int arm_spe_do_get_packet(const unsigned char *buf, size_t len,
0178 struct arm_spe_pkt *packet)
0179 {
0180 unsigned int hdr;
0181 unsigned char ext_hdr = 0;
0182
0183 memset(packet, 0, sizeof(struct arm_spe_pkt));
0184
0185 if (!len)
0186 return ARM_SPE_NEED_MORE_BYTES;
0187
0188 hdr = buf[0];
0189
0190 if (hdr == SPE_HEADER0_PAD)
0191 return arm_spe_get_pad(packet);
0192
0193 if (hdr == SPE_HEADER0_END)
0194 return arm_spe_get_end(packet);
0195
0196 if (hdr == SPE_HEADER0_TIMESTAMP)
0197 return arm_spe_get_timestamp(buf, len, packet);
0198
0199 if ((hdr & SPE_HEADER0_MASK1) == SPE_HEADER0_EVENTS)
0200 return arm_spe_get_events(buf, len, packet);
0201
0202 if ((hdr & SPE_HEADER0_MASK1) == SPE_HEADER0_SOURCE)
0203 return arm_spe_get_data_source(buf, len, packet);
0204
0205 if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_CONTEXT)
0206 return arm_spe_get_context(buf, len, packet);
0207
0208 if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_OP_TYPE)
0209 return arm_spe_get_op_type(buf, len, packet);
0210
0211 if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_EXTENDED) {
0212
0213 if (len == 1)
0214 return ARM_SPE_BAD_PACKET;
0215
0216 ext_hdr = 1;
0217 hdr = buf[1];
0218 if (hdr == SPE_HEADER1_ALIGNMENT)
0219 return arm_spe_get_alignment(buf, len, packet);
0220 }
0221
0222
0223
0224
0225
0226
0227
0228 if ((hdr & SPE_HEADER0_MASK3) == SPE_HEADER0_ADDRESS)
0229 return arm_spe_get_addr(buf, len, ext_hdr, packet);
0230
0231 if ((hdr & SPE_HEADER0_MASK3) == SPE_HEADER0_COUNTER)
0232 return arm_spe_get_counter(buf, len, ext_hdr, packet);
0233
0234 return ARM_SPE_BAD_PACKET;
0235 }
0236
0237 int arm_spe_get_packet(const unsigned char *buf, size_t len,
0238 struct arm_spe_pkt *packet)
0239 {
0240 int ret;
0241
0242 ret = arm_spe_do_get_packet(buf, len, packet);
0243
0244
0245
0246 if (ret > 0 && packet->type == ARM_SPE_PAD) {
0247 while (ret < 16 && len > (size_t)ret && !buf[ret])
0248 ret += 1;
0249 }
0250 return ret;
0251 }
0252
0253 static int arm_spe_pkt_out_string(int *err, char **buf_p, size_t *blen,
0254 const char *fmt, ...)
0255 {
0256 va_list ap;
0257 int ret;
0258
0259
0260 if (err && *err)
0261 return *err;
0262
0263 va_start(ap, fmt);
0264 ret = vsnprintf(*buf_p, *blen, fmt, ap);
0265 va_end(ap);
0266
0267 if (ret < 0) {
0268 if (err && !*err)
0269 *err = ret;
0270
0271
0272
0273
0274
0275 } else if ((size_t)ret >= *blen) {
0276 (*buf_p)[*blen - 1] = '\0';
0277
0278
0279
0280
0281
0282 if (err && !*err)
0283 *err = ret;
0284 } else {
0285 *buf_p += ret;
0286 *blen -= ret;
0287 }
0288
0289 return ret;
0290 }
0291
0292 static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet,
0293 char *buf, size_t buf_len)
0294 {
0295 u64 payload = packet->payload;
0296 int err = 0;
0297
0298 arm_spe_pkt_out_string(&err, &buf, &buf_len, "EV");
0299
0300 if (payload & BIT(EV_EXCEPTION_GEN))
0301 arm_spe_pkt_out_string(&err, &buf, &buf_len, " EXCEPTION-GEN");
0302 if (payload & BIT(EV_RETIRED))
0303 arm_spe_pkt_out_string(&err, &buf, &buf_len, " RETIRED");
0304 if (payload & BIT(EV_L1D_ACCESS))
0305 arm_spe_pkt_out_string(&err, &buf, &buf_len, " L1D-ACCESS");
0306 if (payload & BIT(EV_L1D_REFILL))
0307 arm_spe_pkt_out_string(&err, &buf, &buf_len, " L1D-REFILL");
0308 if (payload & BIT(EV_TLB_ACCESS))
0309 arm_spe_pkt_out_string(&err, &buf, &buf_len, " TLB-ACCESS");
0310 if (payload & BIT(EV_TLB_WALK))
0311 arm_spe_pkt_out_string(&err, &buf, &buf_len, " TLB-REFILL");
0312 if (payload & BIT(EV_NOT_TAKEN))
0313 arm_spe_pkt_out_string(&err, &buf, &buf_len, " NOT-TAKEN");
0314 if (payload & BIT(EV_MISPRED))
0315 arm_spe_pkt_out_string(&err, &buf, &buf_len, " MISPRED");
0316 if (payload & BIT(EV_LLC_ACCESS))
0317 arm_spe_pkt_out_string(&err, &buf, &buf_len, " LLC-ACCESS");
0318 if (payload & BIT(EV_LLC_MISS))
0319 arm_spe_pkt_out_string(&err, &buf, &buf_len, " LLC-REFILL");
0320 if (payload & BIT(EV_REMOTE_ACCESS))
0321 arm_spe_pkt_out_string(&err, &buf, &buf_len, " REMOTE-ACCESS");
0322 if (payload & BIT(EV_ALIGNMENT))
0323 arm_spe_pkt_out_string(&err, &buf, &buf_len, " ALIGNMENT");
0324 if (payload & BIT(EV_PARTIAL_PREDICATE))
0325 arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-PARTIAL-PRED");
0326 if (payload & BIT(EV_EMPTY_PREDICATE))
0327 arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-EMPTY-PRED");
0328
0329 return err;
0330 }
0331
0332 static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet,
0333 char *buf, size_t buf_len)
0334 {
0335 u64 payload = packet->payload;
0336 int err = 0;
0337
0338 switch (packet->index) {
0339 case SPE_OP_PKT_HDR_CLASS_OTHER:
0340 if (SPE_OP_PKT_IS_OTHER_SVE_OP(payload)) {
0341 arm_spe_pkt_out_string(&err, &buf, &buf_len, "SVE-OTHER");
0342
0343
0344 arm_spe_pkt_out_string(&err, &buf, &buf_len, " EVLEN %d",
0345 SPE_OP_PKG_SVE_EVL(payload));
0346
0347 if (payload & SPE_OP_PKT_SVE_FP)
0348 arm_spe_pkt_out_string(&err, &buf, &buf_len, " FP");
0349 if (payload & SPE_OP_PKT_SVE_PRED)
0350 arm_spe_pkt_out_string(&err, &buf, &buf_len, " PRED");
0351 } else {
0352 arm_spe_pkt_out_string(&err, &buf, &buf_len, "OTHER");
0353 arm_spe_pkt_out_string(&err, &buf, &buf_len, " %s",
0354 payload & SPE_OP_PKT_COND ?
0355 "COND-SELECT" : "INSN-OTHER");
0356 }
0357 break;
0358 case SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC:
0359 arm_spe_pkt_out_string(&err, &buf, &buf_len,
0360 payload & 0x1 ? "ST" : "LD");
0361
0362 if (SPE_OP_PKT_IS_LDST_ATOMIC(payload)) {
0363 if (payload & SPE_OP_PKT_AT)
0364 arm_spe_pkt_out_string(&err, &buf, &buf_len, " AT");
0365 if (payload & SPE_OP_PKT_EXCL)
0366 arm_spe_pkt_out_string(&err, &buf, &buf_len, " EXCL");
0367 if (payload & SPE_OP_PKT_AR)
0368 arm_spe_pkt_out_string(&err, &buf, &buf_len, " AR");
0369 }
0370
0371 switch (SPE_OP_PKT_LDST_SUBCLASS_GET(payload)) {
0372 case SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP:
0373 arm_spe_pkt_out_string(&err, &buf, &buf_len, " SIMD-FP");
0374 break;
0375 case SPE_OP_PKT_LDST_SUBCLASS_GP_REG:
0376 arm_spe_pkt_out_string(&err, &buf, &buf_len, " GP-REG");
0377 break;
0378 case SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG:
0379 arm_spe_pkt_out_string(&err, &buf, &buf_len, " UNSPEC-REG");
0380 break;
0381 case SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG:
0382 arm_spe_pkt_out_string(&err, &buf, &buf_len, " NV-SYSREG");
0383 break;
0384 default:
0385 break;
0386 }
0387
0388 if (SPE_OP_PKT_IS_LDST_SVE(payload)) {
0389
0390 arm_spe_pkt_out_string(&err, &buf, &buf_len, " EVLEN %d",
0391 SPE_OP_PKG_SVE_EVL(payload));
0392
0393 if (payload & SPE_OP_PKT_SVE_PRED)
0394 arm_spe_pkt_out_string(&err, &buf, &buf_len, " PRED");
0395 if (payload & SPE_OP_PKT_SVE_SG)
0396 arm_spe_pkt_out_string(&err, &buf, &buf_len, " SG");
0397 }
0398 break;
0399 case SPE_OP_PKT_HDR_CLASS_BR_ERET:
0400 arm_spe_pkt_out_string(&err, &buf, &buf_len, "B");
0401
0402 if (payload & SPE_OP_PKT_COND)
0403 arm_spe_pkt_out_string(&err, &buf, &buf_len, " COND");
0404
0405 if (SPE_OP_PKT_IS_INDIRECT_BRANCH(payload))
0406 arm_spe_pkt_out_string(&err, &buf, &buf_len, " IND");
0407
0408 break;
0409 default:
0410
0411 err = -1;
0412 break;
0413 }
0414
0415 return err;
0416 }
0417
0418 static int arm_spe_pkt_desc_addr(const struct arm_spe_pkt *packet,
0419 char *buf, size_t buf_len)
0420 {
0421 int ns, el, idx = packet->index;
0422 int ch, pat;
0423 u64 payload = packet->payload;
0424 int err = 0;
0425
0426 switch (idx) {
0427 case SPE_ADDR_PKT_HDR_INDEX_INS:
0428 case SPE_ADDR_PKT_HDR_INDEX_BRANCH:
0429 ns = !!SPE_ADDR_PKT_GET_NS(payload);
0430 el = SPE_ADDR_PKT_GET_EL(payload);
0431 payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
0432 arm_spe_pkt_out_string(&err, &buf, &buf_len,
0433 "%s 0x%llx el%d ns=%d",
0434 (idx == 1) ? "TGT" : "PC", payload, el, ns);
0435 break;
0436 case SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT:
0437 arm_spe_pkt_out_string(&err, &buf, &buf_len,
0438 "VA 0x%llx", payload);
0439 break;
0440 case SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS:
0441 ns = !!SPE_ADDR_PKT_GET_NS(payload);
0442 ch = !!SPE_ADDR_PKT_GET_CH(payload);
0443 pat = SPE_ADDR_PKT_GET_PAT(payload);
0444 payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
0445 arm_spe_pkt_out_string(&err, &buf, &buf_len,
0446 "PA 0x%llx ns=%d ch=%d pat=%x",
0447 payload, ns, ch, pat);
0448 break;
0449 default:
0450
0451 err = -1;
0452 break;
0453 }
0454
0455 return err;
0456 }
0457
0458 static int arm_spe_pkt_desc_counter(const struct arm_spe_pkt *packet,
0459 char *buf, size_t buf_len)
0460 {
0461 u64 payload = packet->payload;
0462 const char *name = arm_spe_pkt_name(packet->type);
0463 int err = 0;
0464
0465 arm_spe_pkt_out_string(&err, &buf, &buf_len, "%s %d ", name,
0466 (unsigned short)payload);
0467
0468 switch (packet->index) {
0469 case SPE_CNT_PKT_HDR_INDEX_TOTAL_LAT:
0470 arm_spe_pkt_out_string(&err, &buf, &buf_len, "TOT");
0471 break;
0472 case SPE_CNT_PKT_HDR_INDEX_ISSUE_LAT:
0473 arm_spe_pkt_out_string(&err, &buf, &buf_len, "ISSUE");
0474 break;
0475 case SPE_CNT_PKT_HDR_INDEX_TRANS_LAT:
0476 arm_spe_pkt_out_string(&err, &buf, &buf_len, "XLAT");
0477 break;
0478 default:
0479 break;
0480 }
0481
0482 return err;
0483 }
0484
0485 int arm_spe_pkt_desc(const struct arm_spe_pkt *packet, char *buf,
0486 size_t buf_len)
0487 {
0488 int idx = packet->index;
0489 unsigned long long payload = packet->payload;
0490 const char *name = arm_spe_pkt_name(packet->type);
0491 char *buf_orig = buf;
0492 size_t blen = buf_len;
0493 int err = 0;
0494
0495 switch (packet->type) {
0496 case ARM_SPE_BAD:
0497 case ARM_SPE_PAD:
0498 case ARM_SPE_END:
0499 arm_spe_pkt_out_string(&err, &buf, &blen, "%s", name);
0500 break;
0501 case ARM_SPE_EVENTS:
0502 err = arm_spe_pkt_desc_event(packet, buf, buf_len);
0503 break;
0504 case ARM_SPE_OP_TYPE:
0505 err = arm_spe_pkt_desc_op_type(packet, buf, buf_len);
0506 break;
0507 case ARM_SPE_DATA_SOURCE:
0508 case ARM_SPE_TIMESTAMP:
0509 arm_spe_pkt_out_string(&err, &buf, &blen, "%s %lld", name, payload);
0510 break;
0511 case ARM_SPE_ADDRESS:
0512 err = arm_spe_pkt_desc_addr(packet, buf, buf_len);
0513 break;
0514 case ARM_SPE_CONTEXT:
0515 arm_spe_pkt_out_string(&err, &buf, &blen, "%s 0x%lx el%d",
0516 name, (unsigned long)payload, idx + 1);
0517 break;
0518 case ARM_SPE_COUNTER:
0519 err = arm_spe_pkt_desc_counter(packet, buf, buf_len);
0520 break;
0521 default:
0522
0523 err = -1;
0524 break;
0525 }
0526
0527
0528 if (err) {
0529 err = 0;
0530 arm_spe_pkt_out_string(&err, &buf_orig, &buf_len, "%s 0x%llx (%d)",
0531 name, payload, packet->index);
0532 }
0533
0534 return err;
0535 }