arm-spe-pkt-decoder.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Arm Statistical Profiling Extensions (SPE) support
  4. * Copyright (c) 2017-2018, Arm Ltd.
  5. */
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <endian.h>
  9. #include <byteswap.h>
  10. #include <linux/bitops.h>
  11. #include <stdarg.h>
  12. #include <linux/kernel.h>
  13. #include <linux/unaligned.h>
  14. #include "arm-spe-pkt-decoder.h"
  15. static const char * const arm_spe_packet_name[] = {
  16. [ARM_SPE_PAD] = "PAD",
  17. [ARM_SPE_END] = "END",
  18. [ARM_SPE_TIMESTAMP] = "TS",
  19. [ARM_SPE_ADDRESS] = "ADDR",
  20. [ARM_SPE_COUNTER] = "LAT",
  21. [ARM_SPE_CONTEXT] = "CONTEXT",
  22. [ARM_SPE_OP_TYPE] = "OP-TYPE",
  23. [ARM_SPE_EVENTS] = "EVENTS",
  24. [ARM_SPE_DATA_SOURCE] = "DATA-SOURCE",
  25. };
  26. const char *arm_spe_pkt_name(enum arm_spe_pkt_type type)
  27. {
  28. return arm_spe_packet_name[type];
  29. }
  30. /*
  31. * Extracts the field "sz" from header bits and converts to bytes:
  32. * 00 : byte (1)
  33. * 01 : halfword (2)
  34. * 10 : word (4)
  35. * 11 : doubleword (8)
  36. */
  37. static unsigned int arm_spe_payload_len(unsigned char hdr)
  38. {
  39. return 1U << ((hdr & GENMASK_ULL(5, 4)) >> 4);
  40. }
  41. static int arm_spe_get_payload(const unsigned char *buf, size_t len,
  42. unsigned char ext_hdr,
  43. struct arm_spe_pkt *packet)
  44. {
  45. size_t payload_len = arm_spe_payload_len(buf[ext_hdr]);
  46. if (len < 1 + ext_hdr + payload_len)
  47. return ARM_SPE_NEED_MORE_BYTES;
  48. buf += 1 + ext_hdr;
  49. switch (payload_len) {
  50. case 1: packet->payload = *(uint8_t *)buf; break;
  51. case 2: packet->payload = get_unaligned_le16(buf); break;
  52. case 4: packet->payload = get_unaligned_le32(buf); break;
  53. case 8: packet->payload = get_unaligned_le64(buf); break;
  54. default: return ARM_SPE_BAD_PACKET;
  55. }
  56. return 1 + ext_hdr + payload_len;
  57. }
  58. static int arm_spe_get_pad(struct arm_spe_pkt *packet)
  59. {
  60. packet->type = ARM_SPE_PAD;
  61. return 1;
  62. }
  63. static int arm_spe_get_alignment(const unsigned char *buf, size_t len,
  64. struct arm_spe_pkt *packet)
  65. {
  66. unsigned int alignment = 1 << ((buf[0] & 0xf) + 1);
  67. if (len < alignment)
  68. return ARM_SPE_NEED_MORE_BYTES;
  69. packet->type = ARM_SPE_PAD;
  70. return alignment - (((uintptr_t)buf) & (alignment - 1));
  71. }
  72. static int arm_spe_get_end(struct arm_spe_pkt *packet)
  73. {
  74. packet->type = ARM_SPE_END;
  75. return 1;
  76. }
  77. static int arm_spe_get_timestamp(const unsigned char *buf, size_t len,
  78. struct arm_spe_pkt *packet)
  79. {
  80. packet->type = ARM_SPE_TIMESTAMP;
  81. return arm_spe_get_payload(buf, len, 0, packet);
  82. }
  83. static int arm_spe_get_events(const unsigned char *buf, size_t len,
  84. struct arm_spe_pkt *packet)
  85. {
  86. packet->type = ARM_SPE_EVENTS;
  87. /* we use index to identify Events with a less number of
  88. * comparisons in arm_spe_pkt_desc(): E.g., the LLC-ACCESS,
  89. * LLC-REFILL, and REMOTE-ACCESS events are identified if
  90. * index > 1.
  91. */
  92. packet->index = arm_spe_payload_len(buf[0]);
  93. return arm_spe_get_payload(buf, len, 0, packet);
  94. }
  95. static int arm_spe_get_data_source(const unsigned char *buf, size_t len,
  96. struct arm_spe_pkt *packet)
  97. {
  98. packet->type = ARM_SPE_DATA_SOURCE;
  99. return arm_spe_get_payload(buf, len, 0, packet);
  100. }
  101. static int arm_spe_get_context(const unsigned char *buf, size_t len,
  102. struct arm_spe_pkt *packet)
  103. {
  104. packet->type = ARM_SPE_CONTEXT;
  105. packet->index = SPE_CTX_PKT_HDR_INDEX(buf[0]);
  106. return arm_spe_get_payload(buf, len, 0, packet);
  107. }
  108. static int arm_spe_get_op_type(const unsigned char *buf, size_t len,
  109. struct arm_spe_pkt *packet)
  110. {
  111. packet->type = ARM_SPE_OP_TYPE;
  112. packet->index = SPE_OP_PKT_HDR_CLASS(buf[0]);
  113. return arm_spe_get_payload(buf, len, 0, packet);
  114. }
  115. static int arm_spe_get_counter(const unsigned char *buf, size_t len,
  116. const unsigned char ext_hdr, struct arm_spe_pkt *packet)
  117. {
  118. packet->type = ARM_SPE_COUNTER;
  119. if (ext_hdr)
  120. packet->index = SPE_HDR_EXTENDED_INDEX(buf[0], buf[1]);
  121. else
  122. packet->index = SPE_HDR_SHORT_INDEX(buf[0]);
  123. return arm_spe_get_payload(buf, len, ext_hdr, packet);
  124. }
  125. static int arm_spe_get_addr(const unsigned char *buf, size_t len,
  126. const unsigned char ext_hdr, struct arm_spe_pkt *packet)
  127. {
  128. packet->type = ARM_SPE_ADDRESS;
  129. if (ext_hdr)
  130. packet->index = SPE_HDR_EXTENDED_INDEX(buf[0], buf[1]);
  131. else
  132. packet->index = SPE_HDR_SHORT_INDEX(buf[0]);
  133. return arm_spe_get_payload(buf, len, ext_hdr, packet);
  134. }
  135. static int arm_spe_do_get_packet(const unsigned char *buf, size_t len,
  136. struct arm_spe_pkt *packet)
  137. {
  138. unsigned int hdr;
  139. unsigned char ext_hdr = 0;
  140. memset(packet, 0, sizeof(struct arm_spe_pkt));
  141. if (!len)
  142. return ARM_SPE_NEED_MORE_BYTES;
  143. hdr = buf[0];
  144. if (hdr == SPE_HEADER0_PAD)
  145. return arm_spe_get_pad(packet);
  146. if (hdr == SPE_HEADER0_END) /* no timestamp at end of record */
  147. return arm_spe_get_end(packet);
  148. if (hdr == SPE_HEADER0_TIMESTAMP)
  149. return arm_spe_get_timestamp(buf, len, packet);
  150. if ((hdr & SPE_HEADER0_MASK1) == SPE_HEADER0_EVENTS)
  151. return arm_spe_get_events(buf, len, packet);
  152. if ((hdr & SPE_HEADER0_MASK1) == SPE_HEADER0_SOURCE)
  153. return arm_spe_get_data_source(buf, len, packet);
  154. if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_CONTEXT)
  155. return arm_spe_get_context(buf, len, packet);
  156. if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_OP_TYPE)
  157. return arm_spe_get_op_type(buf, len, packet);
  158. if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_EXTENDED) {
  159. /* 16-bit extended format header */
  160. if (len == 1)
  161. return ARM_SPE_BAD_PACKET;
  162. ext_hdr = 1;
  163. hdr = buf[1];
  164. if (hdr == SPE_HEADER1_ALIGNMENT)
  165. return arm_spe_get_alignment(buf, len, packet);
  166. }
  167. /*
  168. * The short format header's byte 0 or the extended format header's
  169. * byte 1 has been assigned to 'hdr', which uses the same encoding for
  170. * address packet and counter packet, so don't need to distinguish if
  171. * it's short format or extended format and handle in once.
  172. */
  173. if ((hdr & SPE_HEADER0_MASK3) == SPE_HEADER0_ADDRESS)
  174. return arm_spe_get_addr(buf, len, ext_hdr, packet);
  175. if ((hdr & SPE_HEADER0_MASK3) == SPE_HEADER0_COUNTER)
  176. return arm_spe_get_counter(buf, len, ext_hdr, packet);
  177. return ARM_SPE_BAD_PACKET;
  178. }
  179. int arm_spe_get_packet(const unsigned char *buf, size_t len,
  180. struct arm_spe_pkt *packet)
  181. {
  182. int ret;
  183. ret = arm_spe_do_get_packet(buf, len, packet);
  184. /* put multiple consecutive PADs on the same line, up to
  185. * the fixed-width output format of 16 bytes per line.
  186. */
  187. if (ret > 0 && packet->type == ARM_SPE_PAD) {
  188. while (ret < 16 && len > (size_t)ret && !buf[ret])
  189. ret += 1;
  190. }
  191. return ret;
  192. }
  193. static int arm_spe_pkt_out_string(int *err, char **buf_p, size_t *blen,
  194. const char *fmt, ...)
  195. {
  196. va_list ap;
  197. int ret;
  198. /* Bail out if any error occurred */
  199. if (err && *err)
  200. return *err;
  201. va_start(ap, fmt);
  202. ret = vsnprintf(*buf_p, *blen, fmt, ap);
  203. va_end(ap);
  204. if (ret < 0) {
  205. if (err && !*err)
  206. *err = ret;
  207. /*
  208. * A return value of *blen or more means that the output was
  209. * truncated and the buffer is overrun.
  210. */
  211. } else if ((size_t)ret >= *blen) {
  212. (*buf_p)[*blen - 1] = '\0';
  213. /*
  214. * Set *err to 'ret' to avoid overflow if tries to
  215. * fill this buffer sequentially.
  216. */
  217. if (err && !*err)
  218. *err = ret;
  219. } else {
  220. *buf_p += ret;
  221. *blen -= ret;
  222. }
  223. return ret;
  224. }
  225. static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet,
  226. char *buf, size_t buf_len)
  227. {
  228. u64 payload = packet->payload;
  229. int err = 0;
  230. arm_spe_pkt_out_string(&err, &buf, &buf_len, "EV");
  231. if (payload & BIT(EV_EXCEPTION_GEN))
  232. arm_spe_pkt_out_string(&err, &buf, &buf_len, " EXCEPTION-GEN");
  233. if (payload & BIT(EV_RETIRED))
  234. arm_spe_pkt_out_string(&err, &buf, &buf_len, " RETIRED");
  235. if (payload & BIT(EV_L1D_ACCESS))
  236. arm_spe_pkt_out_string(&err, &buf, &buf_len, " L1D-ACCESS");
  237. if (payload & BIT(EV_L1D_REFILL))
  238. arm_spe_pkt_out_string(&err, &buf, &buf_len, " L1D-REFILL");
  239. if (payload & BIT(EV_TLB_ACCESS))
  240. arm_spe_pkt_out_string(&err, &buf, &buf_len, " TLB-ACCESS");
  241. if (payload & BIT(EV_TLB_WALK))
  242. arm_spe_pkt_out_string(&err, &buf, &buf_len, " TLB-REFILL");
  243. if (payload & BIT(EV_NOT_TAKEN))
  244. arm_spe_pkt_out_string(&err, &buf, &buf_len, " NOT-TAKEN");
  245. if (payload & BIT(EV_MISPRED))
  246. arm_spe_pkt_out_string(&err, &buf, &buf_len, " MISPRED");
  247. if (payload & BIT(EV_LLC_ACCESS))
  248. arm_spe_pkt_out_string(&err, &buf, &buf_len, " LLC-ACCESS");
  249. if (payload & BIT(EV_LLC_MISS))
  250. arm_spe_pkt_out_string(&err, &buf, &buf_len, " LLC-REFILL");
  251. if (payload & BIT(EV_REMOTE_ACCESS))
  252. arm_spe_pkt_out_string(&err, &buf, &buf_len, " REMOTE-ACCESS");
  253. if (payload & BIT(EV_ALIGNMENT))
  254. arm_spe_pkt_out_string(&err, &buf, &buf_len, " ALIGNMENT");
  255. if (payload & BIT(EV_TRANSACTIONAL))
  256. arm_spe_pkt_out_string(&err, &buf, &buf_len, " TXN");
  257. if (payload & BIT(EV_PARTIAL_PREDICATE))
  258. arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-PARTIAL-PRED");
  259. if (payload & BIT(EV_EMPTY_PREDICATE))
  260. arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-EMPTY-PRED");
  261. if (payload & BIT(EV_L2D_ACCESS))
  262. arm_spe_pkt_out_string(&err, &buf, &buf_len, " L2D-ACCESS");
  263. if (payload & BIT(EV_L2D_MISS))
  264. arm_spe_pkt_out_string(&err, &buf, &buf_len, " L2D-MISS");
  265. if (payload & BIT(EV_CACHE_DATA_MODIFIED))
  266. arm_spe_pkt_out_string(&err, &buf, &buf_len, " HITM");
  267. if (payload & BIT(EV_RECENTLY_FETCHED))
  268. arm_spe_pkt_out_string(&err, &buf, &buf_len, " LFB");
  269. if (payload & BIT(EV_DATA_SNOOPED))
  270. arm_spe_pkt_out_string(&err, &buf, &buf_len, " SNOOPED");
  271. if (payload & BIT(EV_STREAMING_SVE_MODE))
  272. arm_spe_pkt_out_string(&err, &buf, &buf_len, " STREAMING-SVE");
  273. if (payload & BIT(EV_SMCU))
  274. arm_spe_pkt_out_string(&err, &buf, &buf_len, " SMCU");
  275. return err;
  276. }
  277. static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet,
  278. char *buf, size_t buf_len)
  279. {
  280. u64 payload = packet->payload;
  281. int err = 0;
  282. switch (packet->index) {
  283. case SPE_OP_PKT_HDR_CLASS_OTHER:
  284. if (SPE_OP_PKT_OTHER_SUBCLASS_SVE(payload)) {
  285. arm_spe_pkt_out_string(&err, &buf, &buf_len, "SVE-OTHER");
  286. /* SVE effective vector length */
  287. arm_spe_pkt_out_string(&err, &buf, &buf_len, " EVLEN %d",
  288. SPE_OP_PKG_SVE_EVL(payload));
  289. if (payload & SPE_OP_PKT_SVE_FP)
  290. arm_spe_pkt_out_string(&err, &buf, &buf_len, " FP");
  291. if (payload & SPE_OP_PKT_SVE_PRED)
  292. arm_spe_pkt_out_string(&err, &buf, &buf_len, " PRED");
  293. } else if (SPE_OP_PKT_OTHER_SUBCLASS_SME(payload)) {
  294. arm_spe_pkt_out_string(&err, &buf, &buf_len, "SME-OTHER");
  295. /* SME effective vector length or tile size */
  296. arm_spe_pkt_out_string(&err, &buf, &buf_len, " ETS %d",
  297. SPE_OP_PKG_SME_ETS(payload));
  298. if (payload & SPE_OP_PKT_OTHER_FP)
  299. arm_spe_pkt_out_string(&err, &buf, &buf_len, " FP");
  300. } else if (SPE_OP_PKT_OTHER_SUBCLASS_OTHER(payload)) {
  301. arm_spe_pkt_out_string(&err, &buf, &buf_len, "OTHER");
  302. if (payload & SPE_OP_PKT_OTHER_ASE)
  303. arm_spe_pkt_out_string(&err, &buf, &buf_len, " ASE");
  304. if (payload & SPE_OP_PKT_OTHER_FP)
  305. arm_spe_pkt_out_string(&err, &buf, &buf_len, " FP");
  306. arm_spe_pkt_out_string(&err, &buf, &buf_len, " %s",
  307. payload & SPE_OP_PKT_COND ?
  308. "COND-SELECT" : "INSN-OTHER");
  309. }
  310. break;
  311. case SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC:
  312. arm_spe_pkt_out_string(&err, &buf, &buf_len,
  313. payload & 0x1 ? "ST" : "LD");
  314. if (SPE_OP_PKT_LDST_SUBCLASS_EXTENDED(payload)) {
  315. if (payload & SPE_OP_PKT_AT)
  316. arm_spe_pkt_out_string(&err, &buf, &buf_len, " AT");
  317. if (payload & SPE_OP_PKT_EXCL)
  318. arm_spe_pkt_out_string(&err, &buf, &buf_len, " EXCL");
  319. if (payload & SPE_OP_PKT_AR)
  320. arm_spe_pkt_out_string(&err, &buf, &buf_len, " AR");
  321. } else if (SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(payload)) {
  322. arm_spe_pkt_out_string(&err, &buf, &buf_len, " SIMD-FP");
  323. } else if (SPE_OP_PKT_LDST_SUBCLASS_GP_REG(payload)) {
  324. arm_spe_pkt_out_string(&err, &buf, &buf_len, " GP-REG");
  325. } else if (SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG(payload)) {
  326. arm_spe_pkt_out_string(&err, &buf, &buf_len, " UNSPEC-REG");
  327. } else if (SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG(payload)) {
  328. arm_spe_pkt_out_string(&err, &buf, &buf_len, " NV-SYSREG");
  329. } else if (SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG(payload)) {
  330. arm_spe_pkt_out_string(&err, &buf, &buf_len, " MTE-TAG");
  331. } else if (SPE_OP_PKT_LDST_SUBCLASS_MEMCPY(payload)) {
  332. arm_spe_pkt_out_string(&err, &buf, &buf_len, " MEMCPY");
  333. } else if (SPE_OP_PKT_LDST_SUBCLASS_MEMSET(payload)) {
  334. arm_spe_pkt_out_string(&err, &buf, &buf_len, " MEMSET");
  335. } else if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) {
  336. arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-SME-REG");
  337. /* SVE effective vector length */
  338. arm_spe_pkt_out_string(&err, &buf, &buf_len, " EVLEN %d",
  339. SPE_OP_PKG_SVE_EVL(payload));
  340. if (payload & SPE_OP_PKT_SVE_PRED)
  341. arm_spe_pkt_out_string(&err, &buf, &buf_len, " PRED");
  342. if (payload & SPE_OP_PKT_SVE_SG)
  343. arm_spe_pkt_out_string(&err, &buf, &buf_len, " SG");
  344. } else if (SPE_OP_PKT_LDST_SUBCLASS_GCS(payload)) {
  345. arm_spe_pkt_out_string(&err, &buf, &buf_len, " GCS");
  346. if (payload & SPE_OP_PKT_GCS_COMM)
  347. arm_spe_pkt_out_string(&err, &buf, &buf_len, " COMM");
  348. }
  349. break;
  350. case SPE_OP_PKT_HDR_CLASS_BR_ERET:
  351. arm_spe_pkt_out_string(&err, &buf, &buf_len, "B");
  352. if (payload & SPE_OP_PKT_COND)
  353. arm_spe_pkt_out_string(&err, &buf, &buf_len, " COND");
  354. if (payload & SPE_OP_PKT_INDIRECT_BRANCH)
  355. arm_spe_pkt_out_string(&err, &buf, &buf_len, " IND");
  356. if (payload & SPE_OP_PKT_GCS)
  357. arm_spe_pkt_out_string(&err, &buf, &buf_len, " GCS");
  358. if (SPE_OP_PKT_CR_BL(payload))
  359. arm_spe_pkt_out_string(&err, &buf, &buf_len, " CR-BL");
  360. if (SPE_OP_PKT_CR_RET(payload))
  361. arm_spe_pkt_out_string(&err, &buf, &buf_len, " CR-RET");
  362. if (SPE_OP_PKT_CR_NON_BL_RET(payload))
  363. arm_spe_pkt_out_string(&err, &buf, &buf_len, " CR-NON-BL-RET");
  364. break;
  365. default:
  366. /* Unknown index */
  367. err = -1;
  368. break;
  369. }
  370. return err;
  371. }
  372. static int arm_spe_pkt_desc_addr(const struct arm_spe_pkt *packet,
  373. char *buf, size_t buf_len)
  374. {
  375. int ns, el, idx = packet->index;
  376. int ch, pat;
  377. u64 payload = packet->payload;
  378. int err = 0;
  379. static const char *idx_name[] = {"PC", "TGT", "VA", "PA", "PBT"};
  380. switch (idx) {
  381. case SPE_ADDR_PKT_HDR_INDEX_INS:
  382. case SPE_ADDR_PKT_HDR_INDEX_BRANCH:
  383. case SPE_ADDR_PKT_HDR_INDEX_PREV_BRANCH:
  384. ns = !!SPE_ADDR_PKT_GET_NS(payload);
  385. el = SPE_ADDR_PKT_GET_EL(payload);
  386. payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
  387. arm_spe_pkt_out_string(&err, &buf, &buf_len,
  388. "%s 0x%llx el%d ns=%d",
  389. idx_name[idx], payload, el, ns);
  390. break;
  391. case SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT:
  392. arm_spe_pkt_out_string(&err, &buf, &buf_len,
  393. "VA 0x%llx", payload);
  394. break;
  395. case SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS:
  396. ns = !!SPE_ADDR_PKT_GET_NS(payload);
  397. ch = !!SPE_ADDR_PKT_GET_CH(payload);
  398. pat = SPE_ADDR_PKT_GET_PAT(payload);
  399. payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
  400. arm_spe_pkt_out_string(&err, &buf, &buf_len,
  401. "PA 0x%llx ns=%d ch=%d pat=%x",
  402. payload, ns, ch, pat);
  403. break;
  404. default:
  405. /* Unknown index */
  406. err = -1;
  407. break;
  408. }
  409. return err;
  410. }
  411. static int arm_spe_pkt_desc_counter(const struct arm_spe_pkt *packet,
  412. char *buf, size_t buf_len)
  413. {
  414. u64 payload = packet->payload;
  415. const char *name = arm_spe_pkt_name(packet->type);
  416. int err = 0;
  417. arm_spe_pkt_out_string(&err, &buf, &buf_len, "%s %d ", name,
  418. (unsigned short)payload);
  419. switch (packet->index) {
  420. case SPE_CNT_PKT_HDR_INDEX_TOTAL_LAT:
  421. arm_spe_pkt_out_string(&err, &buf, &buf_len, "TOT");
  422. break;
  423. case SPE_CNT_PKT_HDR_INDEX_ISSUE_LAT:
  424. arm_spe_pkt_out_string(&err, &buf, &buf_len, "ISSUE");
  425. break;
  426. case SPE_CNT_PKT_HDR_INDEX_TRANS_LAT:
  427. arm_spe_pkt_out_string(&err, &buf, &buf_len, "XLAT");
  428. break;
  429. default:
  430. break;
  431. }
  432. return err;
  433. }
  434. int arm_spe_pkt_desc(const struct arm_spe_pkt *packet, char *buf,
  435. size_t buf_len)
  436. {
  437. int idx = packet->index;
  438. unsigned long long payload = packet->payload;
  439. const char *name = arm_spe_pkt_name(packet->type);
  440. char *buf_orig = buf;
  441. size_t blen = buf_len;
  442. int err = 0;
  443. switch (packet->type) {
  444. case ARM_SPE_BAD:
  445. case ARM_SPE_PAD:
  446. case ARM_SPE_END:
  447. arm_spe_pkt_out_string(&err, &buf, &blen, "%s", name);
  448. break;
  449. case ARM_SPE_EVENTS:
  450. err = arm_spe_pkt_desc_event(packet, buf, buf_len);
  451. break;
  452. case ARM_SPE_OP_TYPE:
  453. err = arm_spe_pkt_desc_op_type(packet, buf, buf_len);
  454. break;
  455. case ARM_SPE_DATA_SOURCE:
  456. case ARM_SPE_TIMESTAMP:
  457. arm_spe_pkt_out_string(&err, &buf, &blen, "%s %lld", name, payload);
  458. break;
  459. case ARM_SPE_ADDRESS:
  460. err = arm_spe_pkt_desc_addr(packet, buf, buf_len);
  461. break;
  462. case ARM_SPE_CONTEXT:
  463. arm_spe_pkt_out_string(&err, &buf, &blen, "%s 0x%lx el%d",
  464. name, (unsigned long)payload, idx + 1);
  465. break;
  466. case ARM_SPE_COUNTER:
  467. err = arm_spe_pkt_desc_counter(packet, buf, buf_len);
  468. break;
  469. default:
  470. /* Unknown packet type */
  471. err = -1;
  472. break;
  473. }
  474. /* Output raw data if detect any error */
  475. if (err) {
  476. err = 0;
  477. arm_spe_pkt_out_string(&err, &buf_orig, &buf_len, "%s 0x%llx (%d)",
  478. name, payload, packet->index);
  479. }
  480. return err;
  481. }