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