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

perf intel-pt: Add new packets for PEBS via PT

Add 3 new packets to supports PEBS via PT, namely Block Begin Packet
(BBP), Block Item Packet (BIP) and Block End Packet (BEP). PEBS data is
encoded into multiple BIP packets that come between BBP and BEP. The BEP
packet might be associated with a FUP packet. That is indicated by using
a separate packet type (INTEL_PT_BEP_IP) similar to other packets types
with the _IP suffix.

Refer to the Intel SDM for more information about PEBS via PT:

https://software.intel.com/en-us/articles/intel-sdm
May 2019 version: Vol. 3B 18.5.5.2 PEBS output to Intel® Processor Trace

Decoding of BIP packets conflicts with single-byte TNT packets. Since
BIP packets only occur in the context of a block (i.e. between BBP and
BEP), that context must be recorded and passed to the packet decoder.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-2-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
edff7809 374d910f

+193 -9
+34 -4
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
··· 133 133 int mtc_shift; 134 134 struct intel_pt_stack stack; 135 135 enum intel_pt_pkt_state pkt_state; 136 + enum intel_pt_pkt_ctx pkt_ctx; 136 137 struct intel_pt_pkt packet; 137 138 struct intel_pt_pkt tnt; 138 139 int pkt_step; ··· 560 559 memcpy(buf + len, decoder->buf, n); 561 560 len += n; 562 561 563 - ret = intel_pt_get_packet(buf, len, &decoder->packet); 562 + ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx); 564 563 if (ret < (int)old_len) { 565 564 decoder->next_buf = decoder->buf; 566 565 decoder->next_len = decoder->len; ··· 595 594 { 596 595 struct intel_pt_pkt_info pkt_info; 597 596 const unsigned char *buf = decoder->buf; 597 + enum intel_pt_pkt_ctx pkt_ctx = decoder->pkt_ctx; 598 598 size_t len = decoder->len; 599 599 int ret; 600 600 ··· 614 612 if (!len) 615 613 return INTEL_PT_NEED_MORE_BYTES; 616 614 617 - ret = intel_pt_get_packet(buf, len, &pkt_info.packet); 615 + ret = intel_pt_get_packet(buf, len, &pkt_info.packet, 616 + &pkt_ctx); 618 617 if (!ret) 619 618 return INTEL_PT_NEED_MORE_BYTES; 620 619 if (ret < 0) ··· 690 687 case INTEL_PT_MNT: 691 688 case INTEL_PT_PTWRITE: 692 689 case INTEL_PT_PTWRITE_IP: 690 + case INTEL_PT_BBP: 691 + case INTEL_PT_BIP: 692 + case INTEL_PT_BEP: 693 + case INTEL_PT_BEP_IP: 693 694 return 0; 694 695 695 696 case INTEL_PT_MTC: ··· 886 879 } 887 880 888 881 ret = intel_pt_get_packet(decoder->buf, decoder->len, 889 - &decoder->packet); 882 + &decoder->packet, &decoder->pkt_ctx); 890 883 if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 && 891 884 decoder->len < INTEL_PT_PKT_MAX_SZ && !decoder->next_buf) { 892 885 ret = intel_pt_get_split_packet(decoder); ··· 1640 1633 case INTEL_PT_MWAIT: 1641 1634 case INTEL_PT_PWRE: 1642 1635 case INTEL_PT_PWRX: 1636 + case INTEL_PT_BBP: 1637 + case INTEL_PT_BIP: 1638 + case INTEL_PT_BEP: 1639 + case INTEL_PT_BEP_IP: 1643 1640 decoder->have_tma = false; 1644 1641 intel_pt_log("ERROR: Unexpected packet\n"); 1645 1642 err = -EAGAIN; ··· 1737 1726 case INTEL_PT_MWAIT: 1738 1727 case INTEL_PT_PWRE: 1739 1728 case INTEL_PT_PWRX: 1729 + case INTEL_PT_BBP: 1730 + case INTEL_PT_BIP: 1731 + case INTEL_PT_BEP: 1732 + case INTEL_PT_BEP_IP: 1740 1733 intel_pt_log("ERROR: Missing TIP after FUP\n"); 1741 1734 decoder->pkt_state = INTEL_PT_STATE_ERR3; 1742 1735 decoder->pkt_step = 0; ··· 2062 2047 decoder->state.pwrx_payload = decoder->packet.payload; 2063 2048 return 0; 2064 2049 2050 + case INTEL_PT_BBP: 2051 + case INTEL_PT_BIP: 2052 + case INTEL_PT_BEP: 2053 + case INTEL_PT_BEP_IP: 2054 + break; 2055 + 2065 2056 default: 2066 2057 return intel_pt_bug(decoder); 2067 2058 } ··· 2106 2085 case INTEL_PT_MWAIT: 2107 2086 case INTEL_PT_PWRE: 2108 2087 case INTEL_PT_PWRX: 2088 + case INTEL_PT_BBP: 2089 + case INTEL_PT_BIP: 2090 + case INTEL_PT_BEP: 2091 + case INTEL_PT_BEP_IP: 2109 2092 intel_pt_log("ERROR: Unexpected packet\n"); 2110 2093 err = -ENOENT; 2111 2094 goto out; ··· 2316 2291 case INTEL_PT_MWAIT: 2317 2292 case INTEL_PT_PWRE: 2318 2293 case INTEL_PT_PWRX: 2294 + case INTEL_PT_BBP: 2295 + case INTEL_PT_BIP: 2296 + case INTEL_PT_BEP: 2297 + case INTEL_PT_BEP_IP: 2319 2298 default: 2320 2299 break; 2321 2300 } ··· 2670 2641 static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc, 2671 2642 size_t *rem) 2672 2643 { 2644 + enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX; 2673 2645 struct intel_pt_pkt packet; 2674 2646 int ret; 2675 2647 2676 2648 while (len) { 2677 - ret = intel_pt_get_packet(buf, len, &packet); 2649 + ret = intel_pt_get_packet(buf, len, &packet, &ctx); 2678 2650 if (ret <= 0) 2679 2651 return false; 2680 2652 if (packet.type == INTEL_PT_TSC) {
+137 -3
tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
··· 62 62 [INTEL_PT_MWAIT] = "MWAIT", 63 63 [INTEL_PT_PWRE] = "PWRE", 64 64 [INTEL_PT_PWRX] = "PWRX", 65 + [INTEL_PT_BBP] = "BBP", 66 + [INTEL_PT_BIP] = "BIP", 67 + [INTEL_PT_BEP] = "BEP", 68 + [INTEL_PT_BEP_IP] = "BEP", 65 69 }; 66 70 67 71 const char *intel_pt_pkt_name(enum intel_pt_pkt_type type) ··· 284 280 return 7; 285 281 } 286 282 283 + static int intel_pt_get_bbp(const unsigned char *buf, size_t len, 284 + struct intel_pt_pkt *packet) 285 + { 286 + if (len < 3) 287 + return INTEL_PT_NEED_MORE_BYTES; 288 + packet->type = INTEL_PT_BBP; 289 + packet->count = buf[2] >> 7; 290 + packet->payload = buf[2] & 0x1f; 291 + return 3; 292 + } 293 + 294 + static int intel_pt_get_bip_4(const unsigned char *buf, size_t len, 295 + struct intel_pt_pkt *packet) 296 + { 297 + if (len < 5) 298 + return INTEL_PT_NEED_MORE_BYTES; 299 + packet->type = INTEL_PT_BIP; 300 + packet->count = buf[0] >> 3; 301 + memcpy_le64(&packet->payload, buf + 1, 4); 302 + return 5; 303 + } 304 + 305 + static int intel_pt_get_bip_8(const unsigned char *buf, size_t len, 306 + struct intel_pt_pkt *packet) 307 + { 308 + if (len < 9) 309 + return INTEL_PT_NEED_MORE_BYTES; 310 + packet->type = INTEL_PT_BIP; 311 + packet->count = buf[0] >> 3; 312 + memcpy_le64(&packet->payload, buf + 1, 8); 313 + return 9; 314 + } 315 + 316 + static int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet) 317 + { 318 + if (len < 2) 319 + return INTEL_PT_NEED_MORE_BYTES; 320 + packet->type = INTEL_PT_BEP; 321 + return 2; 322 + } 323 + 324 + static int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet) 325 + { 326 + if (len < 2) 327 + return INTEL_PT_NEED_MORE_BYTES; 328 + packet->type = INTEL_PT_BEP_IP; 329 + return 2; 330 + } 331 + 287 332 static int intel_pt_get_ext(const unsigned char *buf, size_t len, 288 333 struct intel_pt_pkt *packet) 289 334 { ··· 373 320 return intel_pt_get_pwre(buf, len, packet); 374 321 case 0xA2: /* PWRX */ 375 322 return intel_pt_get_pwrx(buf, len, packet); 323 + case 0x63: /* BBP */ 324 + return intel_pt_get_bbp(buf, len, packet); 325 + case 0x33: /* BEP no IP */ 326 + return intel_pt_get_bep(len, packet); 327 + case 0xb3: /* BEP with IP */ 328 + return intel_pt_get_bep_ip(len, packet); 376 329 default: 377 330 return INTEL_PT_BAD_PACKET; 378 331 } ··· 527 468 } 528 469 529 470 static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, 530 - struct intel_pt_pkt *packet) 471 + struct intel_pt_pkt *packet, 472 + enum intel_pt_pkt_ctx ctx) 531 473 { 532 474 unsigned int byte; 533 475 ··· 538 478 return INTEL_PT_NEED_MORE_BYTES; 539 479 540 480 byte = buf[0]; 481 + 482 + switch (ctx) { 483 + case INTEL_PT_NO_CTX: 484 + break; 485 + case INTEL_PT_BLK_4_CTX: 486 + if ((byte & 0x7) == 4) 487 + return intel_pt_get_bip_4(buf, len, packet); 488 + break; 489 + case INTEL_PT_BLK_8_CTX: 490 + if ((byte & 0x7) == 4) 491 + return intel_pt_get_bip_8(buf, len, packet); 492 + break; 493 + default: 494 + break; 495 + }; 496 + 541 497 if (!(byte & BIT(0))) { 542 498 if (byte == 0) 543 499 return intel_pt_get_pad(packet); ··· 592 516 } 593 517 } 594 518 519 + void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet, 520 + enum intel_pt_pkt_ctx *ctx) 521 + { 522 + switch (packet->type) { 523 + case INTEL_PT_BAD: 524 + case INTEL_PT_PAD: 525 + case INTEL_PT_TSC: 526 + case INTEL_PT_TMA: 527 + case INTEL_PT_MTC: 528 + case INTEL_PT_FUP: 529 + case INTEL_PT_CYC: 530 + case INTEL_PT_CBR: 531 + case INTEL_PT_MNT: 532 + case INTEL_PT_EXSTOP: 533 + case INTEL_PT_EXSTOP_IP: 534 + case INTEL_PT_PWRE: 535 + case INTEL_PT_PWRX: 536 + case INTEL_PT_BIP: 537 + break; 538 + case INTEL_PT_TNT: 539 + case INTEL_PT_TIP: 540 + case INTEL_PT_TIP_PGD: 541 + case INTEL_PT_TIP_PGE: 542 + case INTEL_PT_MODE_EXEC: 543 + case INTEL_PT_MODE_TSX: 544 + case INTEL_PT_PIP: 545 + case INTEL_PT_OVF: 546 + case INTEL_PT_VMCS: 547 + case INTEL_PT_TRACESTOP: 548 + case INTEL_PT_PSB: 549 + case INTEL_PT_PSBEND: 550 + case INTEL_PT_PTWRITE: 551 + case INTEL_PT_PTWRITE_IP: 552 + case INTEL_PT_MWAIT: 553 + case INTEL_PT_BEP: 554 + case INTEL_PT_BEP_IP: 555 + *ctx = INTEL_PT_NO_CTX; 556 + break; 557 + case INTEL_PT_BBP: 558 + if (packet->count) 559 + *ctx = INTEL_PT_BLK_4_CTX; 560 + else 561 + *ctx = INTEL_PT_BLK_8_CTX; 562 + break; 563 + default: 564 + break; 565 + } 566 + } 567 + 595 568 int intel_pt_get_packet(const unsigned char *buf, size_t len, 596 - struct intel_pt_pkt *packet) 569 + struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx) 597 570 { 598 571 int ret; 599 572 600 - ret = intel_pt_do_get_packet(buf, len, packet); 573 + ret = intel_pt_do_get_packet(buf, len, packet, *ctx); 601 574 if (ret > 0) { 602 575 while (ret < 8 && len > (size_t)ret && !buf[ret]) 603 576 ret += 1; 577 + intel_pt_upd_pkt_ctx(packet, ctx); 604 578 } 605 579 return ret; 606 580 } ··· 728 602 return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload); 729 603 case INTEL_PT_PTWRITE_IP: 730 604 return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload); 605 + case INTEL_PT_BEP: 731 606 case INTEL_PT_EXSTOP: 732 607 return snprintf(buf, buf_len, "%s IP:0", name); 608 + case INTEL_PT_BEP_IP: 733 609 case INTEL_PT_EXSTOP_IP: 734 610 return snprintf(buf, buf_len, "%s IP:1", name); 735 611 case INTEL_PT_MWAIT: ··· 749 621 (unsigned int)((payload >> 4) & 0xf), 750 622 (unsigned int)(payload & 0xf), 751 623 (unsigned int)((payload >> 8) & 0xf)); 624 + case INTEL_PT_BBP: 625 + return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx", 626 + name, packet->count ? "4" : "8", payload); 627 + case INTEL_PT_BIP: 628 + return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx", 629 + name, packet->count, payload); 752 630 default: 753 631 break; 754 632 }
+20 -1
tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
··· 50 50 INTEL_PT_MWAIT, 51 51 INTEL_PT_PWRE, 52 52 INTEL_PT_PWRX, 53 + INTEL_PT_BBP, 54 + INTEL_PT_BIP, 55 + INTEL_PT_BEP, 56 + INTEL_PT_BEP_IP, 53 57 }; 54 58 55 59 struct intel_pt_pkt { ··· 62 58 uint64_t payload; 63 59 }; 64 60 61 + /* 62 + * Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP 63 + * packets only occur in the context of a block (i.e. between BBP and BEP), that 64 + * context must be recorded and passed to the packet decoder. 65 + */ 66 + enum intel_pt_pkt_ctx { 67 + INTEL_PT_NO_CTX, /* BIP packets are invalid */ 68 + INTEL_PT_BLK_4_CTX, /* 4-byte BIP packets */ 69 + INTEL_PT_BLK_8_CTX, /* 8-byte BIP packets */ 70 + }; 71 + 65 72 const char *intel_pt_pkt_name(enum intel_pt_pkt_type); 66 73 67 74 int intel_pt_get_packet(const unsigned char *buf, size_t len, 68 - struct intel_pt_pkt *packet); 75 + struct intel_pt_pkt *packet, 76 + enum intel_pt_pkt_ctx *ctx); 77 + 78 + void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet, 79 + enum intel_pt_pkt_ctx *ctx); 69 80 70 81 int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, size_t len); 71 82
+2 -1
tools/perf/util/intel-pt.c
··· 177 177 int ret, pkt_len, i; 178 178 char desc[INTEL_PT_PKT_DESC_MAX]; 179 179 const char *color = PERF_COLOR_BLUE; 180 + enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX; 180 181 181 182 color_fprintf(stdout, color, 182 183 ". ... Intel Processor Trace data: size %zu bytes\n", 183 184 len); 184 185 185 186 while (len) { 186 - ret = intel_pt_get_packet(buf, len, &packet); 187 + ret = intel_pt_get_packet(buf, len, &packet, &ctx); 187 188 if (ret > 0) 188 189 pkt_len = ret; 189 190 else