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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf updates from Thomas Gleixner:
"A larger set of perf updates.

Not all of them are strictly fixes, but that's solely the tip
maintainers fault as they let the timely -rc1 pull request fall
through the cracks for various reasons including travel. So I'm
sending this nevertheless because rebasing and distangling fixes and
updates would be a mess and risky as well. As of tomorrow, a strict
fixes separation is happening again. Sorry for the slip-up.

Kernel:

- Handle RECORD_MMAP vs. RECORD_MMAP2 correctly so different
consumers of the mmap event get what they requested.

Tools:

- A larger set of updates to perf record/report/scripts vs. time
stamp handling

- More Python3 fixups

- A pile of memory leak plumbing

- perf BPF improvements and fixes

- Finalize the perf.data directory storage"

[ Note: the kernel part is strictly a fix, the updates are purely to
tooling - Linus ]

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (75 commits)
perf bpf: Show more BPF program info in print_bpf_prog_info()
perf bpf: Extract logic to create program names from perf_event__synthesize_one_bpf_prog()
perf tools: Save bpf_prog_info and BTF of new BPF programs
perf evlist: Introduce side band thread
perf annotate: Enable annotation of BPF programs
perf build: Check what binutils's 'disassembler()' signature to use
perf bpf: Process PERF_BPF_EVENT_PROG_LOAD for annotation
perf symbols: Introduce DSO_BINARY_TYPE__BPF_PROG_INFO
perf feature detection: Add -lopcodes to feature-libbfd
perf top: Add option --no-bpf-event
perf bpf: Save BTF information as headers to perf.data
perf bpf: Save BTF in a rbtree in perf_env
perf bpf: Save bpf_prog_info information as headers to perf.data
perf bpf: Save bpf_prog_info in a rbtree in perf_env
perf bpf: Make synthesize_bpf_events() receive perf_session pointer instead of perf_tool
perf bpf: Synthesize bpf events with bpf_program__get_prog_info_linear()
bpftool: use bpf_program__get_prog_info_linear() in prog.c:do_dump()
tools lib bpf: Introduce bpf_program__get_prog_info_linear()
perf record: Replace option --bpf-event with --no-bpf-event
perf tests: Fix a memory leak in test__perf_evsel__tp_sched_test()
...

+3730 -1320
+2
kernel/events/core.c
··· 7189 7189 struct perf_output_handle handle; 7190 7190 struct perf_sample_data sample; 7191 7191 int size = mmap_event->event_id.header.size; 7192 + u32 type = mmap_event->event_id.header.type; 7192 7193 int ret; 7193 7194 7194 7195 if (!perf_event_mmap_match(event, data)) ··· 7233 7232 perf_output_end(&handle); 7234 7233 out: 7235 7234 mmap_event->event_id.header.size = size; 7235 + mmap_event->event_id.header.type = type; 7236 7236 } 7237 7237 7238 7238 static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
+2
tools/arch/arm64/include/uapi/asm/unistd.h
··· 17 17 18 18 #define __ARCH_WANT_RENAMEAT 19 19 #define __ARCH_WANT_NEW_STAT 20 + #define __ARCH_WANT_SET_GET_RLIMIT 21 + #define __ARCH_WANT_TIME32_SYSCALLS 20 22 21 23 #include <asm-generic/unistd.h>
+62 -210
tools/bpf/bpftool/prog.c
··· 401 401 402 402 static int do_dump(int argc, char **argv) 403 403 { 404 - unsigned int finfo_rec_size, linfo_rec_size, jited_linfo_rec_size; 405 - void *func_info = NULL, *linfo = NULL, *jited_linfo = NULL; 406 - unsigned int nr_finfo, nr_linfo = 0, nr_jited_linfo = 0; 404 + struct bpf_prog_info_linear *info_linear; 407 405 struct bpf_prog_linfo *prog_linfo = NULL; 408 - unsigned long *func_ksyms = NULL; 409 - struct bpf_prog_info info = {}; 410 - unsigned int *func_lens = NULL; 406 + enum {DUMP_JITED, DUMP_XLATED} mode; 411 407 const char *disasm_opt = NULL; 412 - unsigned int nr_func_ksyms; 413 - unsigned int nr_func_lens; 408 + struct bpf_prog_info *info; 414 409 struct dump_data dd = {}; 415 - __u32 len = sizeof(info); 410 + void *func_info = NULL; 416 411 struct btf *btf = NULL; 417 - unsigned int buf_size; 418 412 char *filepath = NULL; 419 413 bool opcodes = false; 420 414 bool visual = false; 421 415 char func_sig[1024]; 422 416 unsigned char *buf; 423 417 bool linum = false; 424 - __u32 *member_len; 425 - __u64 *member_ptr; 418 + __u32 member_len; 419 + __u64 arrays; 426 420 ssize_t n; 427 - int err; 428 421 int fd; 429 422 430 423 if (is_prefix(*argv, "jited")) { 431 424 if (disasm_init()) 432 425 return -1; 433 - 434 - member_len = &info.jited_prog_len; 435 - member_ptr = &info.jited_prog_insns; 426 + mode = DUMP_JITED; 436 427 } else if (is_prefix(*argv, "xlated")) { 437 - member_len = &info.xlated_prog_len; 438 - member_ptr = &info.xlated_prog_insns; 428 + mode = DUMP_XLATED; 439 429 } else { 440 430 p_err("expected 'xlated' or 'jited', got: %s", *argv); 441 431 return -1; ··· 464 474 return -1; 465 475 } 466 476 467 - err = bpf_obj_get_info_by_fd(fd, &info, &len); 468 - if (err) { 469 - p_err("can't get prog info: %s", strerror(errno)); 470 - return -1; 471 - } 477 + if (mode == DUMP_JITED) 478 + arrays = 1UL << BPF_PROG_INFO_JITED_INSNS; 479 + else 480 + arrays = 1UL << BPF_PROG_INFO_XLATED_INSNS; 472 481 473 - if (!*member_len) { 474 - p_info("no instructions returned"); 475 - close(fd); 476 - return 0; 477 - } 482 + arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS; 483 + arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; 484 + arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; 485 + arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; 486 + arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO; 478 487 479 - buf_size = *member_len; 480 - 481 - buf = malloc(buf_size); 482 - if (!buf) { 483 - p_err("mem alloc failed"); 484 - close(fd); 485 - return -1; 486 - } 487 - 488 - nr_func_ksyms = info.nr_jited_ksyms; 489 - if (nr_func_ksyms) { 490 - func_ksyms = malloc(nr_func_ksyms * sizeof(__u64)); 491 - if (!func_ksyms) { 492 - p_err("mem alloc failed"); 493 - close(fd); 494 - goto err_free; 495 - } 496 - } 497 - 498 - nr_func_lens = info.nr_jited_func_lens; 499 - if (nr_func_lens) { 500 - func_lens = malloc(nr_func_lens * sizeof(__u32)); 501 - if (!func_lens) { 502 - p_err("mem alloc failed"); 503 - close(fd); 504 - goto err_free; 505 - } 506 - } 507 - 508 - nr_finfo = info.nr_func_info; 509 - finfo_rec_size = info.func_info_rec_size; 510 - if (nr_finfo && finfo_rec_size) { 511 - func_info = malloc(nr_finfo * finfo_rec_size); 512 - if (!func_info) { 513 - p_err("mem alloc failed"); 514 - close(fd); 515 - goto err_free; 516 - } 517 - } 518 - 519 - linfo_rec_size = info.line_info_rec_size; 520 - if (info.nr_line_info && linfo_rec_size && info.btf_id) { 521 - nr_linfo = info.nr_line_info; 522 - linfo = malloc(nr_linfo * linfo_rec_size); 523 - if (!linfo) { 524 - p_err("mem alloc failed"); 525 - close(fd); 526 - goto err_free; 527 - } 528 - } 529 - 530 - jited_linfo_rec_size = info.jited_line_info_rec_size; 531 - if (info.nr_jited_line_info && 532 - jited_linfo_rec_size && 533 - info.nr_jited_ksyms && 534 - info.nr_jited_func_lens && 535 - info.btf_id) { 536 - nr_jited_linfo = info.nr_jited_line_info; 537 - jited_linfo = malloc(nr_jited_linfo * jited_linfo_rec_size); 538 - if (!jited_linfo) { 539 - p_err("mem alloc failed"); 540 - close(fd); 541 - goto err_free; 542 - } 543 - } 544 - 545 - memset(&info, 0, sizeof(info)); 546 - 547 - *member_ptr = ptr_to_u64(buf); 548 - *member_len = buf_size; 549 - info.jited_ksyms = ptr_to_u64(func_ksyms); 550 - info.nr_jited_ksyms = nr_func_ksyms; 551 - info.jited_func_lens = ptr_to_u64(func_lens); 552 - info.nr_jited_func_lens = nr_func_lens; 553 - info.nr_func_info = nr_finfo; 554 - info.func_info_rec_size = finfo_rec_size; 555 - info.func_info = ptr_to_u64(func_info); 556 - info.nr_line_info = nr_linfo; 557 - info.line_info_rec_size = linfo_rec_size; 558 - info.line_info = ptr_to_u64(linfo); 559 - info.nr_jited_line_info = nr_jited_linfo; 560 - info.jited_line_info_rec_size = jited_linfo_rec_size; 561 - info.jited_line_info = ptr_to_u64(jited_linfo); 562 - 563 - err = bpf_obj_get_info_by_fd(fd, &info, &len); 488 + info_linear = bpf_program__get_prog_info_linear(fd, arrays); 564 489 close(fd); 565 - if (err) { 490 + if (IS_ERR_OR_NULL(info_linear)) { 566 491 p_err("can't get prog info: %s", strerror(errno)); 567 - goto err_free; 492 + return -1; 568 493 } 569 494 570 - if (*member_len > buf_size) { 571 - p_err("too many instructions returned"); 572 - goto err_free; 495 + info = &info_linear->info; 496 + if (mode == DUMP_JITED) { 497 + if (info->jited_prog_len == 0) { 498 + p_info("no instructions returned"); 499 + goto err_free; 500 + } 501 + buf = (unsigned char *)(info->jited_prog_insns); 502 + member_len = info->jited_prog_len; 503 + } else { /* DUMP_XLATED */ 504 + if (info->xlated_prog_len == 0) { 505 + p_err("error retrieving insn dump: kernel.kptr_restrict set?"); 506 + goto err_free; 507 + } 508 + buf = (unsigned char *)info->xlated_prog_insns; 509 + member_len = info->xlated_prog_len; 573 510 } 574 511 575 - if (info.nr_jited_ksyms > nr_func_ksyms) { 576 - p_err("too many addresses returned"); 577 - goto err_free; 578 - } 579 - 580 - if (info.nr_jited_func_lens > nr_func_lens) { 581 - p_err("too many values returned"); 582 - goto err_free; 583 - } 584 - 585 - if (info.nr_func_info != nr_finfo) { 586 - p_err("incorrect nr_func_info %d vs. expected %d", 587 - info.nr_func_info, nr_finfo); 588 - goto err_free; 589 - } 590 - 591 - if (info.func_info_rec_size != finfo_rec_size) { 592 - p_err("incorrect func_info_rec_size %d vs. expected %d", 593 - info.func_info_rec_size, finfo_rec_size); 594 - goto err_free; 595 - } 596 - 597 - if (linfo && info.nr_line_info != nr_linfo) { 598 - p_err("incorrect nr_line_info %u vs. expected %u", 599 - info.nr_line_info, nr_linfo); 600 - goto err_free; 601 - } 602 - 603 - if (info.line_info_rec_size != linfo_rec_size) { 604 - p_err("incorrect line_info_rec_size %u vs. expected %u", 605 - info.line_info_rec_size, linfo_rec_size); 606 - goto err_free; 607 - } 608 - 609 - if (jited_linfo && info.nr_jited_line_info != nr_jited_linfo) { 610 - p_err("incorrect nr_jited_line_info %u vs. expected %u", 611 - info.nr_jited_line_info, nr_jited_linfo); 612 - goto err_free; 613 - } 614 - 615 - if (info.jited_line_info_rec_size != jited_linfo_rec_size) { 616 - p_err("incorrect jited_line_info_rec_size %u vs. expected %u", 617 - info.jited_line_info_rec_size, jited_linfo_rec_size); 618 - goto err_free; 619 - } 620 - 621 - if ((member_len == &info.jited_prog_len && 622 - info.jited_prog_insns == 0) || 623 - (member_len == &info.xlated_prog_len && 624 - info.xlated_prog_insns == 0)) { 625 - p_err("error retrieving insn dump: kernel.kptr_restrict set?"); 626 - goto err_free; 627 - } 628 - 629 - if (info.btf_id && btf__get_from_id(info.btf_id, &btf)) { 512 + if (info->btf_id && btf__get_from_id(info->btf_id, &btf)) { 630 513 p_err("failed to get btf"); 631 514 goto err_free; 632 515 } 633 516 634 - if (nr_linfo) { 635 - prog_linfo = bpf_prog_linfo__new(&info); 517 + func_info = (void *)info->func_info; 518 + 519 + if (info->nr_line_info) { 520 + prog_linfo = bpf_prog_linfo__new(info); 636 521 if (!prog_linfo) 637 522 p_info("error in processing bpf_line_info. continue without it."); 638 523 } ··· 520 655 goto err_free; 521 656 } 522 657 523 - n = write(fd, buf, *member_len); 658 + n = write(fd, buf, member_len); 524 659 close(fd); 525 - if (n != *member_len) { 660 + if (n != member_len) { 526 661 p_err("error writing output file: %s", 527 662 n < 0 ? strerror(errno) : "short write"); 528 663 goto err_free; ··· 530 665 531 666 if (json_output) 532 667 jsonw_null(json_wtr); 533 - } else if (member_len == &info.jited_prog_len) { 668 + } else if (mode == DUMP_JITED) { 534 669 const char *name = NULL; 535 670 536 - if (info.ifindex) { 537 - name = ifindex_to_bfd_params(info.ifindex, 538 - info.netns_dev, 539 - info.netns_ino, 671 + if (info->ifindex) { 672 + name = ifindex_to_bfd_params(info->ifindex, 673 + info->netns_dev, 674 + info->netns_ino, 540 675 &disasm_opt); 541 676 if (!name) 542 677 goto err_free; 543 678 } 544 679 545 - if (info.nr_jited_func_lens && info.jited_func_lens) { 680 + if (info->nr_jited_func_lens && info->jited_func_lens) { 546 681 struct kernel_sym *sym = NULL; 547 682 struct bpf_func_info *record; 548 683 char sym_name[SYM_MAX_NAME]; ··· 550 685 __u64 *ksyms = NULL; 551 686 __u32 *lens; 552 687 __u32 i; 553 - 554 - if (info.nr_jited_ksyms) { 688 + if (info->nr_jited_ksyms) { 555 689 kernel_syms_load(&dd); 556 - ksyms = (__u64 *) info.jited_ksyms; 690 + ksyms = (__u64 *) info->jited_ksyms; 557 691 } 558 692 559 693 if (json_output) 560 694 jsonw_start_array(json_wtr); 561 695 562 - lens = (__u32 *) info.jited_func_lens; 563 - for (i = 0; i < info.nr_jited_func_lens; i++) { 696 + lens = (__u32 *) info->jited_func_lens; 697 + for (i = 0; i < info->nr_jited_func_lens; i++) { 564 698 if (ksyms) { 565 699 sym = kernel_syms_search(&dd, ksyms[i]); 566 700 if (sym) ··· 571 707 } 572 708 573 709 if (func_info) { 574 - record = func_info + i * finfo_rec_size; 710 + record = func_info + i * info->func_info_rec_size; 575 711 btf_dumper_type_only(btf, record->type_id, 576 712 func_sig, 577 713 sizeof(func_sig)); ··· 608 744 if (json_output) 609 745 jsonw_end_array(json_wtr); 610 746 } else { 611 - disasm_print_insn(buf, *member_len, opcodes, name, 747 + disasm_print_insn(buf, member_len, opcodes, name, 612 748 disasm_opt, btf, NULL, 0, 0, false); 613 749 } 614 750 } else if (visual) { 615 751 if (json_output) 616 752 jsonw_null(json_wtr); 617 753 else 618 - dump_xlated_cfg(buf, *member_len); 754 + dump_xlated_cfg(buf, member_len); 619 755 } else { 620 756 kernel_syms_load(&dd); 621 - dd.nr_jited_ksyms = info.nr_jited_ksyms; 622 - dd.jited_ksyms = (__u64 *) info.jited_ksyms; 757 + dd.nr_jited_ksyms = info->nr_jited_ksyms; 758 + dd.jited_ksyms = (__u64 *) info->jited_ksyms; 623 759 dd.btf = btf; 624 760 dd.func_info = func_info; 625 - dd.finfo_rec_size = finfo_rec_size; 761 + dd.finfo_rec_size = info->func_info_rec_size; 626 762 dd.prog_linfo = prog_linfo; 627 763 628 764 if (json_output) 629 - dump_xlated_json(&dd, buf, *member_len, opcodes, 765 + dump_xlated_json(&dd, buf, member_len, opcodes, 630 766 linum); 631 767 else 632 - dump_xlated_plain(&dd, buf, *member_len, opcodes, 768 + dump_xlated_plain(&dd, buf, member_len, opcodes, 633 769 linum); 634 770 kernel_syms_destroy(&dd); 635 771 } 636 772 637 - free(buf); 638 - free(func_ksyms); 639 - free(func_lens); 640 - free(func_info); 641 - free(linfo); 642 - free(jited_linfo); 643 - bpf_prog_linfo__free(prog_linfo); 773 + free(info_linear); 644 774 return 0; 645 775 646 776 err_free: 647 - free(buf); 648 - free(func_ksyms); 649 - free(func_lens); 650 - free(func_info); 651 - free(linfo); 652 - free(jited_linfo); 653 - bpf_prog_linfo__free(prog_linfo); 777 + free(info_linear); 654 778 return -1; 655 779 } 656 780
+4 -2
tools/build/Makefile.feature
··· 66 66 sched_getcpu \ 67 67 sdt \ 68 68 setns \ 69 - libaio 69 + libaio \ 70 + disassembler-four-args 70 71 71 72 # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list 72 73 # of all feature tests ··· 119 118 lzma \ 120 119 get_cpuid \ 121 120 bpf \ 122 - libaio 121 + libaio \ 122 + disassembler-four-args 123 123 124 124 # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. 125 125 # If in the future we need per-feature checks/flags for features not
+5
tools/build/feature/test-all.c
··· 178 178 # include "test-reallocarray.c" 179 179 #undef main 180 180 181 + #define main main_test_disassembler_four_args 182 + # include "test-disassembler-four-args.c" 183 + #undef main 184 + 181 185 int main(int argc, char *argv[]) 182 186 { 183 187 main_test_libpython(); ··· 223 219 main_test_setns(); 224 220 main_test_libaio(); 225 221 main_test_reallocarray(); 222 + main_test_disassembler_four_args(); 226 223 227 224 return 0; 228 225 }
+116 -33
tools/include/uapi/asm-generic/unistd.h
··· 38 38 __SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit) 39 39 #define __NR_io_cancel 3 40 40 __SYSCALL(__NR_io_cancel, sys_io_cancel) 41 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 41 42 #define __NR_io_getevents 4 42 - __SC_COMP(__NR_io_getevents, sys_io_getevents, compat_sys_io_getevents) 43 + __SC_3264(__NR_io_getevents, sys_io_getevents_time32, sys_io_getevents) 44 + #endif 43 45 44 46 /* fs/xattr.c */ 45 47 #define __NR_setxattr 5 ··· 181 179 #define __NR_fchown 55 182 180 __SYSCALL(__NR_fchown, sys_fchown) 183 181 #define __NR_openat 56 184 - __SC_COMP(__NR_openat, sys_openat, compat_sys_openat) 182 + __SYSCALL(__NR_openat, sys_openat) 185 183 #define __NR_close 57 186 184 __SYSCALL(__NR_close, sys_close) 187 185 #define __NR_vhangup 58 ··· 224 222 __SYSCALL(__NR3264_sendfile, sys_sendfile64) 225 223 226 224 /* fs/select.c */ 225 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 227 226 #define __NR_pselect6 72 228 - __SC_COMP(__NR_pselect6, sys_pselect6, compat_sys_pselect6) 227 + __SC_COMP_3264(__NR_pselect6, sys_pselect6_time32, sys_pselect6, compat_sys_pselect6_time32) 229 228 #define __NR_ppoll 73 230 - __SC_COMP(__NR_ppoll, sys_ppoll, compat_sys_ppoll) 229 + __SC_COMP_3264(__NR_ppoll, sys_ppoll_time32, sys_ppoll, compat_sys_ppoll_time32) 230 + #endif 231 231 232 232 /* fs/signalfd.c */ 233 233 #define __NR_signalfd4 74 ··· 273 269 /* fs/timerfd.c */ 274 270 #define __NR_timerfd_create 85 275 271 __SYSCALL(__NR_timerfd_create, sys_timerfd_create) 272 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 276 273 #define __NR_timerfd_settime 86 277 - __SC_COMP(__NR_timerfd_settime, sys_timerfd_settime, \ 278 - compat_sys_timerfd_settime) 274 + __SC_3264(__NR_timerfd_settime, sys_timerfd_settime32, \ 275 + sys_timerfd_settime) 279 276 #define __NR_timerfd_gettime 87 280 - __SC_COMP(__NR_timerfd_gettime, sys_timerfd_gettime, \ 281 - compat_sys_timerfd_gettime) 277 + __SC_3264(__NR_timerfd_gettime, sys_timerfd_gettime32, \ 278 + sys_timerfd_gettime) 279 + #endif 282 280 283 281 /* fs/utimes.c */ 282 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 284 283 #define __NR_utimensat 88 285 - __SC_COMP(__NR_utimensat, sys_utimensat, compat_sys_utimensat) 284 + __SC_3264(__NR_utimensat, sys_utimensat_time32, sys_utimensat) 285 + #endif 286 286 287 287 /* kernel/acct.c */ 288 288 #define __NR_acct 89 ··· 317 309 __SYSCALL(__NR_unshare, sys_unshare) 318 310 319 311 /* kernel/futex.c */ 312 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 320 313 #define __NR_futex 98 321 - __SC_COMP(__NR_futex, sys_futex, compat_sys_futex) 314 + __SC_3264(__NR_futex, sys_futex_time32, sys_futex) 315 + #endif 322 316 #define __NR_set_robust_list 99 323 317 __SC_COMP(__NR_set_robust_list, sys_set_robust_list, \ 324 318 compat_sys_set_robust_list) ··· 329 319 compat_sys_get_robust_list) 330 320 331 321 /* kernel/hrtimer.c */ 322 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 332 323 #define __NR_nanosleep 101 333 - __SC_COMP(__NR_nanosleep, sys_nanosleep, compat_sys_nanosleep) 324 + __SC_3264(__NR_nanosleep, sys_nanosleep_time32, sys_nanosleep) 325 + #endif 334 326 335 327 /* kernel/itimer.c */ 336 328 #define __NR_getitimer 102 ··· 353 341 /* kernel/posix-timers.c */ 354 342 #define __NR_timer_create 107 355 343 __SC_COMP(__NR_timer_create, sys_timer_create, compat_sys_timer_create) 344 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 356 345 #define __NR_timer_gettime 108 357 - __SC_COMP(__NR_timer_gettime, sys_timer_gettime, compat_sys_timer_gettime) 346 + __SC_3264(__NR_timer_gettime, sys_timer_gettime32, sys_timer_gettime) 347 + #endif 358 348 #define __NR_timer_getoverrun 109 359 349 __SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun) 350 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 360 351 #define __NR_timer_settime 110 361 - __SC_COMP(__NR_timer_settime, sys_timer_settime, compat_sys_timer_settime) 352 + __SC_3264(__NR_timer_settime, sys_timer_settime32, sys_timer_settime) 353 + #endif 362 354 #define __NR_timer_delete 111 363 355 __SYSCALL(__NR_timer_delete, sys_timer_delete) 356 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 364 357 #define __NR_clock_settime 112 365 - __SC_COMP(__NR_clock_settime, sys_clock_settime, compat_sys_clock_settime) 358 + __SC_3264(__NR_clock_settime, sys_clock_settime32, sys_clock_settime) 366 359 #define __NR_clock_gettime 113 367 - __SC_COMP(__NR_clock_gettime, sys_clock_gettime, compat_sys_clock_gettime) 360 + __SC_3264(__NR_clock_gettime, sys_clock_gettime32, sys_clock_gettime) 368 361 #define __NR_clock_getres 114 369 - __SC_COMP(__NR_clock_getres, sys_clock_getres, compat_sys_clock_getres) 362 + __SC_3264(__NR_clock_getres, sys_clock_getres_time32, sys_clock_getres) 370 363 #define __NR_clock_nanosleep 115 371 - __SC_COMP(__NR_clock_nanosleep, sys_clock_nanosleep, \ 372 - compat_sys_clock_nanosleep) 364 + __SC_3264(__NR_clock_nanosleep, sys_clock_nanosleep_time32, \ 365 + sys_clock_nanosleep) 366 + #endif 373 367 374 368 /* kernel/printk.c */ 375 369 #define __NR_syslog 116 ··· 406 388 __SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max) 407 389 #define __NR_sched_get_priority_min 126 408 390 __SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min) 391 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 409 392 #define __NR_sched_rr_get_interval 127 410 - __SC_COMP(__NR_sched_rr_get_interval, sys_sched_rr_get_interval, \ 411 - compat_sys_sched_rr_get_interval) 393 + __SC_3264(__NR_sched_rr_get_interval, sys_sched_rr_get_interval_time32, \ 394 + sys_sched_rr_get_interval) 395 + #endif 412 396 413 397 /* kernel/signal.c */ 414 398 #define __NR_restart_syscall 128 ··· 431 411 __SC_COMP(__NR_rt_sigprocmask, sys_rt_sigprocmask, compat_sys_rt_sigprocmask) 432 412 #define __NR_rt_sigpending 136 433 413 __SC_COMP(__NR_rt_sigpending, sys_rt_sigpending, compat_sys_rt_sigpending) 414 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 434 415 #define __NR_rt_sigtimedwait 137 435 - __SC_COMP(__NR_rt_sigtimedwait, sys_rt_sigtimedwait, \ 436 - compat_sys_rt_sigtimedwait) 416 + __SC_COMP_3264(__NR_rt_sigtimedwait, sys_rt_sigtimedwait_time32, \ 417 + sys_rt_sigtimedwait, compat_sys_rt_sigtimedwait_time32) 418 + #endif 437 419 #define __NR_rt_sigqueueinfo 138 438 420 __SC_COMP(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo, \ 439 421 compat_sys_rt_sigqueueinfo) ··· 489 467 __SYSCALL(__NR_sethostname, sys_sethostname) 490 468 #define __NR_setdomainname 162 491 469 __SYSCALL(__NR_setdomainname, sys_setdomainname) 470 + 471 + #ifdef __ARCH_WANT_SET_GET_RLIMIT 472 + /* getrlimit and setrlimit are superseded with prlimit64 */ 492 473 #define __NR_getrlimit 163 493 474 __SC_COMP(__NR_getrlimit, sys_getrlimit, compat_sys_getrlimit) 494 475 #define __NR_setrlimit 164 495 476 __SC_COMP(__NR_setrlimit, sys_setrlimit, compat_sys_setrlimit) 477 + #endif 478 + 496 479 #define __NR_getrusage 165 497 480 __SC_COMP(__NR_getrusage, sys_getrusage, compat_sys_getrusage) 498 481 #define __NR_umask 166 ··· 508 481 __SYSCALL(__NR_getcpu, sys_getcpu) 509 482 510 483 /* kernel/time.c */ 484 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 511 485 #define __NR_gettimeofday 169 512 486 __SC_COMP(__NR_gettimeofday, sys_gettimeofday, compat_sys_gettimeofday) 513 487 #define __NR_settimeofday 170 514 488 __SC_COMP(__NR_settimeofday, sys_settimeofday, compat_sys_settimeofday) 515 489 #define __NR_adjtimex 171 516 - __SC_COMP(__NR_adjtimex, sys_adjtimex, compat_sys_adjtimex) 490 + __SC_3264(__NR_adjtimex, sys_adjtimex_time32, sys_adjtimex) 491 + #endif 517 492 518 493 /* kernel/timer.c */ 519 494 #define __NR_getpid 172 ··· 540 511 __SC_COMP(__NR_mq_open, sys_mq_open, compat_sys_mq_open) 541 512 #define __NR_mq_unlink 181 542 513 __SYSCALL(__NR_mq_unlink, sys_mq_unlink) 514 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 543 515 #define __NR_mq_timedsend 182 544 - __SC_COMP(__NR_mq_timedsend, sys_mq_timedsend, compat_sys_mq_timedsend) 516 + __SC_3264(__NR_mq_timedsend, sys_mq_timedsend_time32, sys_mq_timedsend) 545 517 #define __NR_mq_timedreceive 183 546 - __SC_COMP(__NR_mq_timedreceive, sys_mq_timedreceive, \ 547 - compat_sys_mq_timedreceive) 518 + __SC_3264(__NR_mq_timedreceive, sys_mq_timedreceive_time32, \ 519 + sys_mq_timedreceive) 520 + #endif 548 521 #define __NR_mq_notify 184 549 522 __SC_COMP(__NR_mq_notify, sys_mq_notify, compat_sys_mq_notify) 550 523 #define __NR_mq_getsetattr 185 ··· 567 536 __SYSCALL(__NR_semget, sys_semget) 568 537 #define __NR_semctl 191 569 538 __SC_COMP(__NR_semctl, sys_semctl, compat_sys_semctl) 539 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 570 540 #define __NR_semtimedop 192 571 - __SC_COMP(__NR_semtimedop, sys_semtimedop, compat_sys_semtimedop) 541 + __SC_COMP(__NR_semtimedop, sys_semtimedop, sys_semtimedop_time32) 542 + #endif 572 543 #define __NR_semop 193 573 544 __SYSCALL(__NR_semop, sys_semop) 574 545 ··· 691 658 __SYSCALL(__NR_perf_event_open, sys_perf_event_open) 692 659 #define __NR_accept4 242 693 660 __SYSCALL(__NR_accept4, sys_accept4) 661 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 694 662 #define __NR_recvmmsg 243 695 - __SC_COMP(__NR_recvmmsg, sys_recvmmsg, compat_sys_recvmmsg) 663 + __SC_COMP_3264(__NR_recvmmsg, sys_recvmmsg_time32, sys_recvmmsg, compat_sys_recvmmsg_time32) 664 + #endif 696 665 697 666 /* 698 667 * Architectures may provide up to 16 syscalls of their own ··· 702 667 */ 703 668 #define __NR_arch_specific_syscall 244 704 669 670 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 705 671 #define __NR_wait4 260 706 672 __SC_COMP(__NR_wait4, sys_wait4, compat_sys_wait4) 673 + #endif 707 674 #define __NR_prlimit64 261 708 675 __SYSCALL(__NR_prlimit64, sys_prlimit64) 709 676 #define __NR_fanotify_init 262 ··· 715 678 #define __NR_name_to_handle_at 264 716 679 __SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at) 717 680 #define __NR_open_by_handle_at 265 718 - __SC_COMP(__NR_open_by_handle_at, sys_open_by_handle_at, \ 719 - compat_sys_open_by_handle_at) 681 + __SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) 682 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 720 683 #define __NR_clock_adjtime 266 721 - __SC_COMP(__NR_clock_adjtime, sys_clock_adjtime, compat_sys_clock_adjtime) 684 + __SC_3264(__NR_clock_adjtime, sys_clock_adjtime32, sys_clock_adjtime) 685 + #endif 722 686 #define __NR_syncfs 267 723 687 __SYSCALL(__NR_syncfs, sys_syncfs) 724 688 #define __NR_setns 268 ··· 772 734 __SYSCALL(__NR_pkey_free, sys_pkey_free) 773 735 #define __NR_statx 291 774 736 __SYSCALL(__NR_statx, sys_statx) 737 + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 775 738 #define __NR_io_pgetevents 292 776 - __SC_COMP(__NR_io_pgetevents, sys_io_pgetevents, compat_sys_io_pgetevents) 739 + __SC_COMP_3264(__NR_io_pgetevents, sys_io_pgetevents_time32, sys_io_pgetevents, compat_sys_io_pgetevents) 740 + #endif 777 741 #define __NR_rseq 293 778 742 __SYSCALL(__NR_rseq, sys_rseq) 779 743 #define __NR_kexec_file_load 294 780 744 __SYSCALL(__NR_kexec_file_load, sys_kexec_file_load) 745 + /* 295 through 402 are unassigned to sync up with generic numbers, don't use */ 746 + #if __BITS_PER_LONG == 32 747 + #define __NR_clock_gettime64 403 748 + __SYSCALL(__NR_clock_gettime64, sys_clock_gettime) 749 + #define __NR_clock_settime64 404 750 + __SYSCALL(__NR_clock_settime64, sys_clock_settime) 751 + #define __NR_clock_adjtime64 405 752 + __SYSCALL(__NR_clock_adjtime64, sys_clock_adjtime) 753 + #define __NR_clock_getres_time64 406 754 + __SYSCALL(__NR_clock_getres_time64, sys_clock_getres) 755 + #define __NR_clock_nanosleep_time64 407 756 + __SYSCALL(__NR_clock_nanosleep_time64, sys_clock_nanosleep) 757 + #define __NR_timer_gettime64 408 758 + __SYSCALL(__NR_timer_gettime64, sys_timer_gettime) 759 + #define __NR_timer_settime64 409 760 + __SYSCALL(__NR_timer_settime64, sys_timer_settime) 761 + #define __NR_timerfd_gettime64 410 762 + __SYSCALL(__NR_timerfd_gettime64, sys_timerfd_gettime) 763 + #define __NR_timerfd_settime64 411 764 + __SYSCALL(__NR_timerfd_settime64, sys_timerfd_settime) 765 + #define __NR_utimensat_time64 412 766 + __SYSCALL(__NR_utimensat_time64, sys_utimensat) 767 + #define __NR_pselect6_time64 413 768 + __SC_COMP(__NR_pselect6_time64, sys_pselect6, compat_sys_pselect6_time64) 769 + #define __NR_ppoll_time64 414 770 + __SC_COMP(__NR_ppoll_time64, sys_ppoll, compat_sys_ppoll_time64) 771 + #define __NR_io_pgetevents_time64 416 772 + __SYSCALL(__NR_io_pgetevents_time64, sys_io_pgetevents) 773 + #define __NR_recvmmsg_time64 417 774 + __SC_COMP(__NR_recvmmsg_time64, sys_recvmmsg, compat_sys_recvmmsg_time64) 775 + #define __NR_mq_timedsend_time64 418 776 + __SYSCALL(__NR_mq_timedsend_time64, sys_mq_timedsend) 777 + #define __NR_mq_timedreceive_time64 419 778 + __SYSCALL(__NR_mq_timedreceive_time64, sys_mq_timedreceive) 779 + #define __NR_semtimedop_time64 420 780 + __SYSCALL(__NR_semtimedop_time64, sys_semtimedop) 781 + #define __NR_rt_sigtimedwait_time64 421 782 + __SC_COMP(__NR_rt_sigtimedwait_time64, sys_rt_sigtimedwait, compat_sys_rt_sigtimedwait_time64) 783 + #define __NR_futex_time64 422 784 + __SYSCALL(__NR_futex_time64, sys_futex) 785 + #define __NR_sched_rr_get_interval_time64 423 786 + __SYSCALL(__NR_sched_rr_get_interval_time64, sys_sched_rr_get_interval) 787 + #endif 781 788 782 789 #undef __NR_syscalls 783 - #define __NR_syscalls 295 790 + #define __NR_syscalls 424 784 791 785 792 /* 786 793 * 32 bit systems traditionally used different
+5 -4
tools/include/uapi/linux/in.h
··· 292 292 #define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) 293 293 294 294 /* Defines for Multicast INADDR */ 295 - #define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */ 296 - #define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */ 297 - #define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */ 298 - #define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */ 295 + #define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */ 296 + #define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */ 297 + #define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */ 298 + #define INADDR_ALLSNOOPERS_GROUP 0xe000006aU /* 224.0.0.106 */ 299 + #define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */ 299 300 #endif 300 301 301 302 /* <asm/byteorder.h> contains the htonl type stuff.. */
+252 -1
tools/lib/bpf/libbpf.c
··· 112 112 # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ 113 113 #endif 114 114 115 + static inline __u64 ptr_to_u64(const void *ptr) 116 + { 117 + return (__u64) (unsigned long) ptr; 118 + } 119 + 115 120 struct bpf_capabilities { 116 121 /* v4.14: kernel support for program & map names. */ 117 122 __u32 name:1; ··· 627 622 bool strict = !(flags & MAPS_RELAX_COMPAT); 628 623 int i, map_idx, map_def_sz, nr_maps = 0; 629 624 Elf_Scn *scn; 630 - Elf_Data *data; 625 + Elf_Data *data = NULL; 631 626 Elf_Data *symbols = obj->efile.symbols; 632 627 633 628 if (obj->efile.maps_shndx < 0) ··· 3003 2998 3004 2999 ring_buffer_write_tail(header, data_tail); 3005 3000 return ret; 3001 + } 3002 + 3003 + struct bpf_prog_info_array_desc { 3004 + int array_offset; /* e.g. offset of jited_prog_insns */ 3005 + int count_offset; /* e.g. offset of jited_prog_len */ 3006 + int size_offset; /* > 0: offset of rec size, 3007 + * < 0: fix size of -size_offset 3008 + */ 3009 + }; 3010 + 3011 + static struct bpf_prog_info_array_desc bpf_prog_info_array_desc[] = { 3012 + [BPF_PROG_INFO_JITED_INSNS] = { 3013 + offsetof(struct bpf_prog_info, jited_prog_insns), 3014 + offsetof(struct bpf_prog_info, jited_prog_len), 3015 + -1, 3016 + }, 3017 + [BPF_PROG_INFO_XLATED_INSNS] = { 3018 + offsetof(struct bpf_prog_info, xlated_prog_insns), 3019 + offsetof(struct bpf_prog_info, xlated_prog_len), 3020 + -1, 3021 + }, 3022 + [BPF_PROG_INFO_MAP_IDS] = { 3023 + offsetof(struct bpf_prog_info, map_ids), 3024 + offsetof(struct bpf_prog_info, nr_map_ids), 3025 + -(int)sizeof(__u32), 3026 + }, 3027 + [BPF_PROG_INFO_JITED_KSYMS] = { 3028 + offsetof(struct bpf_prog_info, jited_ksyms), 3029 + offsetof(struct bpf_prog_info, nr_jited_ksyms), 3030 + -(int)sizeof(__u64), 3031 + }, 3032 + [BPF_PROG_INFO_JITED_FUNC_LENS] = { 3033 + offsetof(struct bpf_prog_info, jited_func_lens), 3034 + offsetof(struct bpf_prog_info, nr_jited_func_lens), 3035 + -(int)sizeof(__u32), 3036 + }, 3037 + [BPF_PROG_INFO_FUNC_INFO] = { 3038 + offsetof(struct bpf_prog_info, func_info), 3039 + offsetof(struct bpf_prog_info, nr_func_info), 3040 + offsetof(struct bpf_prog_info, func_info_rec_size), 3041 + }, 3042 + [BPF_PROG_INFO_LINE_INFO] = { 3043 + offsetof(struct bpf_prog_info, line_info), 3044 + offsetof(struct bpf_prog_info, nr_line_info), 3045 + offsetof(struct bpf_prog_info, line_info_rec_size), 3046 + }, 3047 + [BPF_PROG_INFO_JITED_LINE_INFO] = { 3048 + offsetof(struct bpf_prog_info, jited_line_info), 3049 + offsetof(struct bpf_prog_info, nr_jited_line_info), 3050 + offsetof(struct bpf_prog_info, jited_line_info_rec_size), 3051 + }, 3052 + [BPF_PROG_INFO_PROG_TAGS] = { 3053 + offsetof(struct bpf_prog_info, prog_tags), 3054 + offsetof(struct bpf_prog_info, nr_prog_tags), 3055 + -(int)sizeof(__u8) * BPF_TAG_SIZE, 3056 + }, 3057 + 3058 + }; 3059 + 3060 + static __u32 bpf_prog_info_read_offset_u32(struct bpf_prog_info *info, int offset) 3061 + { 3062 + __u32 *array = (__u32 *)info; 3063 + 3064 + if (offset >= 0) 3065 + return array[offset / sizeof(__u32)]; 3066 + return -(int)offset; 3067 + } 3068 + 3069 + static __u64 bpf_prog_info_read_offset_u64(struct bpf_prog_info *info, int offset) 3070 + { 3071 + __u64 *array = (__u64 *)info; 3072 + 3073 + if (offset >= 0) 3074 + return array[offset / sizeof(__u64)]; 3075 + return -(int)offset; 3076 + } 3077 + 3078 + static void bpf_prog_info_set_offset_u32(struct bpf_prog_info *info, int offset, 3079 + __u32 val) 3080 + { 3081 + __u32 *array = (__u32 *)info; 3082 + 3083 + if (offset >= 0) 3084 + array[offset / sizeof(__u32)] = val; 3085 + } 3086 + 3087 + static void bpf_prog_info_set_offset_u64(struct bpf_prog_info *info, int offset, 3088 + __u64 val) 3089 + { 3090 + __u64 *array = (__u64 *)info; 3091 + 3092 + if (offset >= 0) 3093 + array[offset / sizeof(__u64)] = val; 3094 + } 3095 + 3096 + struct bpf_prog_info_linear * 3097 + bpf_program__get_prog_info_linear(int fd, __u64 arrays) 3098 + { 3099 + struct bpf_prog_info_linear *info_linear; 3100 + struct bpf_prog_info info = {}; 3101 + __u32 info_len = sizeof(info); 3102 + __u32 data_len = 0; 3103 + int i, err; 3104 + void *ptr; 3105 + 3106 + if (arrays >> BPF_PROG_INFO_LAST_ARRAY) 3107 + return ERR_PTR(-EINVAL); 3108 + 3109 + /* step 1: get array dimensions */ 3110 + err = bpf_obj_get_info_by_fd(fd, &info, &info_len); 3111 + if (err) { 3112 + pr_debug("can't get prog info: %s", strerror(errno)); 3113 + return ERR_PTR(-EFAULT); 3114 + } 3115 + 3116 + /* step 2: calculate total size of all arrays */ 3117 + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { 3118 + bool include_array = (arrays & (1UL << i)) > 0; 3119 + struct bpf_prog_info_array_desc *desc; 3120 + __u32 count, size; 3121 + 3122 + desc = bpf_prog_info_array_desc + i; 3123 + 3124 + /* kernel is too old to support this field */ 3125 + if (info_len < desc->array_offset + sizeof(__u32) || 3126 + info_len < desc->count_offset + sizeof(__u32) || 3127 + (desc->size_offset > 0 && info_len < desc->size_offset)) 3128 + include_array = false; 3129 + 3130 + if (!include_array) { 3131 + arrays &= ~(1UL << i); /* clear the bit */ 3132 + continue; 3133 + } 3134 + 3135 + count = bpf_prog_info_read_offset_u32(&info, desc->count_offset); 3136 + size = bpf_prog_info_read_offset_u32(&info, desc->size_offset); 3137 + 3138 + data_len += count * size; 3139 + } 3140 + 3141 + /* step 3: allocate continuous memory */ 3142 + data_len = roundup(data_len, sizeof(__u64)); 3143 + info_linear = malloc(sizeof(struct bpf_prog_info_linear) + data_len); 3144 + if (!info_linear) 3145 + return ERR_PTR(-ENOMEM); 3146 + 3147 + /* step 4: fill data to info_linear->info */ 3148 + info_linear->arrays = arrays; 3149 + memset(&info_linear->info, 0, sizeof(info)); 3150 + ptr = info_linear->data; 3151 + 3152 + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { 3153 + struct bpf_prog_info_array_desc *desc; 3154 + __u32 count, size; 3155 + 3156 + if ((arrays & (1UL << i)) == 0) 3157 + continue; 3158 + 3159 + desc = bpf_prog_info_array_desc + i; 3160 + count = bpf_prog_info_read_offset_u32(&info, desc->count_offset); 3161 + size = bpf_prog_info_read_offset_u32(&info, desc->size_offset); 3162 + bpf_prog_info_set_offset_u32(&info_linear->info, 3163 + desc->count_offset, count); 3164 + bpf_prog_info_set_offset_u32(&info_linear->info, 3165 + desc->size_offset, size); 3166 + bpf_prog_info_set_offset_u64(&info_linear->info, 3167 + desc->array_offset, 3168 + ptr_to_u64(ptr)); 3169 + ptr += count * size; 3170 + } 3171 + 3172 + /* step 5: call syscall again to get required arrays */ 3173 + err = bpf_obj_get_info_by_fd(fd, &info_linear->info, &info_len); 3174 + if (err) { 3175 + pr_debug("can't get prog info: %s", strerror(errno)); 3176 + free(info_linear); 3177 + return ERR_PTR(-EFAULT); 3178 + } 3179 + 3180 + /* step 6: verify the data */ 3181 + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { 3182 + struct bpf_prog_info_array_desc *desc; 3183 + __u32 v1, v2; 3184 + 3185 + if ((arrays & (1UL << i)) == 0) 3186 + continue; 3187 + 3188 + desc = bpf_prog_info_array_desc + i; 3189 + v1 = bpf_prog_info_read_offset_u32(&info, desc->count_offset); 3190 + v2 = bpf_prog_info_read_offset_u32(&info_linear->info, 3191 + desc->count_offset); 3192 + if (v1 != v2) 3193 + pr_warning("%s: mismatch in element count\n", __func__); 3194 + 3195 + v1 = bpf_prog_info_read_offset_u32(&info, desc->size_offset); 3196 + v2 = bpf_prog_info_read_offset_u32(&info_linear->info, 3197 + desc->size_offset); 3198 + if (v1 != v2) 3199 + pr_warning("%s: mismatch in rec size\n", __func__); 3200 + } 3201 + 3202 + /* step 7: update info_len and data_len */ 3203 + info_linear->info_len = sizeof(struct bpf_prog_info); 3204 + info_linear->data_len = data_len; 3205 + 3206 + return info_linear; 3207 + } 3208 + 3209 + void bpf_program__bpil_addr_to_offs(struct bpf_prog_info_linear *info_linear) 3210 + { 3211 + int i; 3212 + 3213 + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { 3214 + struct bpf_prog_info_array_desc *desc; 3215 + __u64 addr, offs; 3216 + 3217 + if ((info_linear->arrays & (1UL << i)) == 0) 3218 + continue; 3219 + 3220 + desc = bpf_prog_info_array_desc + i; 3221 + addr = bpf_prog_info_read_offset_u64(&info_linear->info, 3222 + desc->array_offset); 3223 + offs = addr - ptr_to_u64(info_linear->data); 3224 + bpf_prog_info_set_offset_u64(&info_linear->info, 3225 + desc->array_offset, offs); 3226 + } 3227 + } 3228 + 3229 + void bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear) 3230 + { 3231 + int i; 3232 + 3233 + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { 3234 + struct bpf_prog_info_array_desc *desc; 3235 + __u64 addr, offs; 3236 + 3237 + if ((info_linear->arrays & (1UL << i)) == 0) 3238 + continue; 3239 + 3240 + desc = bpf_prog_info_array_desc + i; 3241 + offs = bpf_prog_info_read_offset_u64(&info_linear->info, 3242 + desc->array_offset); 3243 + addr = offs + ptr_to_u64(info_linear->data); 3244 + bpf_prog_info_set_offset_u64(&info_linear->info, 3245 + desc->array_offset, addr); 3246 + } 3006 3247 }
+64
tools/lib/bpf/libbpf.h
··· 10 10 #ifndef __LIBBPF_LIBBPF_H 11 11 #define __LIBBPF_LIBBPF_H 12 12 13 + #include <stdarg.h> 13 14 #include <stdio.h> 14 15 #include <stdint.h> 15 16 #include <stdbool.h> ··· 377 376 LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex); 378 377 LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id, 379 378 enum bpf_prog_type prog_type, __u32 ifindex); 379 + 380 + /* 381 + * Get bpf_prog_info in continuous memory 382 + * 383 + * struct bpf_prog_info has multiple arrays. The user has option to choose 384 + * arrays to fetch from kernel. The following APIs provide an uniform way to 385 + * fetch these data. All arrays in bpf_prog_info are stored in a single 386 + * continuous memory region. This makes it easy to store the info in a 387 + * file. 388 + * 389 + * Before writing bpf_prog_info_linear to files, it is necessary to 390 + * translate pointers in bpf_prog_info to offsets. Helper functions 391 + * bpf_program__bpil_addr_to_offs() and bpf_program__bpil_offs_to_addr() 392 + * are introduced to switch between pointers and offsets. 393 + * 394 + * Examples: 395 + * # To fetch map_ids and prog_tags: 396 + * __u64 arrays = (1UL << BPF_PROG_INFO_MAP_IDS) | 397 + * (1UL << BPF_PROG_INFO_PROG_TAGS); 398 + * struct bpf_prog_info_linear *info_linear = 399 + * bpf_program__get_prog_info_linear(fd, arrays); 400 + * 401 + * # To save data in file 402 + * bpf_program__bpil_addr_to_offs(info_linear); 403 + * write(f, info_linear, sizeof(*info_linear) + info_linear->data_len); 404 + * 405 + * # To read data from file 406 + * read(f, info_linear, <proper_size>); 407 + * bpf_program__bpil_offs_to_addr(info_linear); 408 + */ 409 + enum bpf_prog_info_array { 410 + BPF_PROG_INFO_FIRST_ARRAY = 0, 411 + BPF_PROG_INFO_JITED_INSNS = 0, 412 + BPF_PROG_INFO_XLATED_INSNS, 413 + BPF_PROG_INFO_MAP_IDS, 414 + BPF_PROG_INFO_JITED_KSYMS, 415 + BPF_PROG_INFO_JITED_FUNC_LENS, 416 + BPF_PROG_INFO_FUNC_INFO, 417 + BPF_PROG_INFO_LINE_INFO, 418 + BPF_PROG_INFO_JITED_LINE_INFO, 419 + BPF_PROG_INFO_PROG_TAGS, 420 + BPF_PROG_INFO_LAST_ARRAY, 421 + }; 422 + 423 + struct bpf_prog_info_linear { 424 + /* size of struct bpf_prog_info, when the tool is compiled */ 425 + __u32 info_len; 426 + /* total bytes allocated for data, round up to 8 bytes */ 427 + __u32 data_len; 428 + /* which arrays are included in data */ 429 + __u64 arrays; 430 + struct bpf_prog_info info; 431 + __u8 data[]; 432 + }; 433 + 434 + LIBBPF_API struct bpf_prog_info_linear * 435 + bpf_program__get_prog_info_linear(int fd, __u64 arrays); 436 + 437 + LIBBPF_API void 438 + bpf_program__bpil_addr_to_offs(struct bpf_prog_info_linear *info_linear); 439 + 440 + LIBBPF_API void 441 + bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear); 380 442 381 443 #ifdef __cplusplus 382 444 } /* extern "C" */
+3
tools/lib/bpf/libbpf.map
··· 153 153 xsk_socket__delete; 154 154 xsk_umem__fd; 155 155 xsk_socket__fd; 156 + bpf_program__get_prog_info_linear; 157 + bpf_program__bpil_addr_to_offs; 158 + bpf_program__bpil_offs_to_addr; 156 159 } LIBBPF_0.0.1;
+24
tools/perf/Documentation/Build.txt
··· 47 47 48 48 NOTE this description is omitting other libraries involved, only 49 49 focusing on build framework outcomes 50 + 51 + 3) Build with ASan or UBSan 52 + ========================== 53 + $ cd tools/perf 54 + $ make DESTDIR=/usr 55 + $ make DESTDIR=/usr install 56 + 57 + AddressSanitizer (or ASan) is a GCC feature that detects memory corruption bugs 58 + such as buffer overflows and memory leaks. 59 + 60 + $ cd tools/perf 61 + $ make DEBUG=1 EXTRA_CFLAGS='-fno-omit-frame-pointer -fsanitize=address' 62 + $ ASAN_OPTIONS=log_path=asan.log ./perf record -a 63 + 64 + ASan outputs all detected issues into a log file named 'asan.log.<pid>'. 65 + 66 + UndefinedBehaviorSanitizer (or UBSan) is a fast undefined behavior detector 67 + supported by GCC. UBSan detects undefined behaviors of programs at runtime. 68 + 69 + $ cd tools/perf 70 + $ make DEBUG=1 EXTRA_CFLAGS='-fno-omit-frame-pointer -fsanitize=undefined' 71 + $ UBSAN_OPTIONS=print_stacktrace=1 ./perf record -a 72 + 73 + If UBSan detects any problem at runtime, it outputs a “runtime error:” message.
+15 -1
tools/perf/Documentation/perf-config.txt
··· 114 114 115 115 [report] 116 116 # Defaults 117 - sort-order = comm,dso,symbol 117 + sort_order = comm,dso,symbol 118 118 percent-limit = 0 119 119 queue-size = 0 120 120 children = true ··· 583 583 584 584 llvm.opts:: 585 585 Options passed to llc. 586 + 587 + samples.*:: 588 + 589 + samples.context:: 590 + Define how many ns worth of time to show 591 + around samples in perf report sample context browser. 592 + 593 + scripts.*:: 594 + 595 + Any option defines a script that is added to the scripts menu 596 + in the interactive perf browser and whose output is displayed. 597 + The name of the option is the name, the value is a script command line. 598 + The script gets the same options passed as a full perf script, 599 + in particular -i perfdata file, --cpu, --tid 586 600 587 601 SEE ALSO 588 602 --------
+4
tools/perf/Documentation/perf-record.txt
··· 495 495 496 496 --switch-output --no-no-buildid --no-no-buildid-cache 497 497 498 + --switch-max-files=N:: 499 + 500 + When rotating perf.data with --switch-output, only keep N files. 501 + 498 502 --dry-run:: 499 503 Parse options then exit. --dry-run can be used to detect errors in cmdline 500 504 options.
+13
tools/perf/Documentation/perf-report.txt
··· 105 105 guest machine 106 106 - sample: Number of sample 107 107 - period: Raw number of event count of sample 108 + - time: Separate the samples by time stamp with the resolution specified by 109 + --time-quantum (default 100ms). Specify with overhead and before it. 108 110 109 111 By default, comm, dso and symbol keys are used. 110 112 (i.e. --sort comm,dso,symbol) ··· 461 459 --socket-filter:: 462 460 Only report the samples on the processor socket that match with this filter 463 461 462 + --samples=N:: 463 + Save N individual samples for each histogram entry to show context in perf 464 + report tui browser. 465 + 464 466 --raw-trace:: 465 467 When displaying traceevent output, do not use print fmt or plugins. 466 468 ··· 483 477 Please note that not all mmaps are stored, options affecting which ones 484 478 are include 'perf record --data', for instance. 485 479 480 + --ns:: 481 + Show time stamps in nanoseconds. 482 + 486 483 --stats:: 487 484 Display overall events statistics without any further processing. 488 485 (like the one at the end of the perf report -D command) ··· 502 493 in the scope of the function (local) or the whole data (global). 503 494 The period/hits keywords set the base the percentage is computed 504 495 on - the samples period or the number of samples (hits). 496 + 497 + --time-quantum:: 498 + Configure time quantum for time sort key. Default 100ms. 499 + Accepts s, us, ms, ns units. 505 500 506 501 include::callchain-overhead-calculation.txt[] 507 502
+3
tools/perf/Documentation/perf-script.txt
··· 380 380 Set the maximum number of program blocks to print with brstackasm for 381 381 each sample. 382 382 383 + --reltime:: 384 + Print time stamps relative to trace start. 385 + 383 386 --per-event-dump:: 384 387 Create per event files with a "perf.data.EVENT.dump" name instead of 385 388 printing to stdout, useful, for instance, for generating flamegraphs.
+2 -3
tools/perf/Documentation/perf-stat.txt
··· 72 72 --all-cpus:: 73 73 system-wide collection from all CPUs (default if no target is specified) 74 74 75 - -c:: 76 - --scale:: 77 - scale/normalize counter values 75 + --no-scale:: 76 + Don't scale/normalize counter values 78 77 79 78 -d:: 80 79 --detailed::
+7
tools/perf/Documentation/tips.txt
··· 15 15 Show individual samples with: perf script 16 16 Limit to show entries above 5% only: perf report --percent-limit 5 17 17 Profiling branch (mis)predictions with: perf record -b / perf report 18 + To show assembler sample contexts use perf record -b / perf script -F +brstackinsn --xed 18 19 Treat branches as callchains: perf report --branch-history 19 20 To count events in every 1000 msec: perf stat -I 1000 20 21 Print event counts in CSV format with: perf stat -x, ··· 35 34 Show user configuration overrides: perf config --user --list 36 35 To add Node.js USDT(User-Level Statically Defined Tracing): perf buildid-cache --add `which node` 37 36 To report cacheline events from previous recording: perf c2c report 37 + To browse sample contexts use perf report --sample 10 and select in context menu 38 + To separate samples by time use perf report --sort time,overhead,sym 39 + To set sample time separation other than 100ms with --sort time use --time-quantum 40 + Add -I to perf report to sample register values visible in perf report context. 41 + To show IPC for sampling periods use perf record -e '{cycles,instructions}:S' and then browse context 42 + To show context switches in perf report sample context add --switch-events to perf record.
+12 -3
tools/perf/Makefile.config
··· 227 227 228 228 FEATURE_CHECK_LDFLAGS-libaio = -lrt 229 229 230 + FEATURE_CHECK_LDFLAGS-disassembler-four-args = -lbfd -lopcodes 231 + 230 232 CFLAGS += -fno-omit-frame-pointer 231 233 CFLAGS += -ggdb3 232 234 CFLAGS += -funwind-tables ··· 715 713 endif 716 714 717 715 ifeq ($(feature-libbfd), 1) 718 - EXTLIBS += -lbfd 716 + EXTLIBS += -lbfd -lopcodes 719 717 else 720 718 # we are on a system that requires -liberty and (maybe) -lz 721 719 # to link against -lbfd; test each case individually here ··· 726 724 $(call feature_check,libbfd-liberty-z) 727 725 728 726 ifeq ($(feature-libbfd-liberty), 1) 729 - EXTLIBS += -lbfd -liberty 727 + EXTLIBS += -lbfd -lopcodes -liberty 728 + FEATURE_CHECK_LDFLAGS-disassembler-four-args += -liberty -ldl 730 729 else 731 730 ifeq ($(feature-libbfd-liberty-z), 1) 732 - EXTLIBS += -lbfd -liberty -lz 731 + EXTLIBS += -lbfd -lopcodes -liberty -lz 732 + FEATURE_CHECK_LDFLAGS-disassembler-four-args += -liberty -lz -ldl 733 733 endif 734 734 endif 735 + $(call feature_check,disassembler-four-args) 735 736 endif 736 737 737 738 ifdef NO_DEMANGLE ··· 811 806 812 807 ifdef HAVE_KVM_STAT_SUPPORT 813 808 CFLAGS += -DHAVE_KVM_STAT_SUPPORT 809 + endif 810 + 811 + ifeq ($(feature-disassembler-four-args), 1) 812 + CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE 814 813 endif 815 814 816 815 ifeq (${IS_64_BIT}, 1)
+4 -2
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
··· 343 343 332 common statx __x64_sys_statx 344 344 333 common io_pgetevents __x64_sys_io_pgetevents 345 345 334 common rseq __x64_sys_rseq 346 + # don't use numbers 387 through 423, add new calls after the last 347 + # 'common' entry 346 348 347 349 # 348 350 # x32-specific system call numbers start at 512 to avoid cache impact ··· 363 361 520 x32 execve __x32_compat_sys_execve/ptregs 364 362 521 x32 ptrace __x32_compat_sys_ptrace 365 363 522 x32 rt_sigpending __x32_compat_sys_rt_sigpending 366 - 523 x32 rt_sigtimedwait __x32_compat_sys_rt_sigtimedwait 364 + 523 x32 rt_sigtimedwait __x32_compat_sys_rt_sigtimedwait_time64 367 365 524 x32 rt_sigqueueinfo __x32_compat_sys_rt_sigqueueinfo 368 366 525 x32 sigaltstack __x32_compat_sys_sigaltstack 369 367 526 x32 timer_create __x32_compat_sys_timer_create ··· 377 375 534 x32 preadv __x32_compat_sys_preadv64 378 376 535 x32 pwritev __x32_compat_sys_pwritev64 379 377 536 x32 rt_tgsigqueueinfo __x32_compat_sys_rt_tgsigqueueinfo 380 - 537 x32 recvmmsg __x32_compat_sys_recvmmsg 378 + 537 x32 recvmmsg __x32_compat_sys_recvmmsg_time64 381 379 538 x32 sendmmsg __x32_compat_sys_sendmmsg 382 380 539 x32 process_vm_readv __x32_compat_sys_process_vm_readv 383 381 540 x32 process_vm_writev __x32_compat_sys_process_vm_writev
+1
tools/perf/arch/x86/util/Build
··· 14 14 perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 15 15 16 16 perf-$(CONFIG_AUXTRACE) += auxtrace.o 17 + perf-$(CONFIG_AUXTRACE) += archinsn.o 17 18 perf-$(CONFIG_AUXTRACE) += intel-pt.o 18 19 perf-$(CONFIG_AUXTRACE) += intel-bts.o
+26
tools/perf/arch/x86/util/archinsn.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include "perf.h" 3 + #include "archinsn.h" 4 + #include "util/intel-pt-decoder/insn.h" 5 + #include "machine.h" 6 + #include "thread.h" 7 + #include "symbol.h" 8 + 9 + void arch_fetch_insn(struct perf_sample *sample, 10 + struct thread *thread, 11 + struct machine *machine) 12 + { 13 + struct insn insn; 14 + int len; 15 + bool is64bit = false; 16 + 17 + if (!sample->ip) 18 + return; 19 + len = thread__memcpy(thread, machine, sample->insn, sample->ip, sizeof(sample->insn), &is64bit); 20 + if (len <= 0) 21 + return; 22 + insn_init(&insn, sample->insn, len, is64bit); 23 + insn_get_length(&insn); 24 + if (insn_complete(&insn) && insn.length <= len) 25 + sample->insn_len = insn.length; 26 + }
+1 -1
tools/perf/bench/epoll-ctl.c
··· 224 224 pthread_attr_t thread_attr, *attrp = NULL; 225 225 cpu_set_t cpuset; 226 226 unsigned int i, j; 227 - int ret; 227 + int ret = 0; 228 228 229 229 if (!noaffinity) 230 230 pthread_attr_init(&thread_attr);
+1 -1
tools/perf/bench/epoll-wait.c
··· 293 293 pthread_attr_t thread_attr, *attrp = NULL; 294 294 cpu_set_t cpuset; 295 295 unsigned int i, j; 296 - int ret, events = EPOLLIN; 296 + int ret = 0, events = EPOLLIN; 297 297 298 298 if (oneshot) 299 299 events |= EPOLLONESHOT;
+1 -1
tools/perf/builtin-list.c
··· 119 119 details_flag); 120 120 print_tracepoint_events(NULL, s, raw_dump); 121 121 print_sdt_events(NULL, s, raw_dump); 122 - metricgroup__print(true, true, NULL, raw_dump, details_flag); 122 + metricgroup__print(true, true, s, raw_dump, details_flag); 123 123 free(s); 124 124 } 125 125 }
+48 -6
tools/perf/builtin-record.c
··· 62 62 unsigned long time; 63 63 const char *str; 64 64 bool set; 65 + char **filenames; 66 + int num_files; 67 + int cur_file; 65 68 }; 66 69 67 70 struct record { ··· 395 392 size_t padding; 396 393 u8 pad[8] = {0}; 397 394 398 - if (!perf_data__is_pipe(data)) { 395 + if (!perf_data__is_pipe(data) && !perf_data__is_dir(data)) { 399 396 off_t file_offset; 400 397 int fd = perf_data__fd(data); 401 398 int err; ··· 840 837 if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns)) 841 838 perf_header__clear_feat(&session->header, HEADER_CLOCKID); 842 839 840 + perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); 841 + 843 842 perf_header__clear_feat(&session->header, HEADER_STAT); 844 843 } 845 844 ··· 895 890 { 896 891 struct perf_data *data = &rec->data; 897 892 int fd, err; 893 + char *new_filename; 898 894 899 895 /* Same Size: "2015122520103046"*/ 900 896 char timestamp[] = "InvalidTimestamp"; ··· 916 910 917 911 fd = perf_data__switch(data, timestamp, 918 912 rec->session->header.data_offset, 919 - at_exit); 913 + at_exit, &new_filename); 920 914 if (fd >= 0 && !at_exit) { 921 915 rec->bytes_written = 0; 922 916 rec->session->header.data_size = 0; ··· 925 919 if (!quiet) 926 920 fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 927 921 data->path, timestamp); 922 + 923 + if (rec->switch_output.num_files) { 924 + int n = rec->switch_output.cur_file + 1; 925 + 926 + if (n >= rec->switch_output.num_files) 927 + n = 0; 928 + rec->switch_output.cur_file = n; 929 + if (rec->switch_output.filenames[n]) { 930 + remove(rec->switch_output.filenames[n]); 931 + free(rec->switch_output.filenames[n]); 932 + } 933 + rec->switch_output.filenames[n] = new_filename; 934 + } else { 935 + free(new_filename); 936 + } 928 937 929 938 /* Output tracking events */ 930 939 if (!at_exit) { ··· 1114 1093 return err; 1115 1094 } 1116 1095 1117 - err = perf_event__synthesize_bpf_events(tool, process_synthesized_event, 1096 + err = perf_event__synthesize_bpf_events(session, process_synthesized_event, 1118 1097 machine, opts); 1119 1098 if (err < 0) 1120 1099 pr_warning("Couldn't synthesize bpf events.\n"); ··· 1137 1116 struct perf_data *data = &rec->data; 1138 1117 struct perf_session *session; 1139 1118 bool disabled = false, draining = false; 1119 + struct perf_evlist *sb_evlist = NULL; 1140 1120 int fd; 1141 1121 1142 1122 atexit(record__sig_exit); ··· 1236 1214 "Use --no-buildid to profile anyway.\n"); 1237 1215 err = -1; 1238 1216 goto out_child; 1217 + } 1218 + 1219 + if (!opts->no_bpf_event) 1220 + bpf_event__add_sb_event(&sb_evlist, &session->header.env); 1221 + 1222 + if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) { 1223 + pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n"); 1224 + opts->no_bpf_event = true; 1239 1225 } 1240 1226 1241 1227 err = record__synthesize(rec, false); ··· 1496 1466 1497 1467 out_delete_session: 1498 1468 perf_session__delete(session); 1469 + 1470 + if (!opts->no_bpf_event) 1471 + perf_evlist__stop_sb_thread(sb_evlist); 1499 1472 return status; 1500 1473 } 1501 1474 ··· 1903 1870 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 1904 1871 "synthesize non-sample events at the end of output"), 1905 1872 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 1906 - OPT_BOOLEAN(0, "bpf-event", &record.opts.bpf_event, "record bpf events"), 1873 + OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"), 1907 1874 OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq, 1908 1875 "Fail if the specified frequency can't be used"), 1909 1876 OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'", ··· 2001 1968 OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, 2002 1969 "Record timestamp boundary (time of first/last samples)"), 2003 1970 OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 2004 - &record.switch_output.set, "signal,size,time", 2005 - "Switch output when receive SIGUSR2 or cross size,time threshold", 1971 + &record.switch_output.set, "signal or size[BKMG] or time[smhd]", 1972 + "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold", 2006 1973 "signal"), 1974 + OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files, 1975 + "Limit number of switch output generated files"), 2007 1976 OPT_BOOLEAN(0, "dry-run", &dry_run, 2008 1977 "Parse options then exit"), 2009 1978 #ifdef HAVE_AIO_SUPPORT ··· 2090 2055 if (rec->switch_output.time) { 2091 2056 signal(SIGALRM, alarm_sig_handler); 2092 2057 alarm(rec->switch_output.time); 2058 + } 2059 + 2060 + if (rec->switch_output.num_files) { 2061 + rec->switch_output.filenames = calloc(sizeof(char *), 2062 + rec->switch_output.num_files); 2063 + if (!rec->switch_output.filenames) 2064 + return -EINVAL; 2093 2065 } 2094 2066 2095 2067 /*
+47 -3
tools/perf/builtin-report.c
··· 47 47 #include <errno.h> 48 48 #include <inttypes.h> 49 49 #include <regex.h> 50 + #include "sane_ctype.h" 50 51 #include <signal.h> 51 52 #include <linux/bitmap.h> 52 53 #include <linux/stringify.h> 54 + #include <linux/time64.h> 53 55 #include <sys/types.h> 54 56 #include <sys/stat.h> 55 57 #include <unistd.h> ··· 928 926 return parse_callchain_report_opt(arg); 929 927 } 930 928 929 + static int 930 + parse_time_quantum(const struct option *opt, const char *arg, 931 + int unset __maybe_unused) 932 + { 933 + unsigned long *time_q = opt->value; 934 + char *end; 935 + 936 + *time_q = strtoul(arg, &end, 0); 937 + if (end == arg) 938 + goto parse_err; 939 + if (*time_q == 0) { 940 + pr_err("time quantum cannot be 0"); 941 + return -1; 942 + } 943 + while (isspace(*end)) 944 + end++; 945 + if (*end == 0) 946 + return 0; 947 + if (!strcmp(end, "s")) { 948 + *time_q *= NSEC_PER_SEC; 949 + return 0; 950 + } 951 + if (!strcmp(end, "ms")) { 952 + *time_q *= NSEC_PER_MSEC; 953 + return 0; 954 + } 955 + if (!strcmp(end, "us")) { 956 + *time_q *= NSEC_PER_USEC; 957 + return 0; 958 + } 959 + if (!strcmp(end, "ns")) 960 + return 0; 961 + parse_err: 962 + pr_err("Cannot parse time quantum `%s'\n", arg); 963 + return -1; 964 + } 965 + 931 966 int 932 967 report_parse_ignore_callees_opt(const struct option *opt __maybe_unused, 933 968 const char *arg, int unset __maybe_unused) ··· 1083 1044 OPT_BOOLEAN(0, "header-only", &report.header_only, 1084 1045 "Show only data header."), 1085 1046 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1086 - "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." 1087 - " Please refer the man page for the complete list."), 1047 + sort_help("sort by key(s):")), 1088 1048 OPT_STRING('F', "fields", &field_order, "key[,keys...]", 1089 - "output field(s): overhead, period, sample plus all of sort keys"), 1049 + sort_help("output field(s): overhead period sample ")), 1090 1050 OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization, 1091 1051 "Show sample percentage for different cpu modes"), 1092 1052 OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, ··· 1158 1120 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 1159 1121 "Enable kernel symbol demangling"), 1160 1122 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), 1123 + OPT_INTEGER(0, "samples", &symbol_conf.res_sample, 1124 + "Number of samples to save per histogram entry for individual browsing"), 1161 1125 OPT_CALLBACK(0, "percent-limit", &report, "percent", 1162 1126 "Don't show entries under that percent", parse_percent_limit), 1163 1127 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", ··· 1187 1147 OPT_CALLBACK(0, "percent-type", &report.annotation_opts, "local-period", 1188 1148 "Set percent type local/global-period/hits", 1189 1149 annotate_parse_percent_type), 1150 + OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs, "Show times in nanosecs"), 1151 + OPT_CALLBACK(0, "time-quantum", &symbol_conf.time_quantum, "time (ms|us|ns|s)", 1152 + "Set time quantum for time sort key (default 100ms)", 1153 + parse_time_quantum), 1190 1154 OPT_END() 1191 1155 }; 1192 1156 struct perf_data data = {
+94 -35
tools/perf/builtin-script.c
··· 29 29 #include "util/time-utils.h" 30 30 #include "util/path.h" 31 31 #include "print_binary.h" 32 + #include "archinsn.h" 32 33 #include <linux/bitmap.h> 33 34 #include <linux/kernel.h> 34 35 #include <linux/stringify.h> 35 36 #include <linux/time64.h> 37 + #include <sys/utsname.h> 36 38 #include "asm/bug.h" 37 39 #include "util/mem-events.h" 38 40 #include "util/dump-insn.h" ··· 53 51 54 52 static char const *script_name; 55 53 static char const *generate_script_lang; 54 + static bool reltime; 55 + static u64 initial_time; 56 56 static bool debug_mode; 57 57 static u64 last_timestamp; 58 58 static u64 nr_unordered; ··· 62 58 static bool latency_format; 63 59 static bool system_wide; 64 60 static bool print_flags; 65 - static bool nanosecs; 66 61 static const char *cpu_list; 67 62 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 68 63 static struct perf_stat_config stat_config; 69 64 static int max_blocks; 65 + static bool native_arch; 70 66 71 67 unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; 72 68 ··· 688 684 } 689 685 690 686 if (PRINT_FIELD(TIME)) { 691 - nsecs = sample->time; 687 + u64 t = sample->time; 688 + if (reltime) { 689 + if (!initial_time) 690 + initial_time = sample->time; 691 + t = sample->time - initial_time; 692 + } 693 + nsecs = t; 692 694 secs = nsecs / NSEC_PER_SEC; 693 695 nsecs -= secs * NSEC_PER_SEC; 694 696 695 - if (nanosecs) 697 + if (symbol_conf.nanosecs) 696 698 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs); 697 699 else { 698 700 char sample_time[32]; 699 - timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time)); 701 + timestamp__scnprintf_usec(t, sample_time, sizeof(sample_time)); 700 702 printed += fprintf(fp, "%12s: ", sample_time); 701 703 } 702 704 } ··· 1237 1227 return len + dlen; 1238 1228 } 1239 1229 1230 + __weak void arch_fetch_insn(struct perf_sample *sample __maybe_unused, 1231 + struct thread *thread __maybe_unused, 1232 + struct machine *machine __maybe_unused) 1233 + { 1234 + } 1235 + 1240 1236 static int perf_sample__fprintf_insn(struct perf_sample *sample, 1241 1237 struct perf_event_attr *attr, 1242 1238 struct thread *thread, ··· 1250 1234 { 1251 1235 int printed = 0; 1252 1236 1237 + if (sample->insn_len == 0 && native_arch) 1238 + arch_fetch_insn(sample, thread, machine); 1239 + 1253 1240 if (PRINT_FIELD(INSNLEN)) 1254 1241 printed += fprintf(fp, " ilen: %d", sample->insn_len); 1255 - if (PRINT_FIELD(INSN)) { 1242 + if (PRINT_FIELD(INSN) && sample->insn_len) { 1256 1243 int i; 1257 1244 1258 1245 printed += fprintf(fp, " insn:"); ··· 1941 1922 return scripting_ops ? scripting_ops->stop_script() : 0; 1942 1923 } 1943 1924 1925 + static bool filter_cpu(struct perf_sample *sample) 1926 + { 1927 + if (cpu_list) 1928 + return !test_bit(sample->cpu, cpu_bitmap); 1929 + return false; 1930 + } 1931 + 1944 1932 static int process_sample_event(struct perf_tool *tool, 1945 1933 union perf_event *event, 1946 1934 struct perf_sample *sample, ··· 1982 1956 if (al.filtered) 1983 1957 goto out_put; 1984 1958 1985 - if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 1959 + if (filter_cpu(sample)) 1986 1960 goto out_put; 1987 1961 1988 1962 if (scripting_ops) ··· 2067 2041 sample->tid = event->comm.tid; 2068 2042 sample->pid = event->comm.pid; 2069 2043 } 2070 - perf_sample__fprintf_start(sample, thread, evsel, 2044 + if (!filter_cpu(sample)) { 2045 + perf_sample__fprintf_start(sample, thread, evsel, 2071 2046 PERF_RECORD_COMM, stdout); 2072 - perf_event__fprintf(event, stdout); 2047 + perf_event__fprintf(event, stdout); 2048 + } 2073 2049 ret = 0; 2074 2050 out: 2075 2051 thread__put(thread); ··· 2105 2077 sample->tid = event->namespaces.tid; 2106 2078 sample->pid = event->namespaces.pid; 2107 2079 } 2108 - perf_sample__fprintf_start(sample, thread, evsel, 2109 - PERF_RECORD_NAMESPACES, stdout); 2110 - perf_event__fprintf(event, stdout); 2080 + if (!filter_cpu(sample)) { 2081 + perf_sample__fprintf_start(sample, thread, evsel, 2082 + PERF_RECORD_NAMESPACES, stdout); 2083 + perf_event__fprintf(event, stdout); 2084 + } 2111 2085 ret = 0; 2112 2086 out: 2113 2087 thread__put(thread); ··· 2141 2111 sample->tid = event->fork.tid; 2142 2112 sample->pid = event->fork.pid; 2143 2113 } 2144 - perf_sample__fprintf_start(sample, thread, evsel, 2145 - PERF_RECORD_FORK, stdout); 2146 - perf_event__fprintf(event, stdout); 2114 + if (!filter_cpu(sample)) { 2115 + perf_sample__fprintf_start(sample, thread, evsel, 2116 + PERF_RECORD_FORK, stdout); 2117 + perf_event__fprintf(event, stdout); 2118 + } 2147 2119 thread__put(thread); 2148 2120 2149 2121 return 0; ··· 2173 2141 sample->tid = event->fork.tid; 2174 2142 sample->pid = event->fork.pid; 2175 2143 } 2176 - perf_sample__fprintf_start(sample, thread, evsel, 2177 - PERF_RECORD_EXIT, stdout); 2178 - perf_event__fprintf(event, stdout); 2144 + if (!filter_cpu(sample)) { 2145 + perf_sample__fprintf_start(sample, thread, evsel, 2146 + PERF_RECORD_EXIT, stdout); 2147 + perf_event__fprintf(event, stdout); 2148 + } 2179 2149 2180 2150 if (perf_event__process_exit(tool, event, sample, machine) < 0) 2181 2151 err = -1; ··· 2211 2177 sample->tid = event->mmap.tid; 2212 2178 sample->pid = event->mmap.pid; 2213 2179 } 2214 - perf_sample__fprintf_start(sample, thread, evsel, 2215 - PERF_RECORD_MMAP, stdout); 2216 - perf_event__fprintf(event, stdout); 2180 + if (!filter_cpu(sample)) { 2181 + perf_sample__fprintf_start(sample, thread, evsel, 2182 + PERF_RECORD_MMAP, stdout); 2183 + perf_event__fprintf(event, stdout); 2184 + } 2217 2185 thread__put(thread); 2218 2186 return 0; 2219 2187 } ··· 2245 2209 sample->tid = event->mmap2.tid; 2246 2210 sample->pid = event->mmap2.pid; 2247 2211 } 2248 - perf_sample__fprintf_start(sample, thread, evsel, 2249 - PERF_RECORD_MMAP2, stdout); 2250 - perf_event__fprintf(event, stdout); 2212 + if (!filter_cpu(sample)) { 2213 + perf_sample__fprintf_start(sample, thread, evsel, 2214 + PERF_RECORD_MMAP2, stdout); 2215 + perf_event__fprintf(event, stdout); 2216 + } 2251 2217 thread__put(thread); 2252 2218 return 0; 2253 2219 } ··· 2274 2236 return -1; 2275 2237 } 2276 2238 2277 - perf_sample__fprintf_start(sample, thread, evsel, 2278 - PERF_RECORD_SWITCH, stdout); 2279 - perf_event__fprintf(event, stdout); 2239 + if (!filter_cpu(sample)) { 2240 + perf_sample__fprintf_start(sample, thread, evsel, 2241 + PERF_RECORD_SWITCH, stdout); 2242 + perf_event__fprintf(event, stdout); 2243 + } 2280 2244 thread__put(thread); 2281 2245 return 0; 2282 2246 } ··· 2299 2259 if (thread == NULL) 2300 2260 return -1; 2301 2261 2302 - perf_sample__fprintf_start(sample, thread, evsel, 2303 - PERF_RECORD_LOST, stdout); 2304 - perf_event__fprintf(event, stdout); 2262 + if (!filter_cpu(sample)) { 2263 + perf_sample__fprintf_start(sample, thread, evsel, 2264 + PERF_RECORD_LOST, stdout); 2265 + perf_event__fprintf(event, stdout); 2266 + } 2305 2267 thread__put(thread); 2306 2268 return 0; 2307 2269 } ··· 2990 2948 * will list all statically runnable scripts, select one, execute it and 2991 2949 * show the output in a perf browser. 2992 2950 */ 2993 - int find_scripts(char **scripts_array, char **scripts_path_array) 2951 + int find_scripts(char **scripts_array, char **scripts_path_array, int num, 2952 + int pathlen) 2994 2953 { 2995 2954 struct dirent *script_dirent, *lang_dirent; 2996 2955 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; ··· 3036 2993 /* Skip those real time scripts: xxxtop.p[yl] */ 3037 2994 if (strstr(script_dirent->d_name, "top.")) 3038 2995 continue; 3039 - sprintf(scripts_path_array[i], "%s/%s", lang_path, 2996 + if (i >= num) 2997 + break; 2998 + snprintf(scripts_path_array[i], pathlen, "%s/%s", 2999 + lang_path, 3040 3000 script_dirent->d_name); 3041 3001 temp = strchr(script_dirent->d_name, '.'); 3042 3002 snprintf(scripts_array[i], ··· 3278 3232 { 3279 3233 parse_output_fields(NULL, "+insn,-event,-period", 0); 3280 3234 itrace_parse_synth_opts(opt, "i0ns", 0); 3281 - nanosecs = true; 3235 + symbol_conf.nanosecs = true; 3282 3236 return 0; 3283 3237 } 3284 3238 ··· 3296 3250 { 3297 3251 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0); 3298 3252 itrace_parse_synth_opts(opt, "cewp", 0); 3299 - nanosecs = true; 3253 + symbol_conf.nanosecs = true; 3300 3254 return 0; 3301 3255 } 3302 3256 ··· 3306 3260 { 3307 3261 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0); 3308 3262 itrace_parse_synth_opts(opt, "crewp", 0); 3309 - nanosecs = true; 3263 + symbol_conf.nanosecs = true; 3310 3264 return 0; 3311 3265 } 3312 3266 ··· 3323 3277 .set = false, 3324 3278 .default_no_sample = true, 3325 3279 }; 3280 + struct utsname uts; 3326 3281 char *script_path = NULL; 3327 3282 const char **__argv; 3328 3283 int i, j, err = 0; ··· 3421 3374 "Set the maximum stack depth when parsing the callchain, " 3422 3375 "anything beyond the specified depth will be ignored. " 3423 3376 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), 3377 + OPT_BOOLEAN(0, "reltime", &reltime, "Show time stamps relative to start"), 3424 3378 OPT_BOOLEAN('I', "show-info", &show_full_info, 3425 3379 "display extended information from perf.data file"), 3426 3380 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, ··· 3443 3395 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 3444 3396 OPT_INTEGER(0, "max-blocks", &max_blocks, 3445 3397 "Maximum number of code blocks to dump with brstackinsn"), 3446 - OPT_BOOLEAN(0, "ns", &nanosecs, 3398 + OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs, 3447 3399 "Use 9 decimal places when displaying time"), 3448 3400 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 3449 3401 "Instruction Tracing options\n" ITRACE_HELP, ··· 3494 3446 "(see 'perf script -l' for listing)\n"); 3495 3447 return -1; 3496 3448 } 3449 + } 3450 + 3451 + if (script.time_str && reltime) { 3452 + fprintf(stderr, "Don't combine --reltime with --time\n"); 3453 + return -1; 3497 3454 } 3498 3455 3499 3456 if (itrace_synth_opts.callchain && ··· 3667 3614 3668 3615 if (symbol__init(&session->header.env) < 0) 3669 3616 goto out_delete; 3617 + 3618 + uname(&uts); 3619 + if (!strcmp(uts.machine, session->header.env.arch) || 3620 + (!strcmp(uts.machine, "x86_64") && 3621 + !strcmp(session->header.env.arch, "i386"))) 3622 + native_arch = true; 3670 3623 3671 3624 script.session = session; 3672 3625 script__setup_sample_type(&script);
+2 -1
tools/perf/builtin-stat.c
··· 718 718 "system-wide collection from all CPUs"), 719 719 OPT_BOOLEAN('g', "group", &group, 720 720 "put the counters into a counter group"), 721 - OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"), 721 + OPT_BOOLEAN(0, "scale", &stat_config.scale, 722 + "Use --no-scale to disable counter scaling for multiplexing"), 722 723 OPT_INCR('v', "verbose", &verbose, 723 724 "be more verbose (show counter open errors, etc)"), 724 725 OPT_INTEGER('r', "repeat", &stat_config.run_count,
+36 -26
tools/perf/builtin-top.c
··· 1189 1189 pthread_t thread, thread_process; 1190 1190 int ret; 1191 1191 1192 - top->session = perf_session__new(NULL, false, NULL); 1193 - if (top->session == NULL) 1194 - return -1; 1195 - 1196 1192 if (!top->annotation_opts.objdump_path) { 1197 1193 ret = perf_env__lookup_objdump(&top->session->header.env, 1198 1194 &top->annotation_opts.objdump_path); 1199 1195 if (ret) 1200 - goto out_delete; 1196 + return ret; 1201 1197 } 1202 1198 1203 1199 ret = callchain_param__setup_sample_type(&callchain_param); 1204 1200 if (ret) 1205 - goto out_delete; 1201 + return ret; 1206 1202 1207 1203 if (perf_session__register_idle_thread(top->session) < 0) 1208 - goto out_delete; 1204 + return ret; 1209 1205 1210 1206 if (top->nr_threads_synthesize > 1) 1211 1207 perf_set_multithreaded(); 1212 1208 1213 1209 init_process_thread(top); 1214 1210 1215 - ret = perf_event__synthesize_bpf_events(&top->tool, perf_event__process, 1211 + ret = perf_event__synthesize_bpf_events(top->session, perf_event__process, 1216 1212 &top->session->machines.host, 1217 1213 &top->record_opts); 1218 1214 if (ret < 0) ··· 1223 1227 1224 1228 if (perf_hpp_list.socket) { 1225 1229 ret = perf_env__read_cpu_topology_map(&perf_env); 1226 - if (ret < 0) 1227 - goto out_err_cpu_topo; 1230 + if (ret < 0) { 1231 + char errbuf[BUFSIZ]; 1232 + const char *err = str_error_r(-ret, errbuf, sizeof(errbuf)); 1233 + 1234 + ui__error("Could not read the CPU topology map: %s\n", err); 1235 + return ret; 1236 + } 1228 1237 } 1229 1238 1230 1239 ret = perf_top__start_counters(top); 1231 1240 if (ret) 1232 - goto out_delete; 1241 + return ret; 1233 1242 1234 1243 top->session->evlist = top->evlist; 1235 1244 perf_session__set_id_hdr_size(top->session); ··· 1253 1252 ret = -1; 1254 1253 if (pthread_create(&thread_process, NULL, process_thread, top)) { 1255 1254 ui__error("Could not create process thread.\n"); 1256 - goto out_delete; 1255 + return ret; 1257 1256 } 1258 1257 1259 1258 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : ··· 1297 1296 out_join_thread: 1298 1297 pthread_cond_signal(&top->qe.cond); 1299 1298 pthread_join(thread_process, NULL); 1300 - out_delete: 1301 - perf_session__delete(top->session); 1302 - top->session = NULL; 1303 - 1304 1299 return ret; 1305 - 1306 - out_err_cpu_topo: { 1307 - char errbuf[BUFSIZ]; 1308 - const char *err = str_error_r(-ret, errbuf, sizeof(errbuf)); 1309 - 1310 - ui__error("Could not read the CPU topology map: %s\n", err); 1311 - goto out_delete; 1312 - } 1313 1300 } 1314 1301 1315 1302 static int ··· 1469 1480 "Display raw encoding of assembly instructions (default)"), 1470 1481 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 1471 1482 "Enable kernel symbol demangling"), 1483 + OPT_BOOLEAN(0, "no-bpf-event", &top.record_opts.no_bpf_event, "do not record bpf events"), 1472 1484 OPT_STRING(0, "objdump", &top.annotation_opts.objdump_path, "path", 1473 1485 "objdump binary to use for disassembly and annotations"), 1474 1486 OPT_STRING('M', "disassembler-style", &top.annotation_opts.disassembler_style, "disassembler style", ··· 1501 1511 "number of thread to run event synthesize"), 1502 1512 OPT_END() 1503 1513 }; 1514 + struct perf_evlist *sb_evlist = NULL; 1504 1515 const char * const top_usage[] = { 1505 1516 "perf top [<options>]", 1506 1517 NULL ··· 1619 1628 annotation_config__init(); 1620 1629 1621 1630 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1622 - if (symbol__init(NULL) < 0) 1623 - return -1; 1631 + status = symbol__init(NULL); 1632 + if (status < 0) 1633 + goto out_delete_evlist; 1624 1634 1625 1635 sort__setup_elide(stdout); 1626 1636 ··· 1631 1639 signal(SIGWINCH, winch_sig); 1632 1640 } 1633 1641 1642 + top.session = perf_session__new(NULL, false, NULL); 1643 + if (top.session == NULL) { 1644 + status = -1; 1645 + goto out_delete_evlist; 1646 + } 1647 + 1648 + if (!top.record_opts.no_bpf_event) 1649 + bpf_event__add_sb_event(&sb_evlist, &perf_env); 1650 + 1651 + if (perf_evlist__start_sb_thread(sb_evlist, target)) { 1652 + pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n"); 1653 + opts->no_bpf_event = true; 1654 + } 1655 + 1634 1656 status = __cmd_top(&top); 1657 + 1658 + if (!opts->no_bpf_event) 1659 + perf_evlist__stop_sb_thread(sb_evlist); 1635 1660 1636 1661 out_delete_evlist: 1637 1662 perf_evlist__delete(top.evlist); 1663 + perf_session__delete(top.session); 1638 1664 1639 1665 return status; 1640 1666 }
+2 -1
tools/perf/builtin.h
··· 40 40 int cmd_data(int argc, const char **argv); 41 41 int cmd_ftrace(int argc, const char **argv); 42 42 43 - int find_scripts(char **scripts_array, char **scripts_path_array); 43 + int find_scripts(char **scripts_array, char **scripts_path_array, int num, 44 + int pathlen); 44 45 #endif
+1
tools/perf/perf.c
··· 298 298 use_pager = 1; 299 299 commit_pager_choice(); 300 300 301 + perf_env__init(&perf_env); 301 302 perf_env__set_cmdline(&perf_env, argc, argv); 302 303 status = p->fn(argc, argv); 303 304 perf_config__exit();
+1 -1
tools/perf/perf.h
··· 66 66 bool ignore_missing_thread; 67 67 bool strict_freq; 68 68 bool sample_id; 69 - bool bpf_event; 69 + bool no_bpf_event; 70 70 unsigned int freq; 71 71 unsigned int mmap_pages; 72 72 unsigned int auxtrace_mmap_pages;
-594
tools/perf/pmu-events/arch/powerpc/power8/other.json
··· 348 348 "PublicDescription": "" 349 349 }, 350 350 {, 351 - "EventCode": "0x517082", 352 - "EventName": "PM_CO_DISP_FAIL", 353 - "BriefDescription": "CO dispatch failed due to all CO machines being busy", 354 - "PublicDescription": "" 355 - }, 356 - {, 357 - "EventCode": "0x527084", 358 - "EventName": "PM_CO_TM_SC_FOOTPRINT", 359 - "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3)", 360 - "PublicDescription": "" 361 - }, 362 - {, 363 351 "EventCode": "0x3608a", 364 352 "EventName": "PM_CO_USAGE", 365 353 "BriefDescription": "Continuous 16 cycle(2to1) window where this signals rotates thru sampling each L2 CO machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running", ··· 1566 1578 "PublicDescription": "" 1567 1579 }, 1568 1580 {, 1569 - "EventCode": "0x617082", 1570 - "EventName": "PM_ISIDE_DISP", 1571 - "BriefDescription": "All i-side dispatch attempts", 1572 - "PublicDescription": "" 1573 - }, 1574 - {, 1575 - "EventCode": "0x627084", 1576 - "EventName": "PM_ISIDE_DISP_FAIL", 1577 - "BriefDescription": "All i-side dispatch attempts that failed due to a addr collision with another machine", 1578 - "PublicDescription": "" 1579 - }, 1580 - {, 1581 - "EventCode": "0x627086", 1582 - "EventName": "PM_ISIDE_DISP_FAIL_OTHER", 1583 - "BriefDescription": "All i-side dispatch attempts that failed due to a reason other than addrs collision", 1584 - "PublicDescription": "" 1585 - }, 1586 - {, 1587 1581 "EventCode": "0x4608e", 1588 1582 "EventName": "PM_ISIDE_L2MEMACC", 1589 1583 "BriefDescription": "valid when first beat of data comes in for an i-side fetch where data came from mem(or L4)", 1590 - "PublicDescription": "" 1591 - }, 1592 - {, 1593 - "EventCode": "0x44608e", 1594 - "EventName": "PM_ISIDE_MRU_TOUCH", 1595 - "BriefDescription": "Iside L2 MRU touch", 1596 1584 "PublicDescription": "" 1597 1585 }, 1598 1586 {, ··· 1698 1734 "PublicDescription": "" 1699 1735 }, 1700 1736 {, 1701 - "EventCode": "0x417080", 1702 - "EventName": "PM_L2_CASTOUT_MOD", 1703 - "BriefDescription": "L2 Castouts - Modified (M, Mu, Me)", 1704 - "PublicDescription": "" 1705 - }, 1706 - {, 1707 - "EventCode": "0x417082", 1708 - "EventName": "PM_L2_CASTOUT_SHR", 1709 - "BriefDescription": "L2 Castouts - Shared (T, Te, Si, S)", 1710 - "PublicDescription": "" 1711 - }, 1712 - {, 1713 1737 "EventCode": "0x27084", 1714 1738 "EventName": "PM_L2_CHIP_PUMP", 1715 1739 "BriefDescription": "RC requests that were local on chip pump attempts", 1716 - "PublicDescription": "" 1717 - }, 1718 - {, 1719 - "EventCode": "0x427086", 1720 - "EventName": "PM_L2_DC_INV", 1721 - "BriefDescription": "Dcache invalidates from L2", 1722 - "PublicDescription": "" 1723 - }, 1724 - {, 1725 - "EventCode": "0x44608c", 1726 - "EventName": "PM_L2_DISP_ALL_L2MISS", 1727 - "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2miss", 1728 1740 "PublicDescription": "" 1729 1741 }, 1730 1742 {, ··· 1710 1770 "PublicDescription": "" 1711 1771 }, 1712 1772 {, 1713 - "EventCode": "0x626084", 1714 - "EventName": "PM_L2_GRP_GUESS_CORRECT", 1715 - "BriefDescription": "L2 guess grp and guess was correct (data intra-6chip AND ^on-chip)", 1716 - "PublicDescription": "" 1717 - }, 1718 - {, 1719 - "EventCode": "0x626086", 1720 - "EventName": "PM_L2_GRP_GUESS_WRONG", 1721 - "BriefDescription": "L2 guess grp and guess was not correct (ie data on-chip OR beyond-6chip)", 1722 - "PublicDescription": "" 1723 - }, 1724 - {, 1725 - "EventCode": "0x427084", 1726 - "EventName": "PM_L2_IC_INV", 1727 - "BriefDescription": "Icache Invalidates from L2", 1728 - "PublicDescription": "" 1729 - }, 1730 - {, 1731 - "EventCode": "0x436088", 1732 - "EventName": "PM_L2_INST", 1733 - "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)", 1734 - "PublicDescription": "" 1735 - }, 1736 - {, 1737 - "EventCode": "0x43608a", 1738 - "EventName": "PM_L2_INST_MISS", 1739 - "BriefDescription": "All successful i-side dispatches that were an L2miss for this thread (excludes i_l2mru_tch reqs)", 1740 - "PublicDescription": "" 1741 - }, 1742 - {, 1743 - "EventCode": "0x416080", 1744 - "EventName": "PM_L2_LD", 1745 - "BriefDescription": "All successful D-side Load dispatches for this thread", 1746 - "PublicDescription": "" 1747 - }, 1748 - {, 1749 - "EventCode": "0x437088", 1750 - "EventName": "PM_L2_LD_DISP", 1751 - "BriefDescription": "All successful load dispatches", 1752 - "PublicDescription": "" 1753 - }, 1754 - {, 1755 - "EventCode": "0x43708a", 1756 - "EventName": "PM_L2_LD_HIT", 1757 - "BriefDescription": "All successful load dispatches that were L2 hits", 1758 - "PublicDescription": "" 1759 - }, 1760 - {, 1761 - "EventCode": "0x426084", 1762 - "EventName": "PM_L2_LD_MISS", 1763 - "BriefDescription": "All successful D-Side Load dispatches that were an L2miss for this thread", 1764 - "PublicDescription": "" 1765 - }, 1766 - {, 1767 - "EventCode": "0x616080", 1768 - "EventName": "PM_L2_LOC_GUESS_CORRECT", 1769 - "BriefDescription": "L2 guess loc and guess was correct (ie data local)", 1770 - "PublicDescription": "" 1771 - }, 1772 - {, 1773 - "EventCode": "0x616082", 1774 - "EventName": "PM_L2_LOC_GUESS_WRONG", 1775 - "BriefDescription": "L2 guess loc and guess was not correct (ie data not on chip)", 1776 - "PublicDescription": "" 1777 - }, 1778 - {, 1779 - "EventCode": "0x516080", 1780 - "EventName": "PM_L2_RCLD_DISP", 1781 - "BriefDescription": "L2 RC load dispatch attempt", 1782 - "PublicDescription": "" 1783 - }, 1784 - {, 1785 - "EventCode": "0x516082", 1786 - "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR", 1787 - "BriefDescription": "L2 RC load dispatch attempt failed due to address collision with RC/CO/SN/SQ", 1788 - "PublicDescription": "" 1789 - }, 1790 - {, 1791 - "EventCode": "0x526084", 1792 - "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER", 1793 - "BriefDescription": "L2 RC load dispatch attempt failed due to other reasons", 1794 - "PublicDescription": "" 1795 - }, 1796 - {, 1797 - "EventCode": "0x536088", 1798 - "EventName": "PM_L2_RCST_DISP", 1799 - "BriefDescription": "L2 RC store dispatch attempt", 1800 - "PublicDescription": "" 1801 - }, 1802 - {, 1803 - "EventCode": "0x53608a", 1804 - "EventName": "PM_L2_RCST_DISP_FAIL_ADDR", 1805 - "BriefDescription": "L2 RC store dispatch attempt failed due to address collision with RC/CO/SN/SQ", 1806 - "PublicDescription": "" 1807 - }, 1808 - {, 1809 - "EventCode": "0x54608c", 1810 - "EventName": "PM_L2_RCST_DISP_FAIL_OTHER", 1811 - "BriefDescription": "L2 RC store dispatch attempt failed due to other reasons", 1812 - "PublicDescription": "" 1813 - }, 1814 - {, 1815 - "EventCode": "0x537088", 1816 - "EventName": "PM_L2_RC_ST_DONE", 1817 - "BriefDescription": "RC did st to line that was Tx or Sx", 1818 - "PublicDescription": "" 1819 - }, 1820 - {, 1821 - "EventCode": "0x63708a", 1822 - "EventName": "PM_L2_RTY_LD", 1823 - "BriefDescription": "RC retries on PB for any load from core", 1824 - "PublicDescription": "" 1825 - }, 1826 - {, 1827 1773 "EventCode": "0x3708a", 1828 1774 "EventName": "PM_L2_RTY_ST", 1829 1775 "BriefDescription": "RC retries on PB for any store from core", 1830 - "PublicDescription": "" 1831 - }, 1832 - {, 1833 - "EventCode": "0x54708c", 1834 - "EventName": "PM_L2_SN_M_RD_DONE", 1835 - "BriefDescription": "SNP dispatched for a read and was M", 1836 - "PublicDescription": "" 1837 - }, 1838 - {, 1839 - "EventCode": "0x54708e", 1840 - "EventName": "PM_L2_SN_M_WR_DONE", 1841 - "BriefDescription": "SNP dispatched for a write and was M", 1842 - "PublicDescription": "" 1843 - }, 1844 - {, 1845 - "EventCode": "0x53708a", 1846 - "EventName": "PM_L2_SN_SX_I_DONE", 1847 - "BriefDescription": "SNP dispatched and went from Sx or Tx to Ix", 1848 1776 "PublicDescription": "" 1849 1777 }, 1850 1778 {, ··· 1722 1914 "PublicDescription": "" 1723 1915 }, 1724 1916 {, 1725 - "EventCode": "0x44708c", 1726 - "EventName": "PM_L2_ST_DISP", 1727 - "BriefDescription": "All successful store dispatches", 1728 - "PublicDescription": "" 1729 - }, 1730 - {, 1731 - "EventCode": "0x44708e", 1732 - "EventName": "PM_L2_ST_HIT", 1733 - "BriefDescription": "All successful store dispatches that were L2Hits", 1734 - "PublicDescription": "" 1735 - }, 1736 - {, 1737 1917 "EventCode": "0x17082", 1738 1918 "EventName": "PM_L2_ST_MISS", 1739 1919 "BriefDescription": "All successful D-side store dispatches for this thread that were L2 Miss", 1740 - "PublicDescription": "" 1741 - }, 1742 - {, 1743 - "EventCode": "0x636088", 1744 - "EventName": "PM_L2_SYS_GUESS_CORRECT", 1745 - "BriefDescription": "L2 guess sys and guess was correct (ie data beyond-6chip)", 1746 - "PublicDescription": "" 1747 - }, 1748 - {, 1749 - "EventCode": "0x63608a", 1750 - "EventName": "PM_L2_SYS_GUESS_WRONG", 1751 - "BriefDescription": "L2 guess sys and guess was not correct (ie data ^beyond-6chip)", 1752 - "PublicDescription": "" 1753 - }, 1754 - {, 1755 - "EventCode": "0x617080", 1756 - "EventName": "PM_L2_SYS_PUMP", 1757 - "BriefDescription": "RC requests that were system pump attempts", 1758 1920 "PublicDescription": "" 1759 1921 }, 1760 1922 {, ··· 1740 1962 "PublicDescription": "" 1741 1963 }, 1742 1964 {, 1743 - "EventCode": "0x23808a", 1744 - "EventName": "PM_L3_CINJ", 1745 - "BriefDescription": "l3 ci of cache inject", 1746 - "PublicDescription": "" 1747 - }, 1748 - {, 1749 - "EventCode": "0x128084", 1750 - "EventName": "PM_L3_CI_HIT", 1751 - "BriefDescription": "L3 Castins Hit (total count", 1752 - "PublicDescription": "" 1753 - }, 1754 - {, 1755 - "EventCode": "0x128086", 1756 - "EventName": "PM_L3_CI_MISS", 1757 - "BriefDescription": "L3 castins miss (total count", 1758 - "PublicDescription": "" 1759 - }, 1760 - {, 1761 1965 "EventCode": "0x819082", 1762 1966 "EventName": "PM_L3_CI_USAGE", 1763 1967 "BriefDescription": "rotating sample of 16 CI or CO actives", 1764 - "PublicDescription": "" 1765 - }, 1766 - {, 1767 - "EventCode": "0x438088", 1768 - "EventName": "PM_L3_CO", 1769 - "BriefDescription": "l3 castout occurring ( does not include casthrough or log writes (cinj/dmaw)", 1770 1968 "PublicDescription": "" 1771 1969 }, 1772 1970 {, ··· 1764 2010 "PublicDescription": "" 1765 2011 }, 1766 2012 {, 1767 - "EventCode": "0x238088", 1768 - "EventName": "PM_L3_CO_LCO", 1769 - "BriefDescription": "Total L3 castouts occurred on LCO", 1770 - "PublicDescription": "" 1771 - }, 1772 - {, 1773 2013 "EventCode": "0x28084", 1774 2014 "EventName": "PM_L3_CO_MEM", 1775 2015 "BriefDescription": "L3 CO to memory OR of port 0 and 1 ( lossy)", 1776 2016 "PublicDescription": "" 1777 2017 }, 1778 2018 {, 1779 - "EventCode": "0xb19082", 1780 - "EventName": "PM_L3_GRP_GUESS_CORRECT", 1781 - "BriefDescription": "Initial scope=group and data from same group (near) (pred successful)", 1782 - "PublicDescription": "" 1783 - }, 1784 - {, 1785 - "EventCode": "0xb3908a", 1786 - "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH", 1787 - "BriefDescription": "Initial scope=group but data from local node. Predition too high", 1788 - "PublicDescription": "" 1789 - }, 1790 - {, 1791 - "EventCode": "0xb39088", 1792 - "EventName": "PM_L3_GRP_GUESS_WRONG_LOW", 1793 - "BriefDescription": "Initial scope=group but data from outside group (far or rem). Prediction too Low", 1794 - "PublicDescription": "" 1795 - }, 1796 - {, 1797 - "EventCode": "0x218080", 1798 - "EventName": "PM_L3_HIT", 1799 - "BriefDescription": "L3 Hits", 1800 - "PublicDescription": "" 1801 - }, 1802 - {, 1803 - "EventCode": "0x138088", 1804 - "EventName": "PM_L3_L2_CO_HIT", 1805 - "BriefDescription": "L2 castout hits", 1806 - "PublicDescription": "" 1807 - }, 1808 - {, 1809 - "EventCode": "0x13808a", 1810 - "EventName": "PM_L3_L2_CO_MISS", 1811 - "BriefDescription": "L2 castout miss", 1812 - "PublicDescription": "" 1813 - }, 1814 - {, 1815 - "EventCode": "0x14808c", 1816 - "EventName": "PM_L3_LAT_CI_HIT", 1817 - "BriefDescription": "L3 Lateral Castins Hit", 1818 - "PublicDescription": "" 1819 - }, 1820 - {, 1821 - "EventCode": "0x14808e", 1822 - "EventName": "PM_L3_LAT_CI_MISS", 1823 - "BriefDescription": "L3 Lateral Castins Miss", 1824 - "PublicDescription": "" 1825 - }, 1826 - {, 1827 - "EventCode": "0x228084", 1828 - "EventName": "PM_L3_LD_HIT", 1829 - "BriefDescription": "L3 demand LD Hits", 1830 - "PublicDescription": "" 1831 - }, 1832 - {, 1833 - "EventCode": "0x228086", 1834 - "EventName": "PM_L3_LD_MISS", 1835 - "BriefDescription": "L3 demand LD Miss", 1836 - "PublicDescription": "" 1837 - }, 1838 - {, 1839 2019 "EventCode": "0x1e052", 1840 2020 "EventName": "PM_L3_LD_PREF", 1841 2021 "BriefDescription": "L3 Load Prefetches", 1842 - "PublicDescription": "" 1843 - }, 1844 - {, 1845 - "EventCode": "0xb19080", 1846 - "EventName": "PM_L3_LOC_GUESS_CORRECT", 1847 - "BriefDescription": "initial scope=node/chip and data from local node (local) (pred successful)", 1848 - "PublicDescription": "" 1849 - }, 1850 - {, 1851 - "EventCode": "0xb29086", 1852 - "EventName": "PM_L3_LOC_GUESS_WRONG", 1853 - "BriefDescription": "Initial scope=node but data from out side local node (near or far or rem). Prediction too Low", 1854 - "PublicDescription": "" 1855 - }, 1856 - {, 1857 - "EventCode": "0x218082", 1858 - "EventName": "PM_L3_MISS", 1859 - "BriefDescription": "L3 Misses", 1860 - "PublicDescription": "" 1861 - }, 1862 - {, 1863 - "EventCode": "0x54808c", 1864 - "EventName": "PM_L3_P0_CO_L31", 1865 - "BriefDescription": "l3 CO to L3.1 (lco) port 0", 1866 - "PublicDescription": "" 1867 - }, 1868 - {, 1869 - "EventCode": "0x538088", 1870 - "EventName": "PM_L3_P0_CO_MEM", 1871 - "BriefDescription": "l3 CO to memory port 0", 1872 - "PublicDescription": "" 1873 - }, 1874 - {, 1875 - "EventCode": "0x929084", 1876 - "EventName": "PM_L3_P0_CO_RTY", 1877 - "BriefDescription": "L3 CO received retry port 0", 1878 2022 "PublicDescription": "" 1879 2023 }, 1880 2024 {, ··· 1800 2148 "PublicDescription": "" 1801 2149 }, 1802 2150 {, 1803 - "EventCode": "0xa19080", 1804 - "EventName": "PM_L3_P0_NODE_PUMP", 1805 - "BriefDescription": "L3 pf sent with nodal scope port 0", 1806 - "PublicDescription": "" 1807 - }, 1808 - {, 1809 - "EventCode": "0x919080", 1810 - "EventName": "PM_L3_P0_PF_RTY", 1811 - "BriefDescription": "L3 PF received retry port 0", 1812 - "PublicDescription": "" 1813 - }, 1814 - {, 1815 - "EventCode": "0x939088", 1816 - "EventName": "PM_L3_P0_SN_HIT", 1817 - "BriefDescription": "L3 snoop hit port 0", 1818 - "PublicDescription": "" 1819 - }, 1820 - {, 1821 - "EventCode": "0x118080", 1822 - "EventName": "PM_L3_P0_SN_INV", 1823 - "BriefDescription": "Port0 snooper detects someone doing a store to a line thats Sx", 1824 - "PublicDescription": "" 1825 - }, 1826 - {, 1827 - "EventCode": "0x94908c", 1828 - "EventName": "PM_L3_P0_SN_MISS", 1829 - "BriefDescription": "L3 snoop miss port 0", 1830 - "PublicDescription": "" 1831 - }, 1832 - {, 1833 - "EventCode": "0xa39088", 1834 - "EventName": "PM_L3_P0_SYS_PUMP", 1835 - "BriefDescription": "L3 pf sent with sys scope port 0", 1836 - "PublicDescription": "" 1837 - }, 1838 - {, 1839 - "EventCode": "0x54808e", 1840 - "EventName": "PM_L3_P1_CO_L31", 1841 - "BriefDescription": "l3 CO to L3.1 (lco) port 1", 1842 - "PublicDescription": "" 1843 - }, 1844 - {, 1845 - "EventCode": "0x53808a", 1846 - "EventName": "PM_L3_P1_CO_MEM", 1847 - "BriefDescription": "l3 CO to memory port 1", 1848 - "PublicDescription": "" 1849 - }, 1850 - {, 1851 - "EventCode": "0x929086", 1852 - "EventName": "PM_L3_P1_CO_RTY", 1853 - "BriefDescription": "L3 CO received retry port 1", 1854 - "PublicDescription": "" 1855 - }, 1856 - {, 1857 - "EventCode": "0xa29086", 1858 - "EventName": "PM_L3_P1_GRP_PUMP", 1859 - "BriefDescription": "L3 pf sent with grp scope port 1", 1860 - "PublicDescription": "" 1861 - }, 1862 - {, 1863 - "EventCode": "0x528086", 1864 - "EventName": "PM_L3_P1_LCO_DATA", 1865 - "BriefDescription": "lco sent with data port 1", 1866 - "PublicDescription": "" 1867 - }, 1868 - {, 1869 - "EventCode": "0x518082", 1870 - "EventName": "PM_L3_P1_LCO_NO_DATA", 1871 - "BriefDescription": "dataless l3 lco sent port 1", 1872 - "PublicDescription": "" 1873 - }, 1874 - {, 1875 - "EventCode": "0xa4908e", 1876 - "EventName": "PM_L3_P1_LCO_RTY", 1877 - "BriefDescription": "L3 LCO received retry port 1", 1878 - "PublicDescription": "" 1879 - }, 1880 - {, 1881 - "EventCode": "0xa19082", 1882 - "EventName": "PM_L3_P1_NODE_PUMP", 1883 - "BriefDescription": "L3 pf sent with nodal scope port 1", 1884 - "PublicDescription": "" 1885 - }, 1886 - {, 1887 - "EventCode": "0x919082", 1888 - "EventName": "PM_L3_P1_PF_RTY", 1889 - "BriefDescription": "L3 PF received retry port 1", 1890 - "PublicDescription": "" 1891 - }, 1892 - {, 1893 - "EventCode": "0x93908a", 1894 - "EventName": "PM_L3_P1_SN_HIT", 1895 - "BriefDescription": "L3 snoop hit port 1", 1896 - "PublicDescription": "" 1897 - }, 1898 - {, 1899 - "EventCode": "0x118082", 1900 - "EventName": "PM_L3_P1_SN_INV", 1901 - "BriefDescription": "Port1 snooper detects someone doing a store to a line thats Sx", 1902 - "PublicDescription": "" 1903 - }, 1904 - {, 1905 - "EventCode": "0x94908e", 1906 - "EventName": "PM_L3_P1_SN_MISS", 1907 - "BriefDescription": "L3 snoop miss port 1", 1908 - "PublicDescription": "" 1909 - }, 1910 - {, 1911 - "EventCode": "0xa3908a", 1912 - "EventName": "PM_L3_P1_SYS_PUMP", 1913 - "BriefDescription": "L3 pf sent with sys scope port 1", 1914 - "PublicDescription": "" 1915 - }, 1916 - {, 1917 2151 "EventCode": "0x84908d", 1918 2152 "EventName": "PM_L3_PF0_ALLOC", 1919 2153 "BriefDescription": "lifetime, sample of PF machine 0 valid", ··· 1809 2271 "EventCode": "0x84908c", 1810 2272 "EventName": "PM_L3_PF0_BUSY", 1811 2273 "BriefDescription": "lifetime, sample of PF machine 0 valid", 1812 - "PublicDescription": "" 1813 - }, 1814 - {, 1815 - "EventCode": "0x428084", 1816 - "EventName": "PM_L3_PF_HIT_L3", 1817 - "BriefDescription": "l3 pf hit in l3", 1818 2274 "PublicDescription": "" 1819 2275 }, 1820 2276 {, ··· 1902 2370 "PublicDescription": "" 1903 2371 }, 1904 2372 {, 1905 - "EventCode": "0xb29084", 1906 - "EventName": "PM_L3_SYS_GUESS_CORRECT", 1907 - "BriefDescription": "Initial scope=system and data from outside group (far or rem)(pred successful)", 1908 - "PublicDescription": "" 1909 - }, 1910 - {, 1911 - "EventCode": "0xb4908c", 1912 - "EventName": "PM_L3_SYS_GUESS_WRONG", 1913 - "BriefDescription": "Initial scope=system but data from local or near. Predction too high", 1914 - "PublicDescription": "" 1915 - }, 1916 - {, 1917 - "EventCode": "0x24808e", 1918 - "EventName": "PM_L3_TRANS_PF", 1919 - "BriefDescription": "L3 Transient prefetch", 1920 - "PublicDescription": "" 1921 - }, 1922 - {, 1923 2373 "EventCode": "0x18081", 1924 2374 "EventName": "PM_L3_WI0_ALLOC", 1925 2375 "BriefDescription": "lifetime, sample of Write Inject machine 0 valid", 1926 2376 "PublicDescription": "0.0" 1927 - }, 1928 - {, 1929 - "EventCode": "0x418080", 1930 - "EventName": "PM_L3_WI0_BUSY", 1931 - "BriefDescription": "lifetime, sample of Write Inject machine 0 valid", 1932 - "PublicDescription": "" 1933 - }, 1934 - {, 1935 - "EventCode": "0x418082", 1936 - "EventName": "PM_L3_WI_USAGE", 1937 - "BriefDescription": "rotating sample of 8 WI actives", 1938 - "PublicDescription": "" 1939 2377 }, 1940 2378 {, 1941 2379 "EventCode": "0xc080", ··· 2814 3312 "PublicDescription": "" 2815 3313 }, 2816 3314 {, 2817 - "EventCode": "0x328084", 2818 - "EventName": "PM_NON_TM_RST_SC", 2819 - "BriefDescription": "non tm snp rst tm sc", 2820 - "PublicDescription": "" 2821 - }, 2822 - {, 2823 3315 "EventCode": "0x2001a", 2824 3316 "EventName": "PM_NTCG_ALL_FIN", 2825 3317 "BriefDescription": "Cycles after all instructions have finished to group completed", ··· 2916 3420 "PublicDescription": "" 2917 3421 }, 2918 3422 {, 2919 - "EventCode": "0x34808e", 2920 - "EventName": "PM_RD_CLEARING_SC", 2921 - "BriefDescription": "rd clearing sc", 2922 - "PublicDescription": "" 2923 - }, 2924 - {, 2925 - "EventCode": "0x34808c", 2926 - "EventName": "PM_RD_FORMING_SC", 2927 - "BriefDescription": "rd forming sc", 2928 - "PublicDescription": "" 2929 - }, 2930 - {, 2931 - "EventCode": "0x428086", 2932 - "EventName": "PM_RD_HIT_PF", 2933 - "BriefDescription": "rd machine hit l3 pf machine", 2934 - "PublicDescription": "" 2935 - }, 2936 - {, 2937 3423 "EventCode": "0x20004", 2938 3424 "EventName": "PM_REAL_SRQ_FULL", 2939 3425 "BriefDescription": "Out of real srq entries", ··· 2982 3504 "PublicDescription": "TLBIE snoopSnoop TLBIE" 2983 3505 }, 2984 3506 {, 2985 - "EventCode": "0x338088", 2986 - "EventName": "PM_SNP_TM_HIT_M", 2987 - "BriefDescription": "snp tm st hit m mu", 2988 - "PublicDescription": "" 2989 - }, 2990 - {, 2991 - "EventCode": "0x33808a", 2992 - "EventName": "PM_SNP_TM_HIT_T", 2993 - "BriefDescription": "snp tm_st_hit t tn te", 2994 - "PublicDescription": "" 2995 - }, 2996 - {, 2997 3507 "EventCode": "0x4608c", 2998 3508 "EventName": "PM_SN_USAGE", 2999 3509 "BriefDescription": "Continuous 16 cycle(2to1) window where this signals rotates thru sampling each L2 SN machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running", ··· 2998 3532 "EventName": "PM_STCX_LSU", 2999 3533 "BriefDescription": "STCX executed reported at sent to nest", 3000 3534 "PublicDescription": "STCX executed reported at sent to nest42" 3001 - }, 3002 - {, 3003 - "EventCode": "0x717080", 3004 - "EventName": "PM_ST_CAUSED_FAIL", 3005 - "BriefDescription": "Non TM St caused any thread to fail", 3006 - "PublicDescription": "" 3007 3535 }, 3008 3536 {, 3009 3537 "EventCode": "0x3090", ··· 3084 3624 "PublicDescription": "" 3085 3625 }, 3086 3626 {, 3087 - "EventCode": "0x318082", 3088 - "EventName": "PM_TM_CAM_OVERFLOW", 3089 - "BriefDescription": "l3 tm cam overflow during L2 co of SC", 3090 - "PublicDescription": "" 3091 - }, 3092 - {, 3093 - "EventCode": "0x74708c", 3094 - "EventName": "PM_TM_CAP_OVERFLOW", 3095 - "BriefDescription": "TM Footprint Capactiy Overflow", 3096 - "PublicDescription": "" 3097 - }, 3098 - {, 3099 3627 "EventCode": "0x20ba", 3100 3628 "EventName": "PM_TM_END_ALL", 3101 3629 "BriefDescription": "Tm any tend", ··· 3136 3688 "EventName": "PM_TM_FAIL_TX_CONFLICT", 3137 3689 "BriefDescription": "Transactional conflict from LSU, whatever gets reported to texas", 3138 3690 "PublicDescription": "Transactional conflict from LSU, whatever gets reported to texas 42" 3139 - }, 3140 - {, 3141 - "EventCode": "0x727086", 3142 - "EventName": "PM_TM_FAV_CAUSED_FAIL", 3143 - "BriefDescription": "TM Load (fav) caused another thread to fail", 3144 - "PublicDescription": "" 3145 - }, 3146 - {, 3147 - "EventCode": "0x717082", 3148 - "EventName": "PM_TM_LD_CAUSED_FAIL", 3149 - "BriefDescription": "Non TM Ld caused any thread to fail", 3150 - "PublicDescription": "" 3151 - }, 3152 - {, 3153 - "EventCode": "0x727084", 3154 - "EventName": "PM_TM_LD_CONF", 3155 - "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)", 3156 - "PublicDescription": "" 3157 - }, 3158 - {, 3159 - "EventCode": "0x328086", 3160 - "EventName": "PM_TM_RST_SC", 3161 - "BriefDescription": "tm snp rst tm sc", 3162 - "PublicDescription": "" 3163 - }, 3164 - {, 3165 - "EventCode": "0x318080", 3166 - "EventName": "PM_TM_SC_CO", 3167 - "BriefDescription": "l3 castout tm Sc line", 3168 - "PublicDescription": "" 3169 - }, 3170 - {, 3171 - "EventCode": "0x73708a", 3172 - "EventName": "PM_TM_ST_CAUSED_FAIL", 3173 - "BriefDescription": "TM Store (fav or non-fav) caused another thread to fail", 3174 - "PublicDescription": "" 3175 - }, 3176 - {, 3177 - "EventCode": "0x737088", 3178 - "EventName": "PM_TM_ST_CONF", 3179 - "BriefDescription": "TM Store (fav or non-fav) ran into conflict (failed)", 3180 - "PublicDescription": "" 3181 3691 }, 3182 3692 {, 3183 3693 "EventCode": "0x20bc",
+12
tools/perf/pmu-events/arch/x86/amdfam17h/branch.json
··· 1 + [ 2 + { 3 + "EventName": "bp_l1_btb_correct", 4 + "EventCode": "0x8a", 5 + "BriefDescription": "L1 BTB Correction." 6 + }, 7 + { 8 + "EventName": "bp_l2_btb_correct", 9 + "EventCode": "0x8b", 10 + "BriefDescription": "L2 BTB Correction." 11 + } 12 + ]
+287
tools/perf/pmu-events/arch/x86/amdfam17h/cache.json
··· 1 + [ 2 + { 3 + "EventName": "ic_fw32", 4 + "EventCode": "0x80", 5 + "BriefDescription": "The number of 32B fetch windows transferred from IC pipe to DE instruction decoder (includes non-cacheable and cacheable fill responses)." 6 + }, 7 + { 8 + "EventName": "ic_fw32_miss", 9 + "EventCode": "0x81", 10 + "BriefDescription": "The number of 32B fetch windows tried to read the L1 IC and missed in the full tag." 11 + }, 12 + { 13 + "EventName": "ic_cache_fill_l2", 14 + "EventCode": "0x82", 15 + "BriefDescription": "The number of 64 byte instruction cache line was fulfilled from the L2 cache." 16 + }, 17 + { 18 + "EventName": "ic_cache_fill_sys", 19 + "EventCode": "0x83", 20 + "BriefDescription": "The number of 64 byte instruction cache line fulfilled from system memory or another cache." 21 + }, 22 + { 23 + "EventName": "bp_l1_tlb_miss_l2_hit", 24 + "EventCode": "0x84", 25 + "BriefDescription": "The number of instruction fetches that miss in the L1 ITLB but hit in the L2 ITLB." 26 + }, 27 + { 28 + "EventName": "bp_l1_tlb_miss_l2_miss", 29 + "EventCode": "0x85", 30 + "BriefDescription": "The number of instruction fetches that miss in both the L1 and L2 TLBs." 31 + }, 32 + { 33 + "EventName": "bp_snp_re_sync", 34 + "EventCode": "0x86", 35 + "BriefDescription": "The number of pipeline restarts caused by invalidating probes that hit on the instruction stream currently being executed. This would happen if the active instruction stream was being modified by another processor in an MP system - typically a highly unlikely event." 36 + }, 37 + { 38 + "EventName": "ic_fetch_stall.ic_stall_any", 39 + "EventCode": "0x87", 40 + "BriefDescription": "IC pipe was stalled during this clock cycle for any reason (nothing valid in pipe ICM1).", 41 + "PublicDescription": "Instruction Pipe Stall. IC pipe was stalled during this clock cycle for any reason (nothing valid in pipe ICM1).", 42 + "UMask": "0x4" 43 + }, 44 + { 45 + "EventName": "ic_fetch_stall.ic_stall_dq_empty", 46 + "EventCode": "0x87", 47 + "BriefDescription": "IC pipe was stalled during this clock cycle (including IC to OC fetches) due to DQ empty.", 48 + "PublicDescription": "Instruction Pipe Stall. IC pipe was stalled during this clock cycle (including IC to OC fetches) due to DQ empty.", 49 + "UMask": "0x2" 50 + }, 51 + { 52 + "EventName": "ic_fetch_stall.ic_stall_back_pressure", 53 + "EventCode": "0x87", 54 + "BriefDescription": "IC pipe was stalled during this clock cycle (including IC to OC fetches) due to back-pressure.", 55 + "PublicDescription": "Instruction Pipe Stall. IC pipe was stalled during this clock cycle (including IC to OC fetches) due to back-pressure.", 56 + "UMask": "0x1" 57 + }, 58 + { 59 + "EventName": "ic_cache_inval.l2_invalidating_probe", 60 + "EventCode": "0x8c", 61 + "BriefDescription": "IC line invalidated due to L2 invalidating probe (external or LS).", 62 + "PublicDescription": "The number of instruction cache lines invalidated. A non-SMC event is CMC (cross modifying code), either from the other thread of the core or another core. IC line invalidated due to L2 invalidating probe (external or LS).", 63 + "UMask": "0x2" 64 + }, 65 + { 66 + "EventName": "ic_cache_inval.fill_invalidated", 67 + "EventCode": "0x8c", 68 + "BriefDescription": "IC line invalidated due to overwriting fill response.", 69 + "PublicDescription": "The number of instruction cache lines invalidated. A non-SMC event is CMC (cross modifying code), either from the other thread of the core or another core. IC line invalidated due to overwriting fill response.", 70 + "UMask": "0x1" 71 + }, 72 + { 73 + "EventName": "bp_tlb_rel", 74 + "EventCode": "0x99", 75 + "BriefDescription": "The number of ITLB reload requests." 76 + }, 77 + { 78 + "EventName": "l2_request_g1.rd_blk_l", 79 + "EventCode": "0x60", 80 + "BriefDescription": "Requests to L2 Group1.", 81 + "PublicDescription": "Requests to L2 Group1.", 82 + "UMask": "0x80" 83 + }, 84 + { 85 + "EventName": "l2_request_g1.rd_blk_x", 86 + "EventCode": "0x60", 87 + "BriefDescription": "Requests to L2 Group1.", 88 + "PublicDescription": "Requests to L2 Group1.", 89 + "UMask": "0x40" 90 + }, 91 + { 92 + "EventName": "l2_request_g1.ls_rd_blk_c_s", 93 + "EventCode": "0x60", 94 + "BriefDescription": "Requests to L2 Group1.", 95 + "PublicDescription": "Requests to L2 Group1.", 96 + "UMask": "0x20" 97 + }, 98 + { 99 + "EventName": "l2_request_g1.cacheable_ic_read", 100 + "EventCode": "0x60", 101 + "BriefDescription": "Requests to L2 Group1.", 102 + "PublicDescription": "Requests to L2 Group1.", 103 + "UMask": "0x10" 104 + }, 105 + { 106 + "EventName": "l2_request_g1.change_to_x", 107 + "EventCode": "0x60", 108 + "BriefDescription": "Requests to L2 Group1.", 109 + "PublicDescription": "Requests to L2 Group1.", 110 + "UMask": "0x8" 111 + }, 112 + { 113 + "EventName": "l2_request_g1.prefetch_l2", 114 + "EventCode": "0x60", 115 + "BriefDescription": "Requests to L2 Group1.", 116 + "PublicDescription": "Requests to L2 Group1.", 117 + "UMask": "0x4" 118 + }, 119 + { 120 + "EventName": "l2_request_g1.l2_hw_pf", 121 + "EventCode": "0x60", 122 + "BriefDescription": "Requests to L2 Group1.", 123 + "PublicDescription": "Requests to L2 Group1.", 124 + "UMask": "0x2" 125 + }, 126 + { 127 + "EventName": "l2_request_g1.other_requests", 128 + "EventCode": "0x60", 129 + "BriefDescription": "Events covered by l2_request_g2.", 130 + "PublicDescription": "Requests to L2 Group1. Events covered by l2_request_g2.", 131 + "UMask": "0x1" 132 + }, 133 + { 134 + "EventName": "l2_request_g2.group1", 135 + "EventCode": "0x61", 136 + "BriefDescription": "All Group 1 commands not in unit0.", 137 + "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous. All Group 1 commands not in unit0.", 138 + "UMask": "0x80" 139 + }, 140 + { 141 + "EventName": "l2_request_g2.ls_rd_sized", 142 + "EventCode": "0x61", 143 + "BriefDescription": "RdSized, RdSized32, RdSized64.", 144 + "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous. RdSized, RdSized32, RdSized64.", 145 + "UMask": "0x40" 146 + }, 147 + { 148 + "EventName": "l2_request_g2.ls_rd_sized_nc", 149 + "EventCode": "0x61", 150 + "BriefDescription": "RdSizedNC, RdSized32NC, RdSized64NC.", 151 + "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous. RdSizedNC, RdSized32NC, RdSized64NC.", 152 + "UMask": "0x20" 153 + }, 154 + { 155 + "EventName": "l2_request_g2.ic_rd_sized", 156 + "EventCode": "0x61", 157 + "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 158 + "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 159 + "UMask": "0x10" 160 + }, 161 + { 162 + "EventName": "l2_request_g2.ic_rd_sized_nc", 163 + "EventCode": "0x61", 164 + "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 165 + "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 166 + "UMask": "0x8" 167 + }, 168 + { 169 + "EventName": "l2_request_g2.smc_inval", 170 + "EventCode": "0x61", 171 + "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 172 + "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 173 + "UMask": "0x4" 174 + }, 175 + { 176 + "EventName": "l2_request_g2.bus_locks_originator", 177 + "EventCode": "0x61", 178 + "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 179 + "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 180 + "UMask": "0x2" 181 + }, 182 + { 183 + "EventName": "l2_request_g2.bus_locks_responses", 184 + "EventCode": "0x61", 185 + "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 186 + "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.", 187 + "UMask": "0x1" 188 + }, 189 + { 190 + "EventName": "l2_latency.l2_cycles_waiting_on_fills", 191 + "EventCode": "0x62", 192 + "BriefDescription": "Total cycles spent waiting for L2 fills to complete from L3 or memory, divided by four. Event counts are for both threads. To calculate average latency, the number of fills from both threads must be used.", 193 + "PublicDescription": "Total cycles spent waiting for L2 fills to complete from L3 or memory, divided by four. Event counts are for both threads. To calculate average latency, the number of fills from both threads must be used.", 194 + "UMask": "0x1" 195 + }, 196 + { 197 + "EventName": "l2_wcb_req.wcb_write", 198 + "EventCode": "0x63", 199 + "PublicDescription": "LS (Load/Store unit) to L2 WCB (Write Combining Buffer) write requests.", 200 + "BriefDescription": "LS to L2 WCB write requests.", 201 + "UMask": "0x40" 202 + }, 203 + { 204 + "EventName": "l2_wcb_req.wcb_close", 205 + "EventCode": "0x63", 206 + "BriefDescription": "LS to L2 WCB close requests.", 207 + "PublicDescription": "LS (Load/Store unit) to L2 WCB (Write Combining Buffer) close requests.", 208 + "UMask": "0x20" 209 + }, 210 + { 211 + "EventName": "l2_wcb_req.zero_byte_store", 212 + "EventCode": "0x63", 213 + "BriefDescription": "LS to L2 WCB zero byte store requests.", 214 + "PublicDescription": "LS (Load/Store unit) to L2 WCB (Write Combining Buffer) zero byte store requests.", 215 + "UMask": "0x4" 216 + }, 217 + { 218 + "EventName": "l2_wcb_req.cl_zero", 219 + "EventCode": "0x63", 220 + "PublicDescription": "LS to L2 WCB cache line zeroing requests.", 221 + "BriefDescription": "LS (Load/Store unit) to L2 WCB (Write Combining Buffer) cache line zeroing requests.", 222 + "UMask": "0x1" 223 + }, 224 + { 225 + "EventName": "l2_cache_req_stat.ls_rd_blk_cs", 226 + "EventCode": "0x64", 227 + "BriefDescription": "LS ReadBlock C/S Hit.", 228 + "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LS ReadBlock C/S Hit.", 229 + "UMask": "0x80" 230 + }, 231 + { 232 + "EventName": "l2_cache_req_stat.ls_rd_blk_l_hit_x", 233 + "EventCode": "0x64", 234 + "BriefDescription": "LS Read Block L Hit X.", 235 + "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LS Read Block L Hit X.", 236 + "UMask": "0x40" 237 + }, 238 + { 239 + "EventName": "l2_cache_req_stat.ls_rd_blk_l_hit_s", 240 + "EventCode": "0x64", 241 + "BriefDescription": "LsRdBlkL Hit Shared.", 242 + "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LsRdBlkL Hit Shared.", 243 + "UMask": "0x20" 244 + }, 245 + { 246 + "EventName": "l2_cache_req_stat.ls_rd_blk_x", 247 + "EventCode": "0x64", 248 + "BriefDescription": "LsRdBlkX/ChgToX Hit X. Count RdBlkX finding Shared as a Miss.", 249 + "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LsRdBlkX/ChgToX Hit X. Count RdBlkX finding Shared as a Miss.", 250 + "UMask": "0x10" 251 + }, 252 + { 253 + "EventName": "l2_cache_req_stat.ls_rd_blk_c", 254 + "EventCode": "0x64", 255 + "BriefDescription": "LS Read Block C S L X Change to X Miss.", 256 + "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LS Read Block C S L X Change to X Miss.", 257 + "UMask": "0x8" 258 + }, 259 + { 260 + "EventName": "l2_cache_req_stat.ic_fill_hit_x", 261 + "EventCode": "0x64", 262 + "BriefDescription": "IC Fill Hit Exclusive Stale.", 263 + "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. IC Fill Hit Exclusive Stale.", 264 + "UMask": "0x4" 265 + }, 266 + { 267 + "EventName": "l2_cache_req_stat.ic_fill_hit_s", 268 + "EventCode": "0x64", 269 + "BriefDescription": "IC Fill Hit Shared.", 270 + "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. IC Fill Hit Shared.", 271 + "UMask": "0x2" 272 + }, 273 + { 274 + "EventName": "l2_cache_req_stat.ic_fill_miss", 275 + "EventCode": "0x64", 276 + "BriefDescription": "IC Fill Miss.", 277 + "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. IC Fill Miss.", 278 + "UMask": "0x1" 279 + }, 280 + { 281 + "EventName": "l2_fill_pending.l2_fill_busy", 282 + "EventCode": "0x6d", 283 + "BriefDescription": "Total cycles spent with one or more fill requests in flight from L2.", 284 + "PublicDescription": "Total cycles spent with one or more fill requests in flight from L2.", 285 + "UMask": "0x1" 286 + } 287 + ]
+134
tools/perf/pmu-events/arch/x86/amdfam17h/core.json
··· 1 + [ 2 + { 3 + "EventName": "ex_ret_instr", 4 + "EventCode": "0xc0", 5 + "BriefDescription": "Retired Instructions." 6 + }, 7 + { 8 + "EventName": "ex_ret_cops", 9 + "EventCode": "0xc1", 10 + "BriefDescription": "Retired Uops.", 11 + "PublicDescription": "The number of uOps retired. This includes all processor activity (instructions, exceptions, interrupts, microcode assists, etc.). The number of events logged per cycle can vary from 0 to 4." 12 + }, 13 + { 14 + "EventName": "ex_ret_brn", 15 + "EventCode": "0xc2", 16 + "BriefDescription": "[Retired Branch Instructions.", 17 + "PublicDescription": "The number of branch instructions retired. This includes all types of architectural control flow changes, including exceptions and interrupts." 18 + }, 19 + { 20 + "EventName": "ex_ret_brn_misp", 21 + "EventCode": "0xc3", 22 + "BriefDescription": "Retired Branch Instructions Mispredicted.", 23 + "PublicDescription": "The number of branch instructions retired, of any type, that were not correctly predicted. This includes those for which prediction is not attempted (far control transfers, exceptions and interrupts)." 24 + }, 25 + { 26 + "EventName": "ex_ret_brn_tkn", 27 + "EventCode": "0xc4", 28 + "BriefDescription": "Retired Taken Branch Instructions.", 29 + "PublicDescription": "The number of taken branches that were retired. This includes all types of architectural control flow changes, including exceptions and interrupts." 30 + }, 31 + { 32 + "EventName": "ex_ret_brn_tkn_misp", 33 + "EventCode": "0xc5", 34 + "BriefDescription": "Retired Taken Branch Instructions Mispredicted.", 35 + "PublicDescription": "The number of retired taken branch instructions that were mispredicted." 36 + }, 37 + { 38 + "EventName": "ex_ret_brn_far", 39 + "EventCode": "0xc6", 40 + "BriefDescription": "Retired Far Control Transfers.", 41 + "PublicDescription": "The number of far control transfers retired including far call/jump/return, IRET, SYSCALL and SYSRET, plus exceptions and interrupts. Far control transfers are not subject to branch prediction." 42 + }, 43 + { 44 + "EventName": "ex_ret_brn_resync", 45 + "EventCode": "0xc7", 46 + "BriefDescription": "Retired Branch Resyncs.", 47 + "PublicDescription": "The number of resync branches. These reflect pipeline restarts due to certain microcode assists and events such as writes to the active instruction stream, among other things. Each occurrence reflects a restart penalty similar to a branch mispredict. This is relatively rare." 48 + }, 49 + { 50 + "EventName": "ex_ret_near_ret", 51 + "EventCode": "0xc8", 52 + "BriefDescription": "Retired Near Returns.", 53 + "PublicDescription": "The number of near return instructions (RET or RET Iw) retired." 54 + }, 55 + { 56 + "EventName": "ex_ret_near_ret_mispred", 57 + "EventCode": "0xc9", 58 + "BriefDescription": "Retired Near Returns Mispredicted.", 59 + "PublicDescription": "The number of near returns retired that were not correctly predicted by the return address predictor. Each such mispredict incurs the same penalty as a mispredicted conditional branch instruction." 60 + }, 61 + { 62 + "EventName": "ex_ret_brn_ind_misp", 63 + "EventCode": "0xca", 64 + "BriefDescription": "Retired Indirect Branch Instructions Mispredicted.", 65 + "PublicDescription": "Retired Indirect Branch Instructions Mispredicted." 66 + }, 67 + { 68 + "EventName": "ex_ret_mmx_fp_instr.sse_instr", 69 + "EventCode": "0xcb", 70 + "BriefDescription": "SSE instructions (SSE, SSE2, SSE3, SSSE3, SSE4A, SSE41, SSE42, AVX).", 71 + "PublicDescription": "The number of MMX, SSE or x87 instructions retired. The UnitMask allows the selection of the individual classes of instructions as given in the table. Each increment represents one complete instruction. Since this event includes non-numeric instructions it is not suitable for measuring MFLOPS. SSE instructions (SSE, SSE2, SSE3, SSSE3, SSE4A, SSE41, SSE42, AVX).", 72 + "UMask": "0x4" 73 + }, 74 + { 75 + "EventName": "ex_ret_mmx_fp_instr.mmx_instr", 76 + "EventCode": "0xcb", 77 + "BriefDescription": "MMX instructions.", 78 + "PublicDescription": "The number of MMX, SSE or x87 instructions retired. The UnitMask allows the selection of the individual classes of instructions as given in the table. Each increment represents one complete instruction. Since this event includes non-numeric instructions it is not suitable for measuring MFLOPS. MMX instructions.", 79 + "UMask": "0x2" 80 + }, 81 + { 82 + "EventName": "ex_ret_mmx_fp_instr.x87_instr", 83 + "EventCode": "0xcb", 84 + "BriefDescription": "x87 instructions.", 85 + "PublicDescription": "The number of MMX, SSE or x87 instructions retired. The UnitMask allows the selection of the individual classes of instructions as given in the table. Each increment represents one complete instruction. Since this event includes non-numeric instructions it is not suitable for measuring MFLOPS. x87 instructions.", 86 + "UMask": "0x1" 87 + }, 88 + { 89 + "EventName": "ex_ret_cond", 90 + "EventCode": "0xd1", 91 + "BriefDescription": "Retired Conditional Branch Instructions." 92 + }, 93 + { 94 + "EventName": "ex_ret_cond_misp", 95 + "EventCode": "0xd2", 96 + "BriefDescription": "Retired Conditional Branch Instructions Mispredicted." 97 + }, 98 + { 99 + "EventName": "ex_div_busy", 100 + "EventCode": "0xd3", 101 + "BriefDescription": "Div Cycles Busy count." 102 + }, 103 + { 104 + "EventName": "ex_div_count", 105 + "EventCode": "0xd4", 106 + "BriefDescription": "Div Op Count." 107 + }, 108 + { 109 + "EventName": "ex_tagged_ibs_ops.ibs_count_rollover", 110 + "EventCode": "0x1cf", 111 + "BriefDescription": "Number of times an op could not be tagged by IBS because of a previous tagged op that has not retired.", 112 + "PublicDescription": "Tagged IBS Ops. Number of times an op could not be tagged by IBS because of a previous tagged op that has not retired.", 113 + "UMask": "0x4" 114 + }, 115 + { 116 + "EventName": "ex_tagged_ibs_ops.ibs_tagged_ops_ret", 117 + "EventCode": "0x1cf", 118 + "BriefDescription": "Number of Ops tagged by IBS that retired.", 119 + "PublicDescription": "Tagged IBS Ops. Number of Ops tagged by IBS that retired.", 120 + "UMask": "0x2" 121 + }, 122 + { 123 + "EventName": "ex_tagged_ibs_ops.ibs_tagged_ops", 124 + "EventCode": "0x1cf", 125 + "BriefDescription": "Number of Ops tagged by IBS.", 126 + "PublicDescription": "Tagged IBS Ops. Number of Ops tagged by IBS.", 127 + "UMask": "0x1" 128 + }, 129 + { 130 + "EventName": "ex_ret_fus_brnch_inst", 131 + "EventCode": "0x1d0", 132 + "BriefDescription": "The number of fused retired branch instructions retired per cycle. The number of events logged per cycle can vary from 0 to 3." 133 + } 134 + ]
+168
tools/perf/pmu-events/arch/x86/amdfam17h/floating-point.json
··· 1 + [ 2 + { 3 + "EventName": "fpu_pipe_assignment.dual", 4 + "EventCode": "0x00", 5 + "BriefDescription": "Total number multi-pipe uOps.", 6 + "PublicDescription": "The number of operations (uOps) and dual-pipe uOps dispatched to each of the 4 FPU execution pipelines. This event reflects how busy the FPU pipelines are and may be used for workload characterization. This includes all operations performed by x87, MMX, and SSE instructions, including moves. Each increment represents a one- cycle dispatch event. This event is a speculative event. Since this event includes non-numeric operations it is not suitable for measuring MFLOPS. Total number multi-pipe uOps assigned to Pipe 3.", 7 + "UMask": "0xf0" 8 + }, 9 + { 10 + "EventName": "fpu_pipe_assignment.total", 11 + "EventCode": "0x00", 12 + "BriefDescription": "Total number uOps.", 13 + "PublicDescription": "The number of operations (uOps) and dual-pipe uOps dispatched to each of the 4 FPU execution pipelines. This event reflects how busy the FPU pipelines are and may be used for workload characterization. This includes all operations performed by x87, MMX, and SSE instructions, including moves. Each increment represents a one- cycle dispatch event. This event is a speculative event. Since this event includes non-numeric operations it is not suitable for measuring MFLOPS. Total number uOps assigned to Pipe 3.", 14 + "UMask": "0xf" 15 + }, 16 + { 17 + "EventName": "fp_sched_empty", 18 + "EventCode": "0x01", 19 + "BriefDescription": "This is a speculative event. The number of cycles in which the FPU scheduler is empty. Note that some Ops like FP loads bypass the scheduler." 20 + }, 21 + { 22 + "EventName": "fp_retx87_fp_ops.all", 23 + "EventCode": "0x02", 24 + "BriefDescription": "All Ops.", 25 + "PublicDescription": "The number of x87 floating-point Ops that have retired. The number of events logged per cycle can vary from 0 to 8.", 26 + "UMask": "0x7" 27 + }, 28 + { 29 + "EventName": "fp_retx87_fp_ops.div_sqr_r_ops", 30 + "EventCode": "0x02", 31 + "BriefDescription": "Divide and square root Ops.", 32 + "PublicDescription": "The number of x87 floating-point Ops that have retired. The number of events logged per cycle can vary from 0 to 8. Divide and square root Ops.", 33 + "UMask": "0x4" 34 + }, 35 + { 36 + "EventName": "fp_retx87_fp_ops.mul_ops", 37 + "EventCode": "0x02", 38 + "BriefDescription": "Multiply Ops.", 39 + "PublicDescription": "The number of x87 floating-point Ops that have retired. The number of events logged per cycle can vary from 0 to 8. Multiply Ops.", 40 + "UMask": "0x2" 41 + }, 42 + { 43 + "EventName": "fp_retx87_fp_ops.add_sub_ops", 44 + "EventCode": "0x02", 45 + "BriefDescription": "Add/subtract Ops.", 46 + "PublicDescription": "The number of x87 floating-point Ops that have retired. The number of events logged per cycle can vary from 0 to 8. Add/subtract Ops.", 47 + "UMask": "0x1" 48 + }, 49 + { 50 + "EventName": "fp_ret_sse_avx_ops.all", 51 + "EventCode": "0x03", 52 + "BriefDescription": "All FLOPS.", 53 + "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15.", 54 + "UMask": "0xff" 55 + }, 56 + { 57 + "EventName": "fp_ret_sse_avx_ops.dp_mult_add_flops", 58 + "EventCode": "0x03", 59 + "BriefDescription": "Double precision multiply-add FLOPS. Multiply-add counts as 2 FLOPS.", 60 + "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Double precision multiply-add FLOPS. Multiply-add counts as 2 FLOPS.", 61 + "UMask": "0x80" 62 + }, 63 + { 64 + "EventName": "fp_ret_sse_avx_ops.dp_div_flops", 65 + "EventCode": "0x03", 66 + "BriefDescription": "Double precision divide/square root FLOPS.", 67 + "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Double precision divide/square root FLOPS.", 68 + "UMask": "0x40" 69 + }, 70 + { 71 + "EventName": "fp_ret_sse_avx_ops.dp_mult_flops", 72 + "EventCode": "0x03", 73 + "BriefDescription": "Double precision multiply FLOPS.", 74 + "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Double precision multiply FLOPS.", 75 + "UMask": "0x20" 76 + }, 77 + { 78 + "EventName": "fp_ret_sse_avx_ops.dp_add_sub_flops", 79 + "EventCode": "0x03", 80 + "BriefDescription": "Double precision add/subtract FLOPS.", 81 + "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Double precision add/subtract FLOPS.", 82 + "UMask": "0x10" 83 + }, 84 + { 85 + "EventName": "fp_ret_sse_avx_ops.sp_mult_add_flops", 86 + "EventCode": "0x03", 87 + "BriefDescription": "Single precision multiply-add FLOPS. Multiply-add counts as 2 FLOPS.", 88 + "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Single precision multiply-add FLOPS. Multiply-add counts as 2 FLOPS.", 89 + "UMask": "0x8" 90 + }, 91 + { 92 + "EventName": "fp_ret_sse_avx_ops.sp_div_flops", 93 + "EventCode": "0x03", 94 + "BriefDescription": "Single-precision divide/square root FLOPS.", 95 + "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Single-precision divide/square root FLOPS.", 96 + "UMask": "0x4" 97 + }, 98 + { 99 + "EventName": "fp_ret_sse_avx_ops.sp_mult_flops", 100 + "EventCode": "0x03", 101 + "BriefDescription": "Single-precision multiply FLOPS.", 102 + "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Single-precision multiply FLOPS.", 103 + "UMask": "0x2" 104 + }, 105 + { 106 + "EventName": "fp_ret_sse_avx_ops.sp_add_sub_flops", 107 + "EventCode": "0x03", 108 + "BriefDescription": "Single-precision add/subtract FLOPS.", 109 + "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Single-precision add/subtract FLOPS.", 110 + "UMask": "0x1" 111 + }, 112 + { 113 + "EventName": "fp_num_mov_elim_scal_op.optimized", 114 + "EventCode": "0x04", 115 + "BriefDescription": "Number of Scalar Ops optimized.", 116 + "PublicDescription": "This is a dispatch based speculative event, and is useful for measuring the effectiveness of the Move elimination and Scalar code optimization schemes. Number of Scalar Ops optimized.", 117 + "UMask": "0x8" 118 + }, 119 + { 120 + "EventName": "fp_num_mov_elim_scal_op.opt_potential", 121 + "EventCode": "0x04", 122 + "BriefDescription": "Number of Ops that are candidates for optimization (have Z-bit either set or pass).", 123 + "PublicDescription": "This is a dispatch based speculative event, and is useful for measuring the effectiveness of the Move elimination and Scalar code optimization schemes. Number of Ops that are candidates for optimization (have Z-bit either set or pass).", 124 + "UMask": "0x4" 125 + }, 126 + { 127 + "EventName": "fp_num_mov_elim_scal_op.sse_mov_ops_elim", 128 + "EventCode": "0x04", 129 + "BriefDescription": "Number of SSE Move Ops eliminated.", 130 + "PublicDescription": "This is a dispatch based speculative event, and is useful for measuring the effectiveness of the Move elimination and Scalar code optimization schemes. Number of SSE Move Ops eliminated.", 131 + "UMask": "0x2" 132 + }, 133 + { 134 + "EventName": "fp_num_mov_elim_scal_op.sse_mov_ops", 135 + "EventCode": "0x04", 136 + "BriefDescription": "Number of SSE Move Ops.", 137 + "PublicDescription": "This is a dispatch based speculative event, and is useful for measuring the effectiveness of the Move elimination and Scalar code optimization schemes. Number of SSE Move Ops.", 138 + "UMask": "0x1" 139 + }, 140 + { 141 + "EventName": "fp_retired_ser_ops.x87_ctrl_ret", 142 + "EventCode": "0x05", 143 + "BriefDescription": "x87 control word mispredict traps due to mispredictions in RC or PC, or changes in mask bits.", 144 + "PublicDescription": "The number of serializing Ops retired. x87 control word mispredict traps due to mispredictions in RC or PC, or changes in mask bits.", 145 + "UMask": "0x8" 146 + }, 147 + { 148 + "EventName": "fp_retired_ser_ops.x87_bot_ret", 149 + "EventCode": "0x05", 150 + "BriefDescription": "x87 bottom-executing uOps retired.", 151 + "PublicDescription": "The number of serializing Ops retired. x87 bottom-executing uOps retired.", 152 + "UMask": "0x4" 153 + }, 154 + { 155 + "EventName": "fp_retired_ser_ops.sse_ctrl_ret", 156 + "EventCode": "0x05", 157 + "BriefDescription": "SSE control word mispredict traps due to mispredictions in RC, FTZ or DAZ, or changes in mask bits.", 158 + "PublicDescription": "The number of serializing Ops retired. SSE control word mispredict traps due to mispredictions in RC, FTZ or DAZ, or changes in mask bits.", 159 + "UMask": "0x2" 160 + }, 161 + { 162 + "EventName": "fp_retired_ser_ops.sse_bot_ret", 163 + "EventCode": "0x05", 164 + "BriefDescription": "SSE bottom-executing uOps retired.", 165 + "PublicDescription": "The number of serializing Ops retired. SSE bottom-executing uOps retired.", 166 + "UMask": "0x1" 167 + } 168 + ]
+162
tools/perf/pmu-events/arch/x86/amdfam17h/memory.json
··· 1 + [ 2 + { 3 + "EventName": "ls_locks.bus_lock", 4 + "EventCode": "0x25", 5 + "BriefDescription": "Bus lock when a locked operations crosses a cache boundary or is done on an uncacheable memory type.", 6 + "PublicDescription": "Bus lock when a locked operations crosses a cache boundary or is done on an uncacheable memory type.", 7 + "UMask": "0x1" 8 + }, 9 + { 10 + "EventName": "ls_dispatch.ld_st_dispatch", 11 + "EventCode": "0x29", 12 + "BriefDescription": "Load-op-Stores.", 13 + "PublicDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed. Load-op-Stores.", 14 + "UMask": "0x4" 15 + }, 16 + { 17 + "EventName": "ls_dispatch.store_dispatch", 18 + "EventCode": "0x29", 19 + "BriefDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed.", 20 + "PublicDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed.", 21 + "UMask": "0x2" 22 + }, 23 + { 24 + "EventName": "ls_dispatch.ld_dispatch", 25 + "EventCode": "0x29", 26 + "BriefDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed.", 27 + "PublicDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed.", 28 + "UMask": "0x1" 29 + }, 30 + { 31 + "EventName": "ls_stlf", 32 + "EventCode": "0x35", 33 + "BriefDescription": "Number of STLF hits." 34 + }, 35 + { 36 + "EventName": "ls_dc_accesses", 37 + "EventCode": "0x40", 38 + "BriefDescription": "The number of accesses to the data cache for load and store references. This may include certain microcode scratchpad accesses, although these are generally rare. Each increment represents an eight-byte access, although the instruction may only be accessing a portion of that. This event is a speculative event." 39 + }, 40 + { 41 + "EventName": "ls_l1_d_tlb_miss.all", 42 + "EventCode": "0x45", 43 + "BriefDescription": "L1 DTLB Miss or Reload off all sizes.", 44 + "PublicDescription": "L1 DTLB Miss or Reload off all sizes.", 45 + "UMask": "0xff" 46 + }, 47 + { 48 + "EventName": "ls_l1_d_tlb_miss.tlb_reload_1g_l2_miss", 49 + "EventCode": "0x45", 50 + "BriefDescription": "L1 DTLB Miss of a page of 1G size.", 51 + "PublicDescription": "L1 DTLB Miss of a page of 1G size.", 52 + "UMask": "0x80" 53 + }, 54 + { 55 + "EventName": "ls_l1_d_tlb_miss.tlb_reload_2m_l2_miss", 56 + "EventCode": "0x45", 57 + "BriefDescription": "L1 DTLB Miss of a page of 2M size.", 58 + "PublicDescription": "L1 DTLB Miss of a page of 2M size.", 59 + "UMask": "0x40" 60 + }, 61 + { 62 + "EventName": "ls_l1_d_tlb_miss.tlb_reload_32k_l2_miss", 63 + "EventCode": "0x45", 64 + "BriefDescription": "L1 DTLB Miss of a page of 32K size.", 65 + "PublicDescription": "L1 DTLB Miss of a page of 32K size.", 66 + "UMask": "0x20" 67 + }, 68 + { 69 + "EventName": "ls_l1_d_tlb_miss.tlb_reload_4k_l2_miss", 70 + "EventCode": "0x45", 71 + "BriefDescription": "L1 DTLB Miss of a page of 4K size.", 72 + "PublicDescription": "L1 DTLB Miss of a page of 4K size.", 73 + "UMask": "0x10" 74 + }, 75 + { 76 + "EventName": "ls_l1_d_tlb_miss.tlb_reload_1g_l2_hit", 77 + "EventCode": "0x45", 78 + "BriefDescription": "L1 DTLB Reload of a page of 1G size.", 79 + "PublicDescription": "L1 DTLB Reload of a page of 1G size.", 80 + "UMask": "0x8" 81 + }, 82 + { 83 + "EventName": "ls_l1_d_tlb_miss.tlb_reload_2m_l2_hit", 84 + "EventCode": "0x45", 85 + "BriefDescription": "L1 DTLB Reload of a page of 2M size.", 86 + "PublicDescription": "L1 DTLB Reload of a page of 2M size.", 87 + "UMask": "0x4" 88 + }, 89 + { 90 + "EventName": "ls_l1_d_tlb_miss.tlb_reload_32k_l2_hit", 91 + "EventCode": "0x45", 92 + "BriefDescription": "L1 DTLB Reload of a page of 32K size.", 93 + "PublicDescription": "L1 DTLB Reload of a page of 32K size.", 94 + "UMask": "0x2" 95 + }, 96 + { 97 + "EventName": "ls_l1_d_tlb_miss.tlb_reload_4k_l2_hit", 98 + "EventCode": "0x45", 99 + "BriefDescription": "L1 DTLB Reload of a page of 4K size.", 100 + "PublicDescription": "L1 DTLB Reload of a page of 4K size.", 101 + "UMask": "0x1" 102 + }, 103 + { 104 + "EventName": "ls_tablewalker.perf_mon_tablewalk_alloc_iside", 105 + "EventCode": "0x46", 106 + "BriefDescription": "Tablewalker allocation.", 107 + "PublicDescription": "Tablewalker allocation.", 108 + "UMask": "0xc" 109 + }, 110 + { 111 + "EventName": "ls_tablewalker.perf_mon_tablewalk_alloc_dside", 112 + "EventCode": "0x46", 113 + "BriefDescription": "Tablewalker allocation.", 114 + "PublicDescription": "Tablewalker allocation.", 115 + "UMask": "0x3" 116 + }, 117 + { 118 + "EventName": "ls_misal_accesses", 119 + "EventCode": "0x47", 120 + "BriefDescription": "Misaligned loads." 121 + }, 122 + { 123 + "EventName": "ls_pref_instr_disp.prefetch_nta", 124 + "EventCode": "0x4b", 125 + "BriefDescription": "Software Prefetch Instructions (PREFETCHNTA instruction) Dispatched.", 126 + "PublicDescription": "Software Prefetch Instructions (PREFETCHNTA instruction) Dispatched.", 127 + "UMask": "0x4" 128 + }, 129 + { 130 + "EventName": "ls_pref_instr_disp.store_prefetch_w", 131 + "EventCode": "0x4b", 132 + "BriefDescription": "Software Prefetch Instructions (3DNow PREFETCHW instruction) Dispatched.", 133 + "PublicDescription": "Software Prefetch Instructions (3DNow PREFETCHW instruction) Dispatched.", 134 + "UMask": "0x2" 135 + }, 136 + { 137 + "EventName": "ls_pref_instr_disp.load_prefetch_w", 138 + "EventCode": "0x4b", 139 + "BriefDescription": "Prefetch, Prefetch_T0_T1_T2.", 140 + "PublicDescription": "Software Prefetch Instructions Dispatched. Prefetch, Prefetch_T0_T1_T2.", 141 + "UMask": "0x1" 142 + }, 143 + { 144 + "EventName": "ls_inef_sw_pref.mab_mch_cnt", 145 + "EventCode": "0x52", 146 + "BriefDescription": "The number of software prefetches that did not fetch data outside of the processor core.", 147 + "PublicDescription": "The number of software prefetches that did not fetch data outside of the processor core.", 148 + "UMask": "0x2" 149 + }, 150 + { 151 + "EventName": "ls_inef_sw_pref.data_pipe_sw_pf_dc_hit", 152 + "EventCode": "0x52", 153 + "BriefDescription": "The number of software prefetches that did not fetch data outside of the processor core.", 154 + "PublicDescription": "The number of software prefetches that did not fetch data outside of the processor core.", 155 + "UMask": "0x1" 156 + }, 157 + { 158 + "EventName": "ls_not_halted_cyc", 159 + "EventCode": "0x76", 160 + "BriefDescription": "Cycles not in Halt." 161 + } 162 + ]
+65
tools/perf/pmu-events/arch/x86/amdfam17h/other.json
··· 1 + [ 2 + { 3 + "EventName": "ic_oc_mode_switch.oc_ic_mode_switch", 4 + "EventCode": "0x28a", 5 + "BriefDescription": "OC to IC mode switch.", 6 + "PublicDescription": "OC Mode Switch. OC to IC mode switch.", 7 + "UMask": "0x2" 8 + }, 9 + { 10 + "EventName": "ic_oc_mode_switch.ic_oc_mode_switch", 11 + "EventCode": "0x28a", 12 + "BriefDescription": "IC to OC mode switch.", 13 + "PublicDescription": "OC Mode Switch. IC to OC mode switch.", 14 + "UMask": "0x1" 15 + }, 16 + { 17 + "EventName": "de_dis_dispatch_token_stalls0.retire_token_stall", 18 + "EventCode": "0xaf", 19 + "BriefDescription": "RETIRE Tokens unavailable.", 20 + "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. RETIRE Tokens unavailable.", 21 + "UMask": "0x40" 22 + }, 23 + { 24 + "EventName": "de_dis_dispatch_token_stalls0.agsq_token_stall", 25 + "EventCode": "0xaf", 26 + "BriefDescription": "AGSQ Tokens unavailable.", 27 + "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. AGSQ Tokens unavailable.", 28 + "UMask": "0x20" 29 + }, 30 + { 31 + "EventName": "de_dis_dispatch_token_stalls0.alu_token_stall", 32 + "EventCode": "0xaf", 33 + "BriefDescription": "ALU tokens total unavailable.", 34 + "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. ALU tokens total unavailable.", 35 + "UMask": "0x10" 36 + }, 37 + { 38 + "EventName": "de_dis_dispatch_token_stalls0.alsq3_0_token_stall", 39 + "EventCode": "0xaf", 40 + "BriefDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall.", 41 + "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall.", 42 + "UMask": "0x8" 43 + }, 44 + { 45 + "EventName": "de_dis_dispatch_token_stalls0.alsq3_token_stall", 46 + "EventCode": "0xaf", 47 + "BriefDescription": "ALSQ 3 Tokens unavailable.", 48 + "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. ALSQ 3 Tokens unavailable.", 49 + "UMask": "0x4" 50 + }, 51 + { 52 + "EventName": "de_dis_dispatch_token_stalls0.alsq2_token_stall", 53 + "EventCode": "0xaf", 54 + "BriefDescription": "ALSQ 2 Tokens unavailable.", 55 + "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. ALSQ 2 Tokens unavailable.", 56 + "UMask": "0x2" 57 + }, 58 + { 59 + "EventName": "de_dis_dispatch_token_stalls0.alsq1_token_stall", 60 + "EventCode": "0xaf", 61 + "BriefDescription": "ALSQ 1 Tokens unavailable.", 62 + "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. ALSQ 1 Tokens unavailable.", 63 + "UMask": "0x1" 64 + } 65 + ]
+1
tools/perf/pmu-events/arch/x86/mapfile.csv
··· 33 33 GenuineIntel-6-2F,v2,westmereex,core 34 34 GenuineIntel-6-55-[01234],v1,skylakex,core 35 35 GenuineIntel-6-55-[56789ABCDEF],v1,cascadelakex,core 36 + AuthenticAMD-23-[[:xdigit:]]+,v1,amdfam17h,core
+44 -17
tools/perf/scripts/python/export-to-postgresql.py
··· 10 10 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 11 # more details. 12 12 13 + from __future__ import print_function 14 + 13 15 import os 14 16 import sys 15 17 import struct ··· 201 199 202 200 from PySide.QtSql import * 203 201 202 + if sys.version_info < (3, 0): 203 + def toserverstr(str): 204 + return str 205 + def toclientstr(str): 206 + return str 207 + else: 208 + # Assume UTF-8 server_encoding and client_encoding 209 + def toserverstr(str): 210 + return bytes(str, "UTF_8") 211 + def toclientstr(str): 212 + return bytes(str, "UTF_8") 213 + 204 214 # Need to access PostgreSQL C library directly to use COPY FROM STDIN 205 215 from ctypes import * 206 216 libpq = CDLL("libpq.so.5") ··· 248 234 perf_db_export_calls = False 249 235 perf_db_export_callchains = False 250 236 237 + def printerr(*args, **kw_args): 238 + print(*args, file=sys.stderr, **kw_args) 239 + 240 + def printdate(*args, **kw_args): 241 + print(datetime.datetime.today(), *args, sep=' ', **kw_args) 251 242 252 243 def usage(): 253 - print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]" 254 - print >> sys.stderr, "where: columns 'all' or 'branches'" 255 - print >> sys.stderr, " calls 'calls' => create calls and call_paths table" 256 - print >> sys.stderr, " callchains 'callchains' => create call_paths table" 244 + printerr("Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]") 245 + printerr("where: columns 'all' or 'branches'") 246 + printerr(" calls 'calls' => create calls and call_paths table") 247 + printerr(" callchains 'callchains' => create call_paths table") 257 248 raise Exception("Too few arguments") 258 249 259 250 if (len(sys.argv) < 2): ··· 292 273 return 293 274 raise Exception("Query failed: " + q.lastError().text()) 294 275 295 - print datetime.datetime.today(), "Creating database..." 276 + printdate("Creating database...") 296 277 297 278 db = QSqlDatabase.addDatabase('QPSQL') 298 279 query = QSqlQuery(db) ··· 525 506 ' FROM samples') 526 507 527 508 528 - file_header = struct.pack("!11sii", "PGCOPY\n\377\r\n\0", 0, 0) 529 - file_trailer = "\377\377" 509 + file_header = struct.pack("!11sii", b"PGCOPY\n\377\r\n\0", 0, 0) 510 + file_trailer = b"\377\377" 530 511 531 512 def open_output_file(file_name): 532 513 path_name = output_dir_name + "/" + file_name 533 - file = open(path_name, "w+") 514 + file = open(path_name, "wb+") 534 515 file.write(file_header) 535 516 return file 536 517 ··· 545 526 546 527 # Use COPY FROM STDIN because security may prevent postgres from accessing the files directly 547 528 def copy_output_file(file, table_name): 548 - conn = PQconnectdb("dbname = " + dbname) 529 + conn = PQconnectdb(toclientstr("dbname = " + dbname)) 549 530 if (PQstatus(conn)): 550 531 raise Exception("COPY FROM STDIN PQconnectdb failed") 551 532 file.write(file_trailer) 552 533 file.seek(0) 553 534 sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')" 554 - res = PQexec(conn, sql) 535 + res = PQexec(conn, toclientstr(sql)) 555 536 if (PQresultStatus(res) != 4): 556 537 raise Exception("COPY FROM STDIN PQexec failed") 557 538 data = file.read(65536) ··· 585 566 call_file = open_output_file("call_table.bin") 586 567 587 568 def trace_begin(): 588 - print datetime.datetime.today(), "Writing to intermediate files..." 569 + printdate("Writing to intermediate files...") 589 570 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs 590 571 evsel_table(0, "unknown") 591 572 machine_table(0, 0, "unknown") ··· 601 582 unhandled_count = 0 602 583 603 584 def trace_end(): 604 - print datetime.datetime.today(), "Copying to database..." 585 + printdate("Copying to database...") 605 586 copy_output_file(evsel_file, "selected_events") 606 587 copy_output_file(machine_file, "machines") 607 588 copy_output_file(thread_file, "threads") ··· 616 597 if perf_db_export_calls: 617 598 copy_output_file(call_file, "calls") 618 599 619 - print datetime.datetime.today(), "Removing intermediate files..." 600 + printdate("Removing intermediate files...") 620 601 remove_output_file(evsel_file) 621 602 remove_output_file(machine_file) 622 603 remove_output_file(thread_file) ··· 631 612 if perf_db_export_calls: 632 613 remove_output_file(call_file) 633 614 os.rmdir(output_dir_name) 634 - print datetime.datetime.today(), "Adding primary keys" 615 + printdate("Adding primary keys") 635 616 do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)') 636 617 do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)') 637 618 do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)') ··· 646 627 if perf_db_export_calls: 647 628 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)') 648 629 649 - print datetime.datetime.today(), "Adding foreign keys" 630 + printdate("Adding foreign keys") 650 631 do_query(query, 'ALTER TABLE threads ' 651 632 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),' 652 633 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)') ··· 682 663 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') 683 664 684 665 if (unhandled_count): 685 - print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" 686 - print datetime.datetime.today(), "Done" 666 + printdate("Warning: ", unhandled_count, " unhandled events") 667 + printdate("Done") 687 668 688 669 def trace_unhandled(event_name, context, event_fields_dict): 689 670 global unhandled_count ··· 693 674 pass 694 675 695 676 def evsel_table(evsel_id, evsel_name, *x): 677 + evsel_name = toserverstr(evsel_name) 696 678 n = len(evsel_name) 697 679 fmt = "!hiqi" + str(n) + "s" 698 680 value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name) 699 681 evsel_file.write(value) 700 682 701 683 def machine_table(machine_id, pid, root_dir, *x): 684 + root_dir = toserverstr(root_dir) 702 685 n = len(root_dir) 703 686 fmt = "!hiqiii" + str(n) + "s" 704 687 value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir) ··· 711 690 thread_file.write(value) 712 691 713 692 def comm_table(comm_id, comm_str, *x): 693 + comm_str = toserverstr(comm_str) 714 694 n = len(comm_str) 715 695 fmt = "!hiqi" + str(n) + "s" 716 696 value = struct.pack(fmt, 2, 8, comm_id, n, comm_str) ··· 723 701 comm_thread_file.write(value) 724 702 725 703 def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x): 704 + short_name = toserverstr(short_name) 705 + long_name = toserverstr(long_name) 706 + build_id = toserverstr(build_id) 726 707 n1 = len(short_name) 727 708 n2 = len(long_name) 728 709 n3 = len(build_id) ··· 734 709 dso_file.write(value) 735 710 736 711 def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x): 712 + symbol_name = toserverstr(symbol_name) 737 713 n = len(symbol_name) 738 714 fmt = "!hiqiqiqiqiii" + str(n) + "s" 739 715 value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name) 740 716 symbol_file.write(value) 741 717 742 718 def branch_type_table(branch_type, name, *x): 719 + name = toserverstr(name) 743 720 n = len(name) 744 721 fmt = "!hiii" + str(n) + "s" 745 722 value = struct.pack(fmt, 2, 4, branch_type, n, name)
+17 -9
tools/perf/scripts/python/export-to-sqlite.py
··· 10 10 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 11 # more details. 12 12 13 + from __future__ import print_function 14 + 13 15 import os 14 16 import sys 15 17 import struct ··· 62 60 perf_db_export_calls = False 63 61 perf_db_export_callchains = False 64 62 63 + def printerr(*args, **keyword_args): 64 + print(*args, file=sys.stderr, **keyword_args) 65 + 66 + def printdate(*args, **kw_args): 67 + print(datetime.datetime.today(), *args, sep=' ', **kw_args) 68 + 65 69 def usage(): 66 - print >> sys.stderr, "Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>]" 67 - print >> sys.stderr, "where: columns 'all' or 'branches'" 68 - print >> sys.stderr, " calls 'calls' => create calls and call_paths table" 69 - print >> sys.stderr, " callchains 'callchains' => create call_paths table" 70 + printerr("Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>]"); 71 + printerr("where: columns 'all' or 'branches'"); 72 + printerr(" calls 'calls' => create calls and call_paths table"); 73 + printerr(" callchains 'callchains' => create call_paths table"); 70 74 raise Exception("Too few arguments") 71 75 72 76 if (len(sys.argv) < 2): ··· 108 100 return 109 101 raise Exception("Query failed: " + q.lastError().text()) 110 102 111 - print datetime.datetime.today(), "Creating database..." 103 + printdate("Creating database ...") 112 104 113 105 db_exists = False 114 106 try: ··· 386 378 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") 387 379 388 380 def trace_begin(): 389 - print datetime.datetime.today(), "Writing records..." 381 + printdate("Writing records...") 390 382 do_query(query, 'BEGIN TRANSACTION') 391 383 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs 392 384 evsel_table(0, "unknown") ··· 405 397 def trace_end(): 406 398 do_query(query, 'END TRANSACTION') 407 399 408 - print datetime.datetime.today(), "Adding indexes" 400 + printdate("Adding indexes") 409 401 if perf_db_export_calls: 410 402 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') 411 403 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') 412 404 413 405 if (unhandled_count): 414 - print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" 415 - print datetime.datetime.today(), "Done" 406 + printdate("Warning: ", unhandled_count, " unhandled events") 407 + printdate("Done") 416 408 417 409 def trace_unhandled(event_name, context, event_fields_dict): 418 410 global unhandled_count
+28 -14
tools/perf/scripts/python/exported-sql-viewer.py
··· 88 88 # 7fab593ea956 48 89 15 3b 13 22 00 movq %rdx, 0x22133b(%rip) 89 89 # 8107675243232 2 ls 22011 22011 hardware interrupt No 7fab593ea956 _dl_start+0x26 (ld-2.19.so) -> ffffffff86a012e0 page_fault ([kernel]) 90 90 91 + from __future__ import print_function 92 + 91 93 import sys 92 94 import weakref 93 95 import threading 94 96 import string 95 - import cPickle 97 + try: 98 + # Python2 99 + import cPickle as pickle 100 + # size of pickled integer big enough for record size 101 + glb_nsz = 8 102 + except ImportError: 103 + import pickle 104 + glb_nsz = 16 96 105 import re 97 106 import os 98 107 from PySide.QtCore import * ··· 110 101 from decimal import * 111 102 from ctypes import * 112 103 from multiprocessing import Process, Array, Value, Event 104 + 105 + # xrange is range in Python3 106 + try: 107 + xrange 108 + except NameError: 109 + xrange = range 110 + 111 + def printerr(*args, **keyword_args): 112 + print(*args, file=sys.stderr, **keyword_args) 113 113 114 114 # Data formatting helpers 115 115 ··· 1022 1004 1023 1005 glb_chunk_sz = 10000 1024 1006 1025 - # size of pickled integer big enough for record size 1026 - 1027 - glb_nsz = 8 1028 - 1029 1007 # Background process for SQL data fetcher 1030 1008 1031 1009 class SQLFetcherProcess(): ··· 1080 1066 return True 1081 1067 if space >= glb_nsz: 1082 1068 # Use 0 (or space < glb_nsz) to mean there is no more at the top of the buffer 1083 - nd = cPickle.dumps(0, cPickle.HIGHEST_PROTOCOL) 1069 + nd = pickle.dumps(0, pickle.HIGHEST_PROTOCOL) 1084 1070 self.buffer[self.local_head : self.local_head + len(nd)] = nd 1085 1071 self.local_head = 0 1086 1072 if self.local_tail - self.local_head > sz: ··· 1098 1084 self.wait_event.wait() 1099 1085 1100 1086 def AddToBuffer(self, obj): 1101 - d = cPickle.dumps(obj, cPickle.HIGHEST_PROTOCOL) 1087 + d = pickle.dumps(obj, pickle.HIGHEST_PROTOCOL) 1102 1088 n = len(d) 1103 - nd = cPickle.dumps(n, cPickle.HIGHEST_PROTOCOL) 1089 + nd = pickle.dumps(n, pickle.HIGHEST_PROTOCOL) 1104 1090 sz = n + glb_nsz 1105 1091 self.WaitForSpace(sz) 1106 1092 pos = self.local_head ··· 1212 1198 pos = self.local_tail 1213 1199 if len(self.buffer) - pos < glb_nsz: 1214 1200 pos = 0 1215 - n = cPickle.loads(self.buffer[pos : pos + glb_nsz]) 1201 + n = pickle.loads(self.buffer[pos : pos + glb_nsz]) 1216 1202 if n == 0: 1217 1203 pos = 0 1218 - n = cPickle.loads(self.buffer[0 : glb_nsz]) 1204 + n = pickle.loads(self.buffer[0 : glb_nsz]) 1219 1205 pos += glb_nsz 1220 - obj = cPickle.loads(self.buffer[pos : pos + n]) 1206 + obj = pickle.loads(self.buffer[pos : pos + n]) 1221 1207 self.local_tail = pos + n 1222 1208 return obj 1223 1209 ··· 2987 2973 2988 2974 def Main(): 2989 2975 if (len(sys.argv) < 2): 2990 - print >> sys.stderr, "Usage is: exported-sql-viewer.py {<database name> | --help-only}" 2976 + printerr("Usage is: exported-sql-viewer.py {<database name> | --help-only}"); 2991 2977 raise Exception("Too few arguments") 2992 2978 2993 2979 dbname = sys.argv[1] ··· 3000 2986 3001 2987 is_sqlite3 = False 3002 2988 try: 3003 - f = open(dbname) 3004 - if f.read(15) == "SQLite format 3": 2989 + f = open(dbname, "rb") 2990 + if f.read(15) == b'SQLite format 3': 3005 2991 is_sqlite3 = True 3006 2992 f.close() 3007 2993 except:
+1 -1
tools/perf/tests/attr/test-record-C0
··· 1 1 [config] 2 2 command = record 3 - args = -C 0 kill >/dev/null 2>&1 3 + args = --no-bpf-event -C 0 kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-basic
··· 1 1 [config] 2 2 command = record 3 - args = kill >/dev/null 2>&1 3 + args = --no-bpf-event kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-branch-any
··· 1 1 [config] 2 2 command = record 3 - args = -b kill >/dev/null 2>&1 3 + args = --no-bpf-event -b kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-branch-filter-any
··· 1 1 [config] 2 2 command = record 3 - args = -j any kill >/dev/null 2>&1 3 + args = --no-bpf-event -j any kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-branch-filter-any_call
··· 1 1 [config] 2 2 command = record 3 - args = -j any_call kill >/dev/null 2>&1 3 + args = --no-bpf-event -j any_call kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-branch-filter-any_ret
··· 1 1 [config] 2 2 command = record 3 - args = -j any_ret kill >/dev/null 2>&1 3 + args = --no-bpf-event -j any_ret kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-branch-filter-hv
··· 1 1 [config] 2 2 command = record 3 - args = -j hv kill >/dev/null 2>&1 3 + args = --no-bpf-event -j hv kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-branch-filter-ind_call
··· 1 1 [config] 2 2 command = record 3 - args = -j ind_call kill >/dev/null 2>&1 3 + args = --no-bpf-event -j ind_call kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-branch-filter-k
··· 1 1 [config] 2 2 command = record 3 - args = -j k kill >/dev/null 2>&1 3 + args = --no-bpf-event -j k kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-branch-filter-u
··· 1 1 [config] 2 2 command = record 3 - args = -j u kill >/dev/null 2>&1 3 + args = --no-bpf-event -j u kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-count
··· 1 1 [config] 2 2 command = record 3 - args = -c 123 kill >/dev/null 2>&1 3 + args = --no-bpf-event -c 123 kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-data
··· 1 1 [config] 2 2 command = record 3 - args = -d kill >/dev/null 2>&1 3 + args = --no-bpf-event -d kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-freq
··· 1 1 [config] 2 2 command = record 3 - args = -F 100 kill >/dev/null 2>&1 3 + args = --no-bpf-event -F 100 kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-graph-default
··· 1 1 [config] 2 2 command = record 3 - args = -g kill >/dev/null 2>&1 3 + args = --no-bpf-event -g kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-graph-dwarf
··· 1 1 [config] 2 2 command = record 3 - args = --call-graph dwarf -- kill >/dev/null 2>&1 3 + args = --no-bpf-event --call-graph dwarf -- kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-graph-fp
··· 1 1 [config] 2 2 command = record 3 - args = --call-graph fp kill >/dev/null 2>&1 3 + args = --no-bpf-event --call-graph fp kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-group
··· 1 1 [config] 2 2 command = record 3 - args = --group -e cycles,instructions kill >/dev/null 2>&1 3 + args = --no-bpf-event --group -e cycles,instructions kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event-1:base-record]
+1 -1
tools/perf/tests/attr/test-record-group-sampling
··· 1 1 [config] 2 2 command = record 3 - args = -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 3 + args = --no-bpf-event -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event-1:base-record]
+1 -1
tools/perf/tests/attr/test-record-group1
··· 1 1 [config] 2 2 command = record 3 - args = -e '{cycles,instructions}' kill >/dev/null 2>&1 3 + args = --no-bpf-event -e '{cycles,instructions}' kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event-1:base-record]
+1 -1
tools/perf/tests/attr/test-record-no-buffering
··· 1 1 [config] 2 2 command = record 3 - args = --no-buffering kill >/dev/null 2>&1 3 + args = --no-bpf-event --no-buffering kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-no-inherit
··· 1 1 [config] 2 2 command = record 3 - args = -i kill >/dev/null 2>&1 3 + args = --no-bpf-event -i kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-no-samples
··· 1 1 [config] 2 2 command = record 3 - args = -n kill >/dev/null 2>&1 3 + args = --no-bpf-event -n kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-period
··· 1 1 [config] 2 2 command = record 3 - args = -c 100 -P kill >/dev/null 2>&1 3 + args = --no-bpf-event -c 100 -P kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/attr/test-record-raw
··· 1 1 [config] 2 2 command = record 3 - args = -R kill >/dev/null 2>&1 3 + args = --no-bpf-event -R kill >/dev/null 2>&1 4 4 ret = 1 5 5 6 6 [event:base-record]
+1 -1
tools/perf/tests/backward-ring-buffer.c
··· 18 18 int i; 19 19 20 20 for (i = 0; i < NR_ITERS; i++) { 21 - char proc_name[10]; 21 + char proc_name[15]; 22 22 23 23 snprintf(proc_name, sizeof(proc_name), "p:%d\n", i); 24 24 prctl(PR_SET_NAME, proc_name);
+1
tools/perf/tests/evsel-tp-sched.c
··· 85 85 if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) 86 86 ret = -1; 87 87 88 + perf_evsel__delete(evsel); 88 89 return ret; 89 90 }
+4 -1
tools/perf/tests/expr.c
··· 19 19 const char *p; 20 20 const char **other; 21 21 double val; 22 - int ret; 22 + int i, ret; 23 23 struct parse_ctx ctx; 24 24 int num_other; 25 25 ··· 56 56 TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ")); 57 57 TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO")); 58 58 TEST_ASSERT_VAL("find other", other[3] == NULL); 59 + 60 + for (i = 0; i < num_other; i++) 61 + free((void *)other[i]); 59 62 free((void *)other); 60 63 61 64 return 0;
+3 -1
tools/perf/tests/openat-syscall-all-cpus.c
··· 45 45 if (IS_ERR(evsel)) { 46 46 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat"); 47 47 pr_debug("%s\n", errbuf); 48 - goto out_thread_map_delete; 48 + goto out_cpu_map_delete; 49 49 } 50 50 51 51 if (perf_evsel__open(evsel, cpus, threads) < 0) { ··· 119 119 perf_evsel__close_fd(evsel); 120 120 out_evsel_delete: 121 121 perf_evsel__delete(evsel); 122 + out_cpu_map_delete: 123 + cpu_map__put(cpus); 122 124 out_thread_map_delete: 123 125 thread_map__put(threads); 124 126 return err;
+7 -3
tools/perf/ui/browser.c
··· 611 611 browser->top = browser->entries; 612 612 break; 613 613 case SEEK_CUR: 614 - browser->top = browser->top + browser->top_idx + offset; 614 + browser->top = (char **)browser->top + offset; 615 615 break; 616 616 case SEEK_END: 617 - browser->top = browser->top + browser->nr_entries - 1 + offset; 617 + browser->top = (char **)browser->entries + browser->nr_entries - 1 + offset; 618 618 break; 619 619 default: 620 620 return; 621 621 } 622 + assert((char **)browser->top < (char **)browser->entries + browser->nr_entries); 623 + assert((char **)browser->top >= (char **)browser->entries); 622 624 } 623 625 624 626 unsigned int ui_browser__argv_refresh(struct ui_browser *browser) ··· 632 630 browser->top = browser->entries; 633 631 634 632 pos = (char **)browser->top; 635 - while (idx < browser->nr_entries) { 633 + while (idx < browser->nr_entries && 634 + row < (unsigned)SLtt_Screen_Rows - 1) { 635 + assert(pos < (char **)browser->entries + browser->nr_entries); 636 636 if (!browser->filter || !browser->filter(browser, *pos)) { 637 637 ui_browser__gotorc(browser, row, 0); 638 638 browser->write(browser, pos, row);
+1
tools/perf/ui/browsers/Build
··· 3 3 perf-y += map.o 4 4 perf-y += scripts.o 5 5 perf-y += header.o 6 + perf-y += res_sample.o 6 7 7 8 CFLAGS_annotate.o += -DENABLE_SLFUTURE_CONST 8 9 CFLAGS_hists.o += -DENABLE_SLFUTURE_CONST
+1 -1
tools/perf/ui/browsers/annotate.c
··· 750 750 continue; 751 751 case 'r': 752 752 { 753 - script_browse(NULL); 753 + script_browse(NULL, NULL); 754 754 continue; 755 755 } 756 756 case 'k':
+127 -16
tools/perf/ui/browsers/hists.c
··· 7 7 #include <string.h> 8 8 #include <linux/rbtree.h> 9 9 #include <sys/ttydefaults.h> 10 + #include <linux/time64.h> 10 11 11 12 #include "../../util/callchain.h" 12 13 #include "../../util/evsel.h" ··· 31 30 #include "srcline.h" 32 31 #include "string2.h" 33 32 #include "units.h" 33 + #include "time-utils.h" 34 34 35 35 #include "sane_ctype.h" 36 36 ··· 1226 1224 hist_browser__hpp_color_overhead_guest_us; 1227 1225 perf_hpp__format[PERF_HPP__OVERHEAD_ACC].color = 1228 1226 hist_browser__hpp_color_overhead_acc; 1227 + 1228 + res_sample_init(); 1229 1229 } 1230 1230 1231 1231 static int hist_browser__show_entry(struct hist_browser *browser, ··· 2342 2338 } 2343 2339 2344 2340 struct popup_action { 2341 + unsigned long time; 2345 2342 struct thread *thread; 2346 2343 struct map_symbol ms; 2347 2344 int socket; 2345 + struct perf_evsel *evsel; 2346 + enum rstype rstype; 2348 2347 2349 2348 int (*fn)(struct hist_browser *browser, struct popup_action *act); 2350 2349 }; ··· 2534 2527 do_run_script(struct hist_browser *browser __maybe_unused, 2535 2528 struct popup_action *act) 2536 2529 { 2537 - char script_opt[64]; 2538 - memset(script_opt, 0, sizeof(script_opt)); 2530 + char *script_opt; 2531 + int len; 2532 + int n = 0; 2539 2533 2534 + len = 100; 2535 + if (act->thread) 2536 + len += strlen(thread__comm_str(act->thread)); 2537 + else if (act->ms.sym) 2538 + len += strlen(act->ms.sym->name); 2539 + script_opt = malloc(len); 2540 + if (!script_opt) 2541 + return -1; 2542 + 2543 + script_opt[0] = 0; 2540 2544 if (act->thread) { 2541 - scnprintf(script_opt, sizeof(script_opt), " -c %s ", 2545 + n = scnprintf(script_opt, len, " -c %s ", 2542 2546 thread__comm_str(act->thread)); 2543 2547 } else if (act->ms.sym) { 2544 - scnprintf(script_opt, sizeof(script_opt), " -S %s ", 2548 + n = scnprintf(script_opt, len, " -S %s ", 2545 2549 act->ms.sym->name); 2546 2550 } 2547 2551 2548 - script_browse(script_opt); 2552 + if (act->time) { 2553 + char start[32], end[32]; 2554 + unsigned long starttime = act->time; 2555 + unsigned long endtime = act->time + symbol_conf.time_quantum; 2556 + 2557 + if (starttime == endtime) { /* Display 1ms as fallback */ 2558 + starttime -= 1*NSEC_PER_MSEC; 2559 + endtime += 1*NSEC_PER_MSEC; 2560 + } 2561 + timestamp__scnprintf_usec(starttime, start, sizeof start); 2562 + timestamp__scnprintf_usec(endtime, end, sizeof end); 2563 + n += snprintf(script_opt + n, len - n, " --time %s,%s", start, end); 2564 + } 2565 + 2566 + script_browse(script_opt, act->evsel); 2567 + free(script_opt); 2549 2568 return 0; 2550 2569 } 2551 2570 2552 2571 static int 2553 - add_script_opt(struct hist_browser *browser __maybe_unused, 2554 - struct popup_action *act, char **optstr, 2555 - struct thread *thread, struct symbol *sym) 2572 + do_res_sample_script(struct hist_browser *browser __maybe_unused, 2573 + struct popup_action *act) 2556 2574 { 2575 + struct hist_entry *he; 2576 + 2577 + he = hist_browser__selected_entry(browser); 2578 + res_sample_browse(he->res_samples, he->num_res, act->evsel, act->rstype); 2579 + return 0; 2580 + } 2581 + 2582 + static int 2583 + add_script_opt_2(struct hist_browser *browser __maybe_unused, 2584 + struct popup_action *act, char **optstr, 2585 + struct thread *thread, struct symbol *sym, 2586 + struct perf_evsel *evsel, const char *tstr) 2587 + { 2588 + 2557 2589 if (thread) { 2558 - if (asprintf(optstr, "Run scripts for samples of thread [%s]", 2559 - thread__comm_str(thread)) < 0) 2590 + if (asprintf(optstr, "Run scripts for samples of thread [%s]%s", 2591 + thread__comm_str(thread), tstr) < 0) 2560 2592 return 0; 2561 2593 } else if (sym) { 2562 - if (asprintf(optstr, "Run scripts for samples of symbol [%s]", 2563 - sym->name) < 0) 2594 + if (asprintf(optstr, "Run scripts for samples of symbol [%s]%s", 2595 + sym->name, tstr) < 0) 2564 2596 return 0; 2565 2597 } else { 2566 - if (asprintf(optstr, "Run scripts for all samples") < 0) 2598 + if (asprintf(optstr, "Run scripts for all samples%s", tstr) < 0) 2567 2599 return 0; 2568 2600 } 2569 2601 2570 2602 act->thread = thread; 2571 2603 act->ms.sym = sym; 2604 + act->evsel = evsel; 2572 2605 act->fn = do_run_script; 2606 + return 1; 2607 + } 2608 + 2609 + static int 2610 + add_script_opt(struct hist_browser *browser, 2611 + struct popup_action *act, char **optstr, 2612 + struct thread *thread, struct symbol *sym, 2613 + struct perf_evsel *evsel) 2614 + { 2615 + int n, j; 2616 + struct hist_entry *he; 2617 + 2618 + n = add_script_opt_2(browser, act, optstr, thread, sym, evsel, ""); 2619 + 2620 + he = hist_browser__selected_entry(browser); 2621 + if (sort_order && strstr(sort_order, "time")) { 2622 + char tstr[128]; 2623 + 2624 + optstr++; 2625 + act++; 2626 + j = sprintf(tstr, " in "); 2627 + j += timestamp__scnprintf_usec(he->time, tstr + j, 2628 + sizeof tstr - j); 2629 + j += sprintf(tstr + j, "-"); 2630 + timestamp__scnprintf_usec(he->time + symbol_conf.time_quantum, 2631 + tstr + j, sizeof tstr - j); 2632 + n += add_script_opt_2(browser, act, optstr, thread, sym, 2633 + evsel, tstr); 2634 + act->time = he->time; 2635 + } 2636 + return n; 2637 + } 2638 + 2639 + static int 2640 + add_res_sample_opt(struct hist_browser *browser __maybe_unused, 2641 + struct popup_action *act, char **optstr, 2642 + struct res_sample *res_sample, 2643 + struct perf_evsel *evsel, 2644 + enum rstype type) 2645 + { 2646 + if (!res_sample) 2647 + return 0; 2648 + 2649 + if (asprintf(optstr, "Show context for individual samples %s", 2650 + type == A_ASM ? "with assembler" : 2651 + type == A_SOURCE ? "with source" : "") < 0) 2652 + return 0; 2653 + 2654 + act->fn = do_res_sample_script; 2655 + act->evsel = evsel; 2656 + act->rstype = type; 2573 2657 return 1; 2574 2658 } 2575 2659 ··· 3129 3031 nr_options += add_script_opt(browser, 3130 3032 &actions[nr_options], 3131 3033 &options[nr_options], 3132 - thread, NULL); 3034 + thread, NULL, evsel); 3133 3035 } 3134 3036 /* 3135 3037 * Note that browser->selection != NULL ··· 3144 3046 nr_options += add_script_opt(browser, 3145 3047 &actions[nr_options], 3146 3048 &options[nr_options], 3147 - NULL, browser->selection->sym); 3049 + NULL, browser->selection->sym, 3050 + evsel); 3148 3051 } 3149 3052 } 3150 3053 nr_options += add_script_opt(browser, &actions[nr_options], 3151 - &options[nr_options], NULL, NULL); 3054 + &options[nr_options], NULL, NULL, evsel); 3055 + nr_options += add_res_sample_opt(browser, &actions[nr_options], 3056 + &options[nr_options], 3057 + hist_browser__selected_entry(browser)->res_samples, 3058 + evsel, A_NORMAL); 3059 + nr_options += add_res_sample_opt(browser, &actions[nr_options], 3060 + &options[nr_options], 3061 + hist_browser__selected_entry(browser)->res_samples, 3062 + evsel, A_ASM); 3063 + nr_options += add_res_sample_opt(browser, &actions[nr_options], 3064 + &options[nr_options], 3065 + hist_browser__selected_entry(browser)->res_samples, 3066 + evsel, A_SOURCE); 3152 3067 nr_options += add_switch_opt(browser, &actions[nr_options], 3153 3068 &options[nr_options]); 3154 3069 skip_scripting:
+91
tools/perf/ui/browsers/res_sample.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Display a menu with individual samples to browse with perf script */ 3 + #include "util.h" 4 + #include "hist.h" 5 + #include "evsel.h" 6 + #include "hists.h" 7 + #include "sort.h" 8 + #include "config.h" 9 + #include "time-utils.h" 10 + #include <linux/time64.h> 11 + 12 + static u64 context_len = 10 * NSEC_PER_MSEC; 13 + 14 + static int res_sample_config(const char *var, const char *value, void *data __maybe_unused) 15 + { 16 + if (!strcmp(var, "samples.context")) 17 + return perf_config_u64(&context_len, var, value); 18 + return 0; 19 + } 20 + 21 + void res_sample_init(void) 22 + { 23 + perf_config(res_sample_config, NULL); 24 + } 25 + 26 + int res_sample_browse(struct res_sample *res_samples, int num_res, 27 + struct perf_evsel *evsel, enum rstype rstype) 28 + { 29 + char **names; 30 + int i, n; 31 + int choice; 32 + char *cmd; 33 + char pbuf[256], tidbuf[32], cpubuf[32]; 34 + const char *perf = perf_exe(pbuf, sizeof pbuf); 35 + char trange[128], tsample[64]; 36 + struct res_sample *r; 37 + char extra_format[256]; 38 + 39 + names = calloc(num_res, sizeof(char *)); 40 + if (!names) 41 + return -1; 42 + for (i = 0; i < num_res; i++) { 43 + char tbuf[64]; 44 + 45 + timestamp__scnprintf_nsec(res_samples[i].time, tbuf, sizeof tbuf); 46 + if (asprintf(&names[i], "%s: CPU %d tid %d", tbuf, 47 + res_samples[i].cpu, res_samples[i].tid) < 0) { 48 + while (--i >= 0) 49 + free(names[i]); 50 + free(names); 51 + return -1; 52 + } 53 + } 54 + choice = ui__popup_menu(num_res, names); 55 + for (i = 0; i < num_res; i++) 56 + free(names[i]); 57 + free(names); 58 + 59 + if (choice < 0 || choice >= num_res) 60 + return -1; 61 + r = &res_samples[choice]; 62 + 63 + n = timestamp__scnprintf_nsec(r->time - context_len, trange, sizeof trange); 64 + trange[n++] = ','; 65 + timestamp__scnprintf_nsec(r->time + context_len, trange + n, sizeof trange - n); 66 + 67 + timestamp__scnprintf_nsec(r->time, tsample, sizeof tsample); 68 + 69 + attr_to_script(extra_format, &evsel->attr); 70 + 71 + if (asprintf(&cmd, "%s script %s%s --time %s %s%s %s%s --ns %s %s %s %s %s | less +/%s", 72 + perf, 73 + input_name ? "-i " : "", 74 + input_name ? input_name : "", 75 + trange, 76 + r->cpu >= 0 ? "--cpu " : "", 77 + r->cpu >= 0 ? (sprintf(cpubuf, "%d", r->cpu), cpubuf) : "", 78 + r->tid ? "--tid " : "", 79 + r->tid ? (sprintf(tidbuf, "%d", r->tid), tidbuf) : "", 80 + extra_format, 81 + rstype == A_ASM ? "-F +insn --xed" : 82 + rstype == A_SOURCE ? "-F +srcline,+srccode" : "", 83 + symbol_conf.inline_name ? "--inline" : "", 84 + "--show-lost-events ", 85 + r->tid ? "--show-switch-events --show-task-events " : "", 86 + tsample) < 0) 87 + return -1; 88 + run_script(cmd); 89 + free(cmd); 90 + return 0; 91 + }
+137 -139
tools/perf/ui/browsers/scripts.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <elf.h> 3 - #include <inttypes.h> 4 - #include <sys/ttydefaults.h> 5 - #include <string.h> 6 2 #include "../../util/sort.h" 7 3 #include "../../util/util.h" 8 4 #include "../../util/hist.h" 9 5 #include "../../util/debug.h" 10 6 #include "../../util/symbol.h" 11 7 #include "../browser.h" 12 - #include "../helpline.h" 13 8 #include "../libslang.h" 14 - 15 - /* 2048 lines should be enough for a script output */ 16 - #define MAX_LINES 2048 17 - 18 - /* 160 bytes for one output line */ 19 - #define AVERAGE_LINE_LEN 160 20 - 21 - struct script_line { 22 - struct list_head node; 23 - char line[AVERAGE_LINE_LEN]; 24 - }; 25 - 26 - struct perf_script_browser { 27 - struct ui_browser b; 28 - struct list_head entries; 29 - const char *script_name; 30 - int nr_lines; 31 - }; 9 + #include "config.h" 32 10 33 11 #define SCRIPT_NAMELEN 128 34 12 #define SCRIPT_MAX_NO 64 ··· 18 40 */ 19 41 #define SCRIPT_FULLPATH_LEN 256 20 42 43 + struct script_config { 44 + const char **names; 45 + char **paths; 46 + int index; 47 + const char *perf; 48 + char extra_format[256]; 49 + }; 50 + 51 + void attr_to_script(char *extra_format, struct perf_event_attr *attr) 52 + { 53 + extra_format[0] = 0; 54 + if (attr->read_format & PERF_FORMAT_GROUP) 55 + strcat(extra_format, " -F +metric"); 56 + if (attr->sample_type & PERF_SAMPLE_BRANCH_STACK) 57 + strcat(extra_format, " -F +brstackinsn --xed"); 58 + if (attr->sample_type & PERF_SAMPLE_REGS_INTR) 59 + strcat(extra_format, " -F +iregs"); 60 + if (attr->sample_type & PERF_SAMPLE_REGS_USER) 61 + strcat(extra_format, " -F +uregs"); 62 + if (attr->sample_type & PERF_SAMPLE_PHYS_ADDR) 63 + strcat(extra_format, " -F +phys_addr"); 64 + } 65 + 66 + static int add_script_option(const char *name, const char *opt, 67 + struct script_config *c) 68 + { 69 + c->names[c->index] = name; 70 + if (asprintf(&c->paths[c->index], 71 + "%s script %s -F +metric %s %s", 72 + c->perf, opt, symbol_conf.inline_name ? " --inline" : "", 73 + c->extra_format) < 0) 74 + return -1; 75 + c->index++; 76 + return 0; 77 + } 78 + 79 + static int scripts_config(const char *var, const char *value, void *data) 80 + { 81 + struct script_config *c = data; 82 + 83 + if (!strstarts(var, "scripts.")) 84 + return -1; 85 + if (c->index >= SCRIPT_MAX_NO) 86 + return -1; 87 + c->names[c->index] = strdup(var + 7); 88 + if (!c->names[c->index]) 89 + return -1; 90 + if (asprintf(&c->paths[c->index], "%s %s", value, 91 + c->extra_format) < 0) 92 + return -1; 93 + c->index++; 94 + return 0; 95 + } 96 + 21 97 /* 22 98 * When success, will copy the full path of the selected script 23 99 * into the buffer pointed by script_name, and return 0. 24 100 * Return -1 on failure. 25 101 */ 26 - static int list_scripts(char *script_name) 102 + static int list_scripts(char *script_name, bool *custom, 103 + struct perf_evsel *evsel) 27 104 { 28 - char *buf, *names[SCRIPT_MAX_NO], *paths[SCRIPT_MAX_NO]; 29 - int i, num, choice, ret = -1; 105 + char *buf, *paths[SCRIPT_MAX_NO], *names[SCRIPT_MAX_NO]; 106 + int i, num, choice; 107 + int ret = 0; 108 + int max_std, custom_perf; 109 + char pbuf[256]; 110 + const char *perf = perf_exe(pbuf, sizeof pbuf); 111 + struct script_config scriptc = { 112 + .names = (const char **)names, 113 + .paths = paths, 114 + .perf = perf 115 + }; 116 + 117 + script_name[0] = 0; 30 118 31 119 /* Preset the script name to SCRIPT_NAMELEN */ 32 120 buf = malloc(SCRIPT_MAX_NO * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN)); 33 121 if (!buf) 34 - return ret; 122 + return -1; 35 123 36 - for (i = 0; i < SCRIPT_MAX_NO; i++) { 37 - names[i] = buf + i * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN); 124 + if (evsel) 125 + attr_to_script(scriptc.extra_format, &evsel->attr); 126 + add_script_option("Show individual samples", "", &scriptc); 127 + add_script_option("Show individual samples with assembler", "-F +insn --xed", 128 + &scriptc); 129 + add_script_option("Show individual samples with source", "-F +srcline,+srccode", 130 + &scriptc); 131 + perf_config(scripts_config, &scriptc); 132 + custom_perf = scriptc.index; 133 + add_script_option("Show samples with custom perf script arguments", "", &scriptc); 134 + i = scriptc.index; 135 + max_std = i; 136 + 137 + for (; i < SCRIPT_MAX_NO; i++) { 138 + names[i] = buf + (i - max_std) * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN); 38 139 paths[i] = names[i] + SCRIPT_NAMELEN; 39 140 } 40 141 41 - num = find_scripts(names, paths); 42 - if (num > 0) { 43 - choice = ui__popup_menu(num, names); 44 - if (choice < num && choice >= 0) { 45 - strcpy(script_name, paths[choice]); 46 - ret = 0; 47 - } 142 + num = find_scripts(names + max_std, paths + max_std, SCRIPT_MAX_NO - max_std, 143 + SCRIPT_FULLPATH_LEN); 144 + if (num < 0) 145 + num = 0; 146 + choice = ui__popup_menu(num + max_std, (char * const *)names); 147 + if (choice < 0) { 148 + ret = -1; 149 + goto out; 48 150 } 151 + if (choice == custom_perf) { 152 + char script_args[50]; 153 + int key = ui_browser__input_window("perf script command", 154 + "Enter perf script command line (without perf script prefix)", 155 + script_args, "", 0); 156 + if (key != K_ENTER) 157 + return -1; 158 + sprintf(script_name, "%s script %s", perf, script_args); 159 + } else if (choice < num + max_std) { 160 + strcpy(script_name, paths[choice]); 161 + } 162 + *custom = choice >= max_std; 49 163 164 + out: 50 165 free(buf); 166 + for (i = 0; i < max_std; i++) 167 + free(paths[i]); 51 168 return ret; 52 169 } 53 170 54 - static void script_browser__write(struct ui_browser *browser, 55 - void *entry, int row) 171 + void run_script(char *cmd) 56 172 { 57 - struct script_line *sline = list_entry(entry, struct script_line, node); 58 - bool current_entry = ui_browser__is_current_entry(browser, row); 59 - 60 - ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : 61 - HE_COLORSET_NORMAL); 62 - 63 - ui_browser__write_nstring(browser, sline->line, browser->width); 173 + pr_debug("Running %s\n", cmd); 174 + SLang_reset_tty(); 175 + if (system(cmd) < 0) 176 + pr_warning("Cannot run %s\n", cmd); 177 + /* 178 + * SLang doesn't seem to reset the whole terminal, so be more 179 + * forceful to get back to the original state. 180 + */ 181 + printf("\033[c\033[H\033[J"); 182 + fflush(stdout); 183 + SLang_init_tty(0, 0, 0); 184 + SLsmg_refresh(); 64 185 } 65 186 66 - static int script_browser__run(struct perf_script_browser *browser) 187 + int script_browse(const char *script_opt, struct perf_evsel *evsel) 67 188 { 68 - int key; 69 - 70 - if (ui_browser__show(&browser->b, browser->script_name, 71 - "Press ESC to exit") < 0) 72 - return -1; 73 - 74 - while (1) { 75 - key = ui_browser__run(&browser->b, 0); 76 - 77 - /* We can add some special key handling here if needed */ 78 - break; 79 - } 80 - 81 - ui_browser__hide(&browser->b); 82 - return key; 83 - } 84 - 85 - 86 - int script_browse(const char *script_opt) 87 - { 88 - char cmd[SCRIPT_FULLPATH_LEN*2], script_name[SCRIPT_FULLPATH_LEN]; 89 - char *line = NULL; 90 - size_t len = 0; 91 - ssize_t retlen; 92 - int ret = -1, nr_entries = 0; 93 - FILE *fp; 94 - void *buf; 95 - struct script_line *sline; 96 - 97 - struct perf_script_browser script = { 98 - .b = { 99 - .refresh = ui_browser__list_head_refresh, 100 - .seek = ui_browser__list_head_seek, 101 - .write = script_browser__write, 102 - }, 103 - .script_name = script_name, 104 - }; 105 - 106 - INIT_LIST_HEAD(&script.entries); 107 - 108 - /* Save each line of the output in one struct script_line object. */ 109 - buf = zalloc((sizeof(*sline)) * MAX_LINES); 110 - if (!buf) 111 - return -1; 112 - sline = buf; 189 + char *cmd, script_name[SCRIPT_FULLPATH_LEN]; 190 + bool custom = false; 113 191 114 192 memset(script_name, 0, SCRIPT_FULLPATH_LEN); 115 - if (list_scripts(script_name)) 116 - goto exit; 193 + if (list_scripts(script_name, &custom, evsel)) 194 + return -1; 117 195 118 - sprintf(cmd, "perf script -s %s ", script_name); 196 + if (asprintf(&cmd, "%s%s %s %s%s 2>&1 | less", 197 + custom ? "perf script -s " : "", 198 + script_name, 199 + script_opt ? script_opt : "", 200 + input_name ? "-i " : "", 201 + input_name ? input_name : "") < 0) 202 + return -1; 119 203 120 - if (script_opt) 121 - strcat(cmd, script_opt); 204 + run_script(cmd); 205 + free(cmd); 122 206 123 - if (input_name) { 124 - strcat(cmd, " -i "); 125 - strcat(cmd, input_name); 126 - } 127 - 128 - strcat(cmd, " 2>&1"); 129 - 130 - fp = popen(cmd, "r"); 131 - if (!fp) 132 - goto exit; 133 - 134 - while ((retlen = getline(&line, &len, fp)) != -1) { 135 - strncpy(sline->line, line, AVERAGE_LINE_LEN); 136 - 137 - /* If one output line is very large, just cut it short */ 138 - if (retlen >= AVERAGE_LINE_LEN) { 139 - sline->line[AVERAGE_LINE_LEN - 1] = '\0'; 140 - sline->line[AVERAGE_LINE_LEN - 2] = '\n'; 141 - } 142 - list_add_tail(&sline->node, &script.entries); 143 - 144 - if (script.b.width < retlen) 145 - script.b.width = retlen; 146 - 147 - if (nr_entries++ >= MAX_LINES - 1) 148 - break; 149 - sline++; 150 - } 151 - 152 - if (script.b.width > AVERAGE_LINE_LEN) 153 - script.b.width = AVERAGE_LINE_LEN; 154 - 155 - free(line); 156 - pclose(fp); 157 - 158 - script.nr_lines = nr_entries; 159 - script.b.nr_entries = nr_entries; 160 - script.b.entries = &script.entries; 161 - 162 - ret = script_browser__run(&script); 163 - exit: 164 - free(buf); 165 - return ret; 207 + return 0; 166 208 }
+162 -1
tools/perf/util/annotate.c
··· 10 10 #include <errno.h> 11 11 #include <inttypes.h> 12 12 #include <libgen.h> 13 + #include <bpf/bpf.h> 14 + #include <bpf/btf.h> 15 + #include <bpf/libbpf.h> 16 + #include <linux/btf.h> 13 17 #include "util.h" 14 18 #include "ui/ui.h" 15 19 #include "sort.h" ··· 28 24 #include "annotate.h" 29 25 #include "evsel.h" 30 26 #include "evlist.h" 27 + #include "bpf-event.h" 31 28 #include "block-range.h" 32 29 #include "string2.h" 33 30 #include "arch/common.h" ··· 36 31 #include <pthread.h> 37 32 #include <linux/bitops.h> 38 33 #include <linux/kernel.h> 34 + #include <bpf/libbpf.h> 39 35 40 36 /* FIXME: For the HE_COLORSET */ 41 37 #include "ui/browser.h" ··· 1621 1615 " --vmlinux vmlinux\n", build_id_msg ?: ""); 1622 1616 } 1623 1617 break; 1618 + case SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF: 1619 + scnprintf(buf, buflen, "Please link with binutils's libopcode to enable BPF annotation"); 1620 + break; 1624 1621 default: 1625 1622 scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum); 1626 1623 break; ··· 1683 1674 return 0; 1684 1675 } 1685 1676 1677 + #if defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT) 1678 + #define PACKAGE "perf" 1679 + #include <bfd.h> 1680 + #include <dis-asm.h> 1681 + 1682 + static int symbol__disassemble_bpf(struct symbol *sym, 1683 + struct annotate_args *args) 1684 + { 1685 + struct annotation *notes = symbol__annotation(sym); 1686 + struct annotation_options *opts = args->options; 1687 + struct bpf_prog_info_linear *info_linear; 1688 + struct bpf_prog_linfo *prog_linfo = NULL; 1689 + struct bpf_prog_info_node *info_node; 1690 + int len = sym->end - sym->start; 1691 + disassembler_ftype disassemble; 1692 + struct map *map = args->ms.map; 1693 + struct disassemble_info info; 1694 + struct dso *dso = map->dso; 1695 + int pc = 0, count, sub_id; 1696 + struct btf *btf = NULL; 1697 + char tpath[PATH_MAX]; 1698 + size_t buf_size; 1699 + int nr_skip = 0; 1700 + int ret = -1; 1701 + char *buf; 1702 + bfd *bfdf; 1703 + FILE *s; 1704 + 1705 + if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO) 1706 + return -1; 1707 + 1708 + pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__, 1709 + sym->name, sym->start, sym->end - sym->start); 1710 + 1711 + memset(tpath, 0, sizeof(tpath)); 1712 + perf_exe(tpath, sizeof(tpath)); 1713 + 1714 + bfdf = bfd_openr(tpath, NULL); 1715 + assert(bfdf); 1716 + assert(bfd_check_format(bfdf, bfd_object)); 1717 + 1718 + s = open_memstream(&buf, &buf_size); 1719 + if (!s) 1720 + goto out; 1721 + init_disassemble_info(&info, s, 1722 + (fprintf_ftype) fprintf); 1723 + 1724 + info.arch = bfd_get_arch(bfdf); 1725 + info.mach = bfd_get_mach(bfdf); 1726 + 1727 + info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, 1728 + dso->bpf_prog.id); 1729 + if (!info_node) 1730 + goto out; 1731 + info_linear = info_node->info_linear; 1732 + sub_id = dso->bpf_prog.sub_id; 1733 + 1734 + info.buffer = (void *)(info_linear->info.jited_prog_insns); 1735 + info.buffer_length = info_linear->info.jited_prog_len; 1736 + 1737 + if (info_linear->info.nr_line_info) 1738 + prog_linfo = bpf_prog_linfo__new(&info_linear->info); 1739 + 1740 + if (info_linear->info.btf_id) { 1741 + struct btf_node *node; 1742 + 1743 + node = perf_env__find_btf(dso->bpf_prog.env, 1744 + info_linear->info.btf_id); 1745 + if (node) 1746 + btf = btf__new((__u8 *)(node->data), 1747 + node->data_size); 1748 + } 1749 + 1750 + disassemble_init_for_target(&info); 1751 + 1752 + #ifdef DISASM_FOUR_ARGS_SIGNATURE 1753 + disassemble = disassembler(info.arch, 1754 + bfd_big_endian(bfdf), 1755 + info.mach, 1756 + bfdf); 1757 + #else 1758 + disassemble = disassembler(bfdf); 1759 + #endif 1760 + assert(disassemble); 1761 + 1762 + fflush(s); 1763 + do { 1764 + const struct bpf_line_info *linfo = NULL; 1765 + struct disasm_line *dl; 1766 + size_t prev_buf_size; 1767 + const char *srcline; 1768 + u64 addr; 1769 + 1770 + addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id]; 1771 + count = disassemble(pc, &info); 1772 + 1773 + if (prog_linfo) 1774 + linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo, 1775 + addr, sub_id, 1776 + nr_skip); 1777 + 1778 + if (linfo && btf) { 1779 + srcline = btf__name_by_offset(btf, linfo->line_off); 1780 + nr_skip++; 1781 + } else 1782 + srcline = NULL; 1783 + 1784 + fprintf(s, "\n"); 1785 + prev_buf_size = buf_size; 1786 + fflush(s); 1787 + 1788 + if (!opts->hide_src_code && srcline) { 1789 + args->offset = -1; 1790 + args->line = strdup(srcline); 1791 + args->line_nr = 0; 1792 + args->ms.sym = sym; 1793 + dl = disasm_line__new(args); 1794 + if (dl) { 1795 + annotation_line__add(&dl->al, 1796 + &notes->src->source); 1797 + } 1798 + } 1799 + 1800 + args->offset = pc; 1801 + args->line = buf + prev_buf_size; 1802 + args->line_nr = 0; 1803 + args->ms.sym = sym; 1804 + dl = disasm_line__new(args); 1805 + if (dl) 1806 + annotation_line__add(&dl->al, &notes->src->source); 1807 + 1808 + pc += count; 1809 + } while (count > 0 && pc < len); 1810 + 1811 + ret = 0; 1812 + out: 1813 + free(prog_linfo); 1814 + free(btf); 1815 + fclose(s); 1816 + bfd_close(bfdf); 1817 + return ret; 1818 + } 1819 + #else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT) 1820 + static int symbol__disassemble_bpf(struct symbol *sym __maybe_unused, 1821 + struct annotate_args *args __maybe_unused) 1822 + { 1823 + return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF; 1824 + } 1825 + #endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT) 1826 + 1686 1827 static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) 1687 1828 { 1688 1829 struct annotation_options *opts = args->options; ··· 1860 1701 pr_debug("annotating [%p] %30s : [%p] %30s\n", 1861 1702 dso, dso->long_name, sym, sym->name); 1862 1703 1863 - if (dso__is_kcore(dso)) { 1704 + if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) { 1705 + return symbol__disassemble_bpf(sym, args); 1706 + } else if (dso__is_kcore(dso)) { 1864 1707 kce.kcore_filename = symfs_filename; 1865 1708 kce.addr = map__rip_2objdump(map, sym->start); 1866 1709 kce.offs = sym->start;
+1
tools/perf/util/annotate.h
··· 369 369 __SYMBOL_ANNOTATE_ERRNO__START = -10000, 370 370 371 371 SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START, 372 + SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF, 372 373 373 374 __SYMBOL_ANNOTATE_ERRNO__END, 374 375 };
+12
tools/perf/util/archinsn.h
··· 1 + #ifndef INSN_H 2 + #define INSN_H 1 3 + 4 + struct perf_sample; 5 + struct machine; 6 + struct thread; 7 + 8 + void arch_fetch_insn(struct perf_sample *sample, 9 + struct thread *thread, 10 + struct machine *machine); 11 + 12 + #endif
+321 -104
tools/perf/util/bpf-event.c
··· 3 3 #include <stdlib.h> 4 4 #include <bpf/bpf.h> 5 5 #include <bpf/btf.h> 6 + #include <bpf/libbpf.h> 6 7 #include <linux/btf.h> 8 + #include <linux/err.h> 7 9 #include "bpf-event.h" 8 10 #include "debug.h" 9 11 #include "symbol.h" 10 12 #include "machine.h" 13 + #include "env.h" 14 + #include "session.h" 15 + #include "map.h" 16 + #include "evlist.h" 11 17 12 18 #define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr)) 13 19 ··· 27 21 return ret; 28 22 } 29 23 24 + static int machine__process_bpf_event_load(struct machine *machine, 25 + union perf_event *event, 26 + struct perf_sample *sample __maybe_unused) 27 + { 28 + struct bpf_prog_info_linear *info_linear; 29 + struct bpf_prog_info_node *info_node; 30 + struct perf_env *env = machine->env; 31 + int id = event->bpf_event.id; 32 + unsigned int i; 33 + 34 + /* perf-record, no need to handle bpf-event */ 35 + if (env == NULL) 36 + return 0; 37 + 38 + info_node = perf_env__find_bpf_prog_info(env, id); 39 + if (!info_node) 40 + return 0; 41 + info_linear = info_node->info_linear; 42 + 43 + for (i = 0; i < info_linear->info.nr_jited_ksyms; i++) { 44 + u64 *addrs = (u64 *)(uintptr_t)(info_linear->info.jited_ksyms); 45 + u64 addr = addrs[i]; 46 + struct map *map; 47 + 48 + map = map_groups__find(&machine->kmaps, addr); 49 + 50 + if (map) { 51 + map->dso->binary_type = DSO_BINARY_TYPE__BPF_PROG_INFO; 52 + map->dso->bpf_prog.id = id; 53 + map->dso->bpf_prog.sub_id = i; 54 + map->dso->bpf_prog.env = env; 55 + } 56 + } 57 + return 0; 58 + } 59 + 30 60 int machine__process_bpf_event(struct machine *machine __maybe_unused, 31 61 union perf_event *event, 32 62 struct perf_sample *sample __maybe_unused) 33 63 { 34 64 if (dump_trace) 35 65 perf_event__fprintf_bpf_event(event, stdout); 66 + 67 + switch (event->bpf_event.type) { 68 + case PERF_BPF_EVENT_PROG_LOAD: 69 + return machine__process_bpf_event_load(machine, event, sample); 70 + 71 + case PERF_BPF_EVENT_PROG_UNLOAD: 72 + /* 73 + * Do not free bpf_prog_info and btf of the program here, 74 + * as annotation still need them. They will be freed at 75 + * the end of the session. 76 + */ 77 + break; 78 + default: 79 + pr_debug("unexpected bpf_event type of %d\n", 80 + event->bpf_event.type); 81 + break; 82 + } 36 83 return 0; 84 + } 85 + 86 + static int perf_env__fetch_btf(struct perf_env *env, 87 + u32 btf_id, 88 + struct btf *btf) 89 + { 90 + struct btf_node *node; 91 + u32 data_size; 92 + const void *data; 93 + 94 + data = btf__get_raw_data(btf, &data_size); 95 + 96 + node = malloc(data_size + sizeof(struct btf_node)); 97 + if (!node) 98 + return -1; 99 + 100 + node->id = btf_id; 101 + node->data_size = data_size; 102 + memcpy(node->data, data, data_size); 103 + 104 + perf_env__insert_btf(env, node); 105 + return 0; 106 + } 107 + 108 + static int synthesize_bpf_prog_name(char *buf, int size, 109 + struct bpf_prog_info *info, 110 + struct btf *btf, 111 + u32 sub_id) 112 + { 113 + u8 (*prog_tags)[BPF_TAG_SIZE] = (void *)(uintptr_t)(info->prog_tags); 114 + void *func_infos = (void *)(uintptr_t)(info->func_info); 115 + u32 sub_prog_cnt = info->nr_jited_ksyms; 116 + const struct bpf_func_info *finfo; 117 + const char *short_name = NULL; 118 + const struct btf_type *t; 119 + int name_len; 120 + 121 + name_len = snprintf(buf, size, "bpf_prog_"); 122 + name_len += snprintf_hex(buf + name_len, size - name_len, 123 + prog_tags[sub_id], BPF_TAG_SIZE); 124 + if (btf) { 125 + finfo = func_infos + sub_id * info->func_info_rec_size; 126 + t = btf__type_by_id(btf, finfo->type_id); 127 + short_name = btf__name_by_offset(btf, t->name_off); 128 + } else if (sub_id == 0 && sub_prog_cnt == 1) { 129 + /* no subprog */ 130 + if (info->name[0]) 131 + short_name = info->name; 132 + } else 133 + short_name = "F"; 134 + if (short_name) 135 + name_len += snprintf(buf + name_len, size - name_len, 136 + "_%s", short_name); 137 + return name_len; 37 138 } 38 139 39 140 /* ··· 153 40 * -1 for failures; 154 41 * -2 for lack of kernel support. 155 42 */ 156 - static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, 43 + static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, 157 44 perf_event__handler_t process, 158 45 struct machine *machine, 159 46 int fd, ··· 162 49 { 163 50 struct ksymbol_event *ksymbol_event = &event->ksymbol_event; 164 51 struct bpf_event *bpf_event = &event->bpf_event; 165 - u32 sub_prog_cnt, i, func_info_rec_size = 0; 166 - u8 (*prog_tags)[BPF_TAG_SIZE] = NULL; 167 - struct bpf_prog_info info = { .type = 0, }; 168 - u32 info_len = sizeof(info); 169 - void *func_infos = NULL; 170 - u64 *prog_addrs = NULL; 52 + struct bpf_prog_info_linear *info_linear; 53 + struct perf_tool *tool = session->tool; 54 + struct bpf_prog_info_node *info_node; 55 + struct bpf_prog_info *info; 171 56 struct btf *btf = NULL; 172 - u32 *prog_lens = NULL; 173 - bool has_btf = false; 174 - char errbuf[512]; 57 + struct perf_env *env; 58 + u32 sub_prog_cnt, i; 175 59 int err = 0; 60 + u64 arrays; 176 61 177 - /* Call bpf_obj_get_info_by_fd() to get sizes of arrays */ 178 - err = bpf_obj_get_info_by_fd(fd, &info, &info_len); 62 + /* 63 + * for perf-record and perf-report use header.env; 64 + * otherwise, use global perf_env. 65 + */ 66 + env = session->data ? &session->header.env : &perf_env; 179 67 180 - if (err) { 181 - pr_debug("%s: failed to get BPF program info: %s, aborting\n", 182 - __func__, str_error_r(errno, errbuf, sizeof(errbuf))); 68 + arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS; 69 + arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; 70 + arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; 71 + arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS; 72 + arrays |= 1UL << BPF_PROG_INFO_JITED_INSNS; 73 + arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; 74 + arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO; 75 + 76 + info_linear = bpf_program__get_prog_info_linear(fd, arrays); 77 + if (IS_ERR_OR_NULL(info_linear)) { 78 + info_linear = NULL; 79 + pr_debug("%s: failed to get BPF program info. aborting\n", __func__); 183 80 return -1; 184 81 } 185 - if (info_len < offsetof(struct bpf_prog_info, prog_tags)) { 82 + 83 + if (info_linear->info_len < offsetof(struct bpf_prog_info, prog_tags)) { 186 84 pr_debug("%s: the kernel is too old, aborting\n", __func__); 187 85 return -2; 188 86 } 189 87 88 + info = &info_linear->info; 89 + 190 90 /* number of ksyms, func_lengths, and tags should match */ 191 - sub_prog_cnt = info.nr_jited_ksyms; 192 - if (sub_prog_cnt != info.nr_prog_tags || 193 - sub_prog_cnt != info.nr_jited_func_lens) 91 + sub_prog_cnt = info->nr_jited_ksyms; 92 + if (sub_prog_cnt != info->nr_prog_tags || 93 + sub_prog_cnt != info->nr_jited_func_lens) 194 94 return -1; 195 95 196 96 /* check BTF func info support */ 197 - if (info.btf_id && info.nr_func_info && info.func_info_rec_size) { 97 + if (info->btf_id && info->nr_func_info && info->func_info_rec_size) { 198 98 /* btf func info number should be same as sub_prog_cnt */ 199 - if (sub_prog_cnt != info.nr_func_info) { 99 + if (sub_prog_cnt != info->nr_func_info) { 200 100 pr_debug("%s: mismatch in BPF sub program count and BTF function info count, aborting\n", __func__); 201 - return -1; 101 + err = -1; 102 + goto out; 202 103 } 203 - if (btf__get_from_id(info.btf_id, &btf)) { 204 - pr_debug("%s: failed to get BTF of id %u, aborting\n", __func__, info.btf_id); 205 - return -1; 104 + if (btf__get_from_id(info->btf_id, &btf)) { 105 + pr_debug("%s: failed to get BTF of id %u, aborting\n", __func__, info->btf_id); 106 + err = -1; 107 + btf = NULL; 108 + goto out; 206 109 } 207 - func_info_rec_size = info.func_info_rec_size; 208 - func_infos = calloc(sub_prog_cnt, func_info_rec_size); 209 - if (!func_infos) { 210 - pr_debug("%s: failed to allocate memory for func_infos, aborting\n", __func__); 211 - return -1; 212 - } 213 - has_btf = true; 214 - } 215 - 216 - /* 217 - * We need address, length, and tag for each sub program. 218 - * Allocate memory and call bpf_obj_get_info_by_fd() again 219 - */ 220 - prog_addrs = calloc(sub_prog_cnt, sizeof(u64)); 221 - if (!prog_addrs) { 222 - pr_debug("%s: failed to allocate memory for prog_addrs, aborting\n", __func__); 223 - goto out; 224 - } 225 - prog_lens = calloc(sub_prog_cnt, sizeof(u32)); 226 - if (!prog_lens) { 227 - pr_debug("%s: failed to allocate memory for prog_lens, aborting\n", __func__); 228 - goto out; 229 - } 230 - prog_tags = calloc(sub_prog_cnt, BPF_TAG_SIZE); 231 - if (!prog_tags) { 232 - pr_debug("%s: failed to allocate memory for prog_tags, aborting\n", __func__); 233 - goto out; 234 - } 235 - 236 - memset(&info, 0, sizeof(info)); 237 - info.nr_jited_ksyms = sub_prog_cnt; 238 - info.nr_jited_func_lens = sub_prog_cnt; 239 - info.nr_prog_tags = sub_prog_cnt; 240 - info.jited_ksyms = ptr_to_u64(prog_addrs); 241 - info.jited_func_lens = ptr_to_u64(prog_lens); 242 - info.prog_tags = ptr_to_u64(prog_tags); 243 - info_len = sizeof(info); 244 - if (has_btf) { 245 - info.nr_func_info = sub_prog_cnt; 246 - info.func_info_rec_size = func_info_rec_size; 247 - info.func_info = ptr_to_u64(func_infos); 248 - } 249 - 250 - err = bpf_obj_get_info_by_fd(fd, &info, &info_len); 251 - if (err) { 252 - pr_debug("%s: failed to get BPF program info, aborting\n", __func__); 253 - goto out; 110 + perf_env__fetch_btf(env, info->btf_id, btf); 254 111 } 255 112 256 113 /* Synthesize PERF_RECORD_KSYMBOL */ 257 114 for (i = 0; i < sub_prog_cnt; i++) { 258 - const struct bpf_func_info *finfo; 259 - const char *short_name = NULL; 260 - const struct btf_type *t; 115 + __u32 *prog_lens = (__u32 *)(uintptr_t)(info->jited_func_lens); 116 + __u64 *prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms); 261 117 int name_len; 262 118 263 119 *ksymbol_event = (struct ksymbol_event){ ··· 239 157 .ksym_type = PERF_RECORD_KSYMBOL_TYPE_BPF, 240 158 .flags = 0, 241 159 }; 242 - name_len = snprintf(ksymbol_event->name, KSYM_NAME_LEN, 243 - "bpf_prog_"); 244 - name_len += snprintf_hex(ksymbol_event->name + name_len, 245 - KSYM_NAME_LEN - name_len, 246 - prog_tags[i], BPF_TAG_SIZE); 247 - if (has_btf) { 248 - finfo = func_infos + i * info.func_info_rec_size; 249 - t = btf__type_by_id(btf, finfo->type_id); 250 - short_name = btf__name_by_offset(btf, t->name_off); 251 - } else if (i == 0 && sub_prog_cnt == 1) { 252 - /* no subprog */ 253 - if (info.name[0]) 254 - short_name = info.name; 255 - } else 256 - short_name = "F"; 257 - if (short_name) 258 - name_len += snprintf(ksymbol_event->name + name_len, 259 - KSYM_NAME_LEN - name_len, 260 - "_%s", short_name); 261 160 161 + name_len = synthesize_bpf_prog_name(ksymbol_event->name, 162 + KSYM_NAME_LEN, info, btf, i); 262 163 ksymbol_event->header.size += PERF_ALIGN(name_len + 1, 263 164 sizeof(u64)); 264 165 ··· 251 186 machine, process); 252 187 } 253 188 254 - /* Synthesize PERF_RECORD_BPF_EVENT */ 255 - if (opts->bpf_event) { 189 + if (!opts->no_bpf_event) { 190 + /* Synthesize PERF_RECORD_BPF_EVENT */ 256 191 *bpf_event = (struct bpf_event){ 257 192 .header = { 258 193 .type = PERF_RECORD_BPF_EVENT, ··· 260 195 }, 261 196 .type = PERF_BPF_EVENT_PROG_LOAD, 262 197 .flags = 0, 263 - .id = info.id, 198 + .id = info->id, 264 199 }; 265 - memcpy(bpf_event->tag, prog_tags[i], BPF_TAG_SIZE); 200 + memcpy(bpf_event->tag, info->tag, BPF_TAG_SIZE); 266 201 memset((void *)event + event->header.size, 0, machine->id_hdr_size); 267 202 event->header.size += machine->id_hdr_size; 203 + 204 + /* save bpf_prog_info to env */ 205 + info_node = malloc(sizeof(struct bpf_prog_info_node)); 206 + if (!info_node) { 207 + err = -1; 208 + goto out; 209 + } 210 + 211 + info_node->info_linear = info_linear; 212 + perf_env__insert_bpf_prog_info(env, info_node); 213 + info_linear = NULL; 214 + 215 + /* 216 + * process after saving bpf_prog_info to env, so that 217 + * required information is ready for look up 218 + */ 268 219 err = perf_tool__process_synth_event(tool, event, 269 220 machine, process); 270 221 } 271 222 272 223 out: 273 - free(prog_tags); 274 - free(prog_lens); 275 - free(prog_addrs); 276 - free(func_infos); 224 + free(info_linear); 277 225 free(btf); 278 226 return err ? -1 : 0; 279 227 } 280 228 281 - int perf_event__synthesize_bpf_events(struct perf_tool *tool, 229 + int perf_event__synthesize_bpf_events(struct perf_session *session, 282 230 perf_event__handler_t process, 283 231 struct machine *machine, 284 232 struct record_opts *opts) ··· 325 247 continue; 326 248 } 327 249 328 - err = perf_event__synthesize_one_bpf_prog(tool, process, 250 + err = perf_event__synthesize_one_bpf_prog(session, process, 329 251 machine, fd, 330 252 event, opts); 331 253 close(fd); ··· 338 260 } 339 261 free(event); 340 262 return err; 263 + } 264 + 265 + static void perf_env__add_bpf_info(struct perf_env *env, u32 id) 266 + { 267 + struct bpf_prog_info_linear *info_linear; 268 + struct bpf_prog_info_node *info_node; 269 + struct btf *btf = NULL; 270 + u64 arrays; 271 + u32 btf_id; 272 + int fd; 273 + 274 + fd = bpf_prog_get_fd_by_id(id); 275 + if (fd < 0) 276 + return; 277 + 278 + arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS; 279 + arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; 280 + arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; 281 + arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS; 282 + arrays |= 1UL << BPF_PROG_INFO_JITED_INSNS; 283 + arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; 284 + arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO; 285 + 286 + info_linear = bpf_program__get_prog_info_linear(fd, arrays); 287 + if (IS_ERR_OR_NULL(info_linear)) { 288 + pr_debug("%s: failed to get BPF program info. aborting\n", __func__); 289 + goto out; 290 + } 291 + 292 + btf_id = info_linear->info.btf_id; 293 + 294 + info_node = malloc(sizeof(struct bpf_prog_info_node)); 295 + if (info_node) { 296 + info_node->info_linear = info_linear; 297 + perf_env__insert_bpf_prog_info(env, info_node); 298 + } else 299 + free(info_linear); 300 + 301 + if (btf_id == 0) 302 + goto out; 303 + 304 + if (btf__get_from_id(btf_id, &btf)) { 305 + pr_debug("%s: failed to get BTF of id %u, aborting\n", 306 + __func__, btf_id); 307 + goto out; 308 + } 309 + perf_env__fetch_btf(env, btf_id, btf); 310 + 311 + out: 312 + free(btf); 313 + close(fd); 314 + } 315 + 316 + static int bpf_event__sb_cb(union perf_event *event, void *data) 317 + { 318 + struct perf_env *env = data; 319 + 320 + if (event->header.type != PERF_RECORD_BPF_EVENT) 321 + return -1; 322 + 323 + switch (event->bpf_event.type) { 324 + case PERF_BPF_EVENT_PROG_LOAD: 325 + perf_env__add_bpf_info(env, event->bpf_event.id); 326 + 327 + case PERF_BPF_EVENT_PROG_UNLOAD: 328 + /* 329 + * Do not free bpf_prog_info and btf of the program here, 330 + * as annotation still need them. They will be freed at 331 + * the end of the session. 332 + */ 333 + break; 334 + default: 335 + pr_debug("unexpected bpf_event type of %d\n", 336 + event->bpf_event.type); 337 + break; 338 + } 339 + 340 + return 0; 341 + } 342 + 343 + int bpf_event__add_sb_event(struct perf_evlist **evlist, 344 + struct perf_env *env) 345 + { 346 + struct perf_event_attr attr = { 347 + .type = PERF_TYPE_SOFTWARE, 348 + .config = PERF_COUNT_SW_DUMMY, 349 + .sample_id_all = 1, 350 + .watermark = 1, 351 + .bpf_event = 1, 352 + .size = sizeof(attr), /* to capture ABI version */ 353 + }; 354 + 355 + /* 356 + * Older gcc versions don't support designated initializers, like above, 357 + * for unnamed union members, such as the following: 358 + */ 359 + attr.wakeup_watermark = 1; 360 + 361 + return perf_evlist__add_sb_event(evlist, &attr, bpf_event__sb_cb, env); 362 + } 363 + 364 + void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, 365 + struct perf_env *env, 366 + FILE *fp) 367 + { 368 + __u32 *prog_lens = (__u32 *)(uintptr_t)(info->jited_func_lens); 369 + __u64 *prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms); 370 + char name[KSYM_NAME_LEN]; 371 + struct btf *btf = NULL; 372 + u32 sub_prog_cnt, i; 373 + 374 + sub_prog_cnt = info->nr_jited_ksyms; 375 + if (sub_prog_cnt != info->nr_prog_tags || 376 + sub_prog_cnt != info->nr_jited_func_lens) 377 + return; 378 + 379 + if (info->btf_id) { 380 + struct btf_node *node; 381 + 382 + node = perf_env__find_btf(env, info->btf_id); 383 + if (node) 384 + btf = btf__new((__u8 *)(node->data), 385 + node->data_size); 386 + } 387 + 388 + if (sub_prog_cnt == 1) { 389 + synthesize_bpf_prog_name(name, KSYM_NAME_LEN, info, btf, 0); 390 + fprintf(fp, "# bpf_prog_info %u: %s addr 0x%llx size %u\n", 391 + info->id, name, prog_addrs[0], prog_lens[0]); 392 + return; 393 + } 394 + 395 + fprintf(fp, "# bpf_prog_info %u:\n", info->id); 396 + for (i = 0; i < sub_prog_cnt; i++) { 397 + synthesize_bpf_prog_name(name, KSYM_NAME_LEN, info, btf, i); 398 + 399 + fprintf(fp, "# \tsub_prog %u: %s addr 0x%llx size %u\n", 400 + i, name, prog_addrs[i], prog_lens[i]); 401 + } 341 402 }
+39 -3
tools/perf/util/bpf-event.h
··· 3 3 #define __PERF_BPF_EVENT_H 4 4 5 5 #include <linux/compiler.h> 6 + #include <linux/rbtree.h> 7 + #include <pthread.h> 8 + #include <api/fd/array.h> 6 9 #include "event.h" 10 + #include <stdio.h> 7 11 8 12 struct machine; 9 13 union perf_event; 14 + struct perf_env; 10 15 struct perf_sample; 11 - struct perf_tool; 12 16 struct record_opts; 17 + struct evlist; 18 + struct target; 19 + 20 + struct bpf_prog_info_node { 21 + struct bpf_prog_info_linear *info_linear; 22 + struct rb_node rb_node; 23 + }; 24 + 25 + struct btf_node { 26 + struct rb_node rb_node; 27 + u32 id; 28 + u32 data_size; 29 + char data[]; 30 + }; 13 31 14 32 #ifdef HAVE_LIBBPF_SUPPORT 15 33 int machine__process_bpf_event(struct machine *machine, union perf_event *event, 16 34 struct perf_sample *sample); 17 35 18 - int perf_event__synthesize_bpf_events(struct perf_tool *tool, 36 + int perf_event__synthesize_bpf_events(struct perf_session *session, 19 37 perf_event__handler_t process, 20 38 struct machine *machine, 21 39 struct record_opts *opts); 40 + int bpf_event__add_sb_event(struct perf_evlist **evlist, 41 + struct perf_env *env); 42 + void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, 43 + struct perf_env *env, 44 + FILE *fp); 22 45 #else 23 46 static inline int machine__process_bpf_event(struct machine *machine __maybe_unused, 24 47 union perf_event *event __maybe_unused, ··· 50 27 return 0; 51 28 } 52 29 53 - static inline int perf_event__synthesize_bpf_events(struct perf_tool *tool __maybe_unused, 30 + static inline int perf_event__synthesize_bpf_events(struct perf_session *session __maybe_unused, 54 31 perf_event__handler_t process __maybe_unused, 55 32 struct machine *machine __maybe_unused, 56 33 struct record_opts *opts __maybe_unused) 57 34 { 58 35 return 0; 36 + } 37 + 38 + static inline int bpf_event__add_sb_event(struct perf_evlist **evlist __maybe_unused, 39 + struct perf_env *env __maybe_unused) 40 + { 41 + return 0; 42 + } 43 + 44 + static inline void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info __maybe_unused, 45 + struct perf_env *env __maybe_unused, 46 + FILE *fp __maybe_unused) 47 + { 48 + 59 49 } 60 50 #endif // HAVE_LIBBPF_SUPPORT 61 51 #endif
+1
tools/perf/util/build-id.c
··· 185 185 return bf; 186 186 } 187 187 188 + /* The caller is responsible to free the returned buffer. */ 188 189 char *build_id_cache__origname(const char *sbuild_id) 189 190 { 190 191 char *linkname;
+1 -2
tools/perf/util/config.c
··· 633 633 } 634 634 635 635 ret = set_value(item, value); 636 - return ret; 637 636 638 637 out_free: 639 638 free(key); 640 - return -1; 639 + return ret; 641 640 } 642 641 643 642 int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
+98 -9
tools/perf/util/data.c
··· 14 14 #include "data.h" 15 15 #include "util.h" 16 16 #include "debug.h" 17 + #include "header.h" 17 18 18 19 static void close_dir(struct perf_data_file *files, int nr) 19 20 { ··· 35 34 struct perf_data_file *files = NULL; 36 35 int i, ret = -1; 37 36 37 + if (WARN_ON(!data->is_dir)) 38 + return -EINVAL; 39 + 38 40 files = zalloc(nr * sizeof(*files)); 39 41 if (!files) 40 42 return -ENOMEM; 41 43 42 - data->dir.files = files; 43 - data->dir.nr = nr; 44 + data->dir.version = PERF_DIR_VERSION; 45 + data->dir.files = files; 46 + data->dir.nr = nr; 44 47 45 48 for (i = 0; i < nr; i++) { 46 49 struct perf_data_file *file = &files[i]; ··· 73 68 int ret = -1; 74 69 DIR *dir; 75 70 int nr = 0; 71 + 72 + if (WARN_ON(!data->is_dir)) 73 + return -EINVAL; 74 + 75 + /* The version is provided by DIR_FORMAT feature. */ 76 + if (WARN_ON(data->dir.version != PERF_DIR_VERSION)) 77 + return -1; 76 78 77 79 dir = opendir(data->path); 78 80 if (!dir) ··· 128 116 out_err: 129 117 close_dir(files, nr); 130 118 return ret; 119 + } 120 + 121 + int perf_data__update_dir(struct perf_data *data) 122 + { 123 + int i; 124 + 125 + if (WARN_ON(!data->is_dir)) 126 + return -EINVAL; 127 + 128 + for (i = 0; i < data->dir.nr; i++) { 129 + struct perf_data_file *file = &data->dir.files[i]; 130 + struct stat st; 131 + 132 + if (fstat(file->fd, &st)) 133 + return -1; 134 + 135 + file->size = st.st_size; 136 + } 137 + 138 + return 0; 131 139 } 132 140 133 141 static bool check_pipe(struct perf_data *data) ··· 203 171 } 204 172 205 173 return 0; 174 + } 175 + 176 + static bool is_dir(struct perf_data *data) 177 + { 178 + struct stat st; 179 + 180 + if (stat(data->path, &st)) 181 + return false; 182 + 183 + return (st.st_mode & S_IFMT) == S_IFDIR; 206 184 } 207 185 208 186 static int open_file_read(struct perf_data *data) ··· 296 254 return open_file(data); 297 255 } 298 256 257 + static int open_dir(struct perf_data *data) 258 + { 259 + int ret; 260 + 261 + /* 262 + * So far we open only the header, so we can read the data version and 263 + * layout. 264 + */ 265 + if (asprintf(&data->file.path, "%s/header", data->path) < 0) 266 + return -1; 267 + 268 + if (perf_data__is_write(data) && 269 + mkdir(data->path, S_IRWXU) < 0) 270 + return -1; 271 + 272 + ret = open_file(data); 273 + 274 + /* Cleanup whatever we managed to create so far. */ 275 + if (ret && perf_data__is_write(data)) 276 + rm_rf_perf_data(data->path); 277 + 278 + return ret; 279 + } 280 + 299 281 int perf_data__open(struct perf_data *data) 300 282 { 301 283 if (check_pipe(data)) ··· 331 265 if (check_backup(data)) 332 266 return -1; 333 267 334 - return open_file_dup(data); 268 + if (perf_data__is_read(data)) 269 + data->is_dir = is_dir(data); 270 + 271 + return perf_data__is_dir(data) ? 272 + open_dir(data) : open_file_dup(data); 335 273 } 336 274 337 275 void perf_data__close(struct perf_data *data) 338 276 { 277 + if (perf_data__is_dir(data)) 278 + perf_data__close_dir(data); 279 + 339 280 zfree(&data->file.path); 340 281 close(data->file.fd); 341 282 } ··· 361 288 362 289 int perf_data__switch(struct perf_data *data, 363 290 const char *postfix, 364 - size_t pos, bool at_exit) 291 + size_t pos, bool at_exit, 292 + char **new_filepath) 365 293 { 366 - char *new_filepath; 367 294 int ret; 368 295 369 296 if (check_pipe(data)) ··· 371 298 if (perf_data__is_read(data)) 372 299 return -EINVAL; 373 300 374 - if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0) 301 + if (asprintf(new_filepath, "%s.%s", data->path, postfix) < 0) 375 302 return -ENOMEM; 376 303 377 304 /* 378 305 * Only fire a warning, don't return error, continue fill 379 306 * original file. 380 307 */ 381 - if (rename(data->path, new_filepath)) 382 - pr_warning("Failed to rename %s to %s\n", data->path, new_filepath); 308 + if (rename(data->path, *new_filepath)) 309 + pr_warning("Failed to rename %s to %s\n", data->path, *new_filepath); 383 310 384 311 if (!at_exit) { 385 312 close(data->file.fd); ··· 396 323 } 397 324 ret = data->file.fd; 398 325 out: 399 - free(new_filepath); 400 326 return ret; 327 + } 328 + 329 + unsigned long perf_data__size(struct perf_data *data) 330 + { 331 + u64 size = data->file.size; 332 + int i; 333 + 334 + if (!data->is_dir) 335 + return size; 336 + 337 + for (i = 0; i < data->dir.nr; i++) { 338 + struct perf_data_file *file = &data->dir.files[i]; 339 + 340 + size += file->size; 341 + } 342 + 343 + return size; 401 344 }
+10 -6
tools/perf/util/data.h
··· 19 19 const char *path; 20 20 struct perf_data_file file; 21 21 bool is_pipe; 22 + bool is_dir; 22 23 bool force; 23 24 enum perf_data_mode mode; 24 25 25 26 struct { 27 + u64 version; 26 28 struct perf_data_file *files; 27 29 int nr; 28 30 } dir; ··· 45 43 return data->is_pipe; 46 44 } 47 45 46 + static inline bool perf_data__is_dir(struct perf_data *data) 47 + { 48 + return data->is_dir; 49 + } 50 + 48 51 static inline int perf_data__fd(struct perf_data *data) 49 52 { 50 53 return data->file.fd; 51 - } 52 - 53 - static inline unsigned long perf_data__size(struct perf_data *data) 54 - { 55 - return data->file.size; 56 54 } 57 55 58 56 int perf_data__open(struct perf_data *data); ··· 70 68 */ 71 69 int perf_data__switch(struct perf_data *data, 72 70 const char *postfix, 73 - size_t pos, bool at_exit); 71 + size_t pos, bool at_exit, char **new_filepath); 74 72 75 73 int perf_data__create_dir(struct perf_data *data, int nr); 76 74 int perf_data__open_dir(struct perf_data *data); 77 75 void perf_data__close_dir(struct perf_data *data); 76 + int perf_data__update_dir(struct perf_data *data); 77 + unsigned long perf_data__size(struct perf_data *data); 78 78 #endif /* __PERF_DATA_H */
+25 -18
tools/perf/util/dso.c
··· 184 184 case DSO_BINARY_TYPE__KALLSYMS: 185 185 case DSO_BINARY_TYPE__GUEST_KALLSYMS: 186 186 case DSO_BINARY_TYPE__JAVA_JIT: 187 + case DSO_BINARY_TYPE__BPF_PROG_INFO: 187 188 case DSO_BINARY_TYPE__NOT_FOUND: 188 189 ret = -1; 189 190 break; ··· 1142 1141 1143 1142 static void dso__set_basename(struct dso *dso) 1144 1143 { 1145 - /* 1146 - * basename() may modify path buffer, so we must pass 1147 - * a copy. 1148 - */ 1149 - char *base, *lname = strdup(dso->long_name); 1144 + char *base, *lname; 1145 + int tid; 1150 1146 1151 - if (!lname) 1152 - return; 1147 + if (sscanf(dso->long_name, "/tmp/perf-%d.map", &tid) == 1) { 1148 + if (asprintf(&base, "[JIT] tid %d", tid) < 0) 1149 + return; 1150 + } else { 1151 + /* 1152 + * basename() may modify path buffer, so we must pass 1153 + * a copy. 1154 + */ 1155 + lname = strdup(dso->long_name); 1156 + if (!lname) 1157 + return; 1153 1158 1154 - /* 1155 - * basename() may return a pointer to internal 1156 - * storage which is reused in subsequent calls 1157 - * so copy the result. 1158 - */ 1159 - base = strdup(basename(lname)); 1159 + /* 1160 + * basename() may return a pointer to internal 1161 + * storage which is reused in subsequent calls 1162 + * so copy the result. 1163 + */ 1164 + base = strdup(basename(lname)); 1160 1165 1161 - free(lname); 1166 + free(lname); 1162 1167 1163 - if (!base) 1164 - return; 1165 - 1166 - dso__set_short_name(dso, base, true); 1168 + if (!base) 1169 + return; 1170 + } 1171 + dso__set_short_name(dso, base, true); 1167 1172 } 1168 1173 1169 1174 int dso__name_len(const struct dso *dso)
+8
tools/perf/util/dso.h
··· 14 14 15 15 struct machine; 16 16 struct map; 17 + struct perf_env; 17 18 18 19 enum dso_binary_type { 19 20 DSO_BINARY_TYPE__KALLSYMS = 0, ··· 36 35 DSO_BINARY_TYPE__KCORE, 37 36 DSO_BINARY_TYPE__GUEST_KCORE, 38 37 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 38 + DSO_BINARY_TYPE__BPF_PROG_INFO, 39 39 DSO_BINARY_TYPE__NOT_FOUND, 40 40 }; 41 41 ··· 191 189 u64 debug_frame_offset; 192 190 u64 eh_frame_hdr_offset; 193 191 } data; 192 + /* bpf prog information */ 193 + struct { 194 + u32 id; 195 + u32 sub_id; 196 + struct perf_env *env; 197 + } bpf_prog; 194 198 195 199 union { /* Tool specific area */ 196 200 void *priv;
+155
tools/perf/util/env.c
··· 3 3 #include "env.h" 4 4 #include "sane_ctype.h" 5 5 #include "util.h" 6 + #include "bpf-event.h" 6 7 #include <errno.h> 7 8 #include <sys/utsname.h> 9 + #include <bpf/libbpf.h> 8 10 9 11 struct perf_env perf_env; 12 + 13 + void perf_env__insert_bpf_prog_info(struct perf_env *env, 14 + struct bpf_prog_info_node *info_node) 15 + { 16 + __u32 prog_id = info_node->info_linear->info.id; 17 + struct bpf_prog_info_node *node; 18 + struct rb_node *parent = NULL; 19 + struct rb_node **p; 20 + 21 + down_write(&env->bpf_progs.lock); 22 + p = &env->bpf_progs.infos.rb_node; 23 + 24 + while (*p != NULL) { 25 + parent = *p; 26 + node = rb_entry(parent, struct bpf_prog_info_node, rb_node); 27 + if (prog_id < node->info_linear->info.id) { 28 + p = &(*p)->rb_left; 29 + } else if (prog_id > node->info_linear->info.id) { 30 + p = &(*p)->rb_right; 31 + } else { 32 + pr_debug("duplicated bpf prog info %u\n", prog_id); 33 + goto out; 34 + } 35 + } 36 + 37 + rb_link_node(&info_node->rb_node, parent, p); 38 + rb_insert_color(&info_node->rb_node, &env->bpf_progs.infos); 39 + env->bpf_progs.infos_cnt++; 40 + out: 41 + up_write(&env->bpf_progs.lock); 42 + } 43 + 44 + struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, 45 + __u32 prog_id) 46 + { 47 + struct bpf_prog_info_node *node = NULL; 48 + struct rb_node *n; 49 + 50 + down_read(&env->bpf_progs.lock); 51 + n = env->bpf_progs.infos.rb_node; 52 + 53 + while (n) { 54 + node = rb_entry(n, struct bpf_prog_info_node, rb_node); 55 + if (prog_id < node->info_linear->info.id) 56 + n = n->rb_left; 57 + else if (prog_id > node->info_linear->info.id) 58 + n = n->rb_right; 59 + else 60 + break; 61 + } 62 + 63 + up_read(&env->bpf_progs.lock); 64 + return node; 65 + } 66 + 67 + void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) 68 + { 69 + struct rb_node *parent = NULL; 70 + __u32 btf_id = btf_node->id; 71 + struct btf_node *node; 72 + struct rb_node **p; 73 + 74 + down_write(&env->bpf_progs.lock); 75 + p = &env->bpf_progs.btfs.rb_node; 76 + 77 + while (*p != NULL) { 78 + parent = *p; 79 + node = rb_entry(parent, struct btf_node, rb_node); 80 + if (btf_id < node->id) { 81 + p = &(*p)->rb_left; 82 + } else if (btf_id > node->id) { 83 + p = &(*p)->rb_right; 84 + } else { 85 + pr_debug("duplicated btf %u\n", btf_id); 86 + goto out; 87 + } 88 + } 89 + 90 + rb_link_node(&btf_node->rb_node, parent, p); 91 + rb_insert_color(&btf_node->rb_node, &env->bpf_progs.btfs); 92 + env->bpf_progs.btfs_cnt++; 93 + out: 94 + up_write(&env->bpf_progs.lock); 95 + } 96 + 97 + struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id) 98 + { 99 + struct btf_node *node = NULL; 100 + struct rb_node *n; 101 + 102 + down_read(&env->bpf_progs.lock); 103 + n = env->bpf_progs.btfs.rb_node; 104 + 105 + while (n) { 106 + node = rb_entry(n, struct btf_node, rb_node); 107 + if (btf_id < node->id) 108 + n = n->rb_left; 109 + else if (btf_id > node->id) 110 + n = n->rb_right; 111 + else 112 + break; 113 + } 114 + 115 + up_read(&env->bpf_progs.lock); 116 + return node; 117 + } 118 + 119 + /* purge data in bpf_progs.infos tree */ 120 + static void perf_env__purge_bpf(struct perf_env *env) 121 + { 122 + struct rb_root *root; 123 + struct rb_node *next; 124 + 125 + down_write(&env->bpf_progs.lock); 126 + 127 + root = &env->bpf_progs.infos; 128 + next = rb_first(root); 129 + 130 + while (next) { 131 + struct bpf_prog_info_node *node; 132 + 133 + node = rb_entry(next, struct bpf_prog_info_node, rb_node); 134 + next = rb_next(&node->rb_node); 135 + rb_erase(&node->rb_node, root); 136 + free(node); 137 + } 138 + 139 + env->bpf_progs.infos_cnt = 0; 140 + 141 + root = &env->bpf_progs.btfs; 142 + next = rb_first(root); 143 + 144 + while (next) { 145 + struct btf_node *node; 146 + 147 + node = rb_entry(next, struct btf_node, rb_node); 148 + next = rb_next(&node->rb_node); 149 + rb_erase(&node->rb_node, root); 150 + free(node); 151 + } 152 + 153 + env->bpf_progs.btfs_cnt = 0; 154 + 155 + up_write(&env->bpf_progs.lock); 156 + } 10 157 11 158 void perf_env__exit(struct perf_env *env) 12 159 { 13 160 int i; 14 161 162 + perf_env__purge_bpf(env); 15 163 zfree(&env->hostname); 16 164 zfree(&env->os_release); 17 165 zfree(&env->version); ··· 184 36 for (i = 0; i < env->nr_memory_nodes; i++) 185 37 free(env->memory_nodes[i].set); 186 38 zfree(&env->memory_nodes); 39 + } 40 + 41 + void perf_env__init(struct perf_env *env) 42 + { 43 + env->bpf_progs.infos = RB_ROOT; 44 + env->bpf_progs.btfs = RB_ROOT; 45 + init_rwsem(&env->bpf_progs.lock); 187 46 } 188 47 189 48 int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
+24
tools/perf/util/env.h
··· 3 3 #define __PERF_ENV_H 4 4 5 5 #include <linux/types.h> 6 + #include <linux/rbtree.h> 6 7 #include "cpumap.h" 8 + #include "rwsem.h" 7 9 8 10 struct cpu_topology_map { 9 11 int socket_id; ··· 66 64 struct memory_node *memory_nodes; 67 65 unsigned long long memory_bsize; 68 66 u64 clockid_res_ns; 67 + 68 + /* 69 + * bpf_info_lock protects bpf rbtrees. This is needed because the 70 + * trees are accessed by different threads in perf-top 71 + */ 72 + struct { 73 + struct rw_semaphore lock; 74 + struct rb_root infos; 75 + u32 infos_cnt; 76 + struct rb_root btfs; 77 + u32 btfs_cnt; 78 + } bpf_progs; 69 79 }; 80 + 81 + struct bpf_prog_info_node; 82 + struct btf_node; 70 83 71 84 extern struct perf_env perf_env; 72 85 ··· 97 80 const char *perf_env__raw_arch(struct perf_env *env); 98 81 int perf_env__nr_cpus_avail(struct perf_env *env); 99 82 83 + void perf_env__init(struct perf_env *env); 84 + void perf_env__insert_bpf_prog_info(struct perf_env *env, 85 + struct bpf_prog_info_node *info_node); 86 + struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, 87 + __u32 prog_id); 88 + void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); 89 + struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id); 100 90 #endif /* __PERF_ENV_H */
+119
tools/perf/util/evlist.c
··· 19 19 #include "debug.h" 20 20 #include "units.h" 21 21 #include "asm/bug.h" 22 + #include "bpf-event.h" 22 23 #include <signal.h> 23 24 #include <unistd.h> 24 25 ··· 1856 1855 } 1857 1856 } 1858 1857 return leader; 1858 + } 1859 + 1860 + int perf_evlist__add_sb_event(struct perf_evlist **evlist, 1861 + struct perf_event_attr *attr, 1862 + perf_evsel__sb_cb_t cb, 1863 + void *data) 1864 + { 1865 + struct perf_evsel *evsel; 1866 + bool new_evlist = (*evlist) == NULL; 1867 + 1868 + if (*evlist == NULL) 1869 + *evlist = perf_evlist__new(); 1870 + if (*evlist == NULL) 1871 + return -1; 1872 + 1873 + if (!attr->sample_id_all) { 1874 + pr_warning("enabling sample_id_all for all side band events\n"); 1875 + attr->sample_id_all = 1; 1876 + } 1877 + 1878 + evsel = perf_evsel__new_idx(attr, (*evlist)->nr_entries); 1879 + if (!evsel) 1880 + goto out_err; 1881 + 1882 + evsel->side_band.cb = cb; 1883 + evsel->side_band.data = data; 1884 + perf_evlist__add(*evlist, evsel); 1885 + return 0; 1886 + 1887 + out_err: 1888 + if (new_evlist) { 1889 + perf_evlist__delete(*evlist); 1890 + *evlist = NULL; 1891 + } 1892 + return -1; 1893 + } 1894 + 1895 + static void *perf_evlist__poll_thread(void *arg) 1896 + { 1897 + struct perf_evlist *evlist = arg; 1898 + bool draining = false; 1899 + int i; 1900 + 1901 + while (draining || !(evlist->thread.done)) { 1902 + if (draining) 1903 + draining = false; 1904 + else if (evlist->thread.done) 1905 + draining = true; 1906 + 1907 + if (!draining) 1908 + perf_evlist__poll(evlist, 1000); 1909 + 1910 + for (i = 0; i < evlist->nr_mmaps; i++) { 1911 + struct perf_mmap *map = &evlist->mmap[i]; 1912 + union perf_event *event; 1913 + 1914 + if (perf_mmap__read_init(map)) 1915 + continue; 1916 + while ((event = perf_mmap__read_event(map)) != NULL) { 1917 + struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); 1918 + 1919 + if (evsel && evsel->side_band.cb) 1920 + evsel->side_band.cb(event, evsel->side_band.data); 1921 + else 1922 + pr_warning("cannot locate proper evsel for the side band event\n"); 1923 + 1924 + perf_mmap__consume(map); 1925 + } 1926 + perf_mmap__read_done(map); 1927 + } 1928 + } 1929 + return NULL; 1930 + } 1931 + 1932 + int perf_evlist__start_sb_thread(struct perf_evlist *evlist, 1933 + struct target *target) 1934 + { 1935 + struct perf_evsel *counter; 1936 + 1937 + if (!evlist) 1938 + return 0; 1939 + 1940 + if (perf_evlist__create_maps(evlist, target)) 1941 + goto out_delete_evlist; 1942 + 1943 + evlist__for_each_entry(evlist, counter) { 1944 + if (perf_evsel__open(counter, evlist->cpus, 1945 + evlist->threads) < 0) 1946 + goto out_delete_evlist; 1947 + } 1948 + 1949 + if (perf_evlist__mmap(evlist, UINT_MAX)) 1950 + goto out_delete_evlist; 1951 + 1952 + evlist__for_each_entry(evlist, counter) { 1953 + if (perf_evsel__enable(counter)) 1954 + goto out_delete_evlist; 1955 + } 1956 + 1957 + evlist->thread.done = 0; 1958 + if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist)) 1959 + goto out_delete_evlist; 1960 + 1961 + return 0; 1962 + 1963 + out_delete_evlist: 1964 + perf_evlist__delete(evlist); 1965 + evlist = NULL; 1966 + return -1; 1967 + } 1968 + 1969 + void perf_evlist__stop_sb_thread(struct perf_evlist *evlist) 1970 + { 1971 + if (!evlist) 1972 + return; 1973 + evlist->thread.done = 1; 1974 + pthread_join(evlist->thread.th, NULL); 1975 + perf_evlist__delete(evlist); 1859 1976 }
+12
tools/perf/util/evlist.h
··· 54 54 struct perf_sample *sample); 55 55 u64 first_sample_time; 56 56 u64 last_sample_time; 57 + struct { 58 + pthread_t th; 59 + volatile int done; 60 + } thread; 57 61 }; 58 62 59 63 struct perf_evsel_str_handler { ··· 90 86 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) 91 87 92 88 int perf_evlist__add_dummy(struct perf_evlist *evlist); 89 + 90 + int perf_evlist__add_sb_event(struct perf_evlist **evlist, 91 + struct perf_event_attr *attr, 92 + perf_evsel__sb_cb_t cb, 93 + void *data); 94 + int perf_evlist__start_sb_thread(struct perf_evlist *evlist, 95 + struct target *target); 96 + void perf_evlist__stop_sb_thread(struct perf_evlist *evlist); 93 97 94 98 int perf_evlist__add_newtp(struct perf_evlist *evlist, 95 99 const char *sys, const char *name, void *handler);
+4 -4
tools/perf/util/evsel.c
··· 1036 1036 attr->mmap2 = track && !perf_missing_features.mmap2; 1037 1037 attr->comm = track; 1038 1038 attr->ksymbol = track && !perf_missing_features.ksymbol; 1039 - attr->bpf_event = track && opts->bpf_event && 1039 + attr->bpf_event = track && !opts->no_bpf_event && 1040 1040 !perf_missing_features.bpf_event; 1041 1041 1042 1042 if (opts->record_namespaces) ··· 1292 1292 { 1293 1293 assert(list_empty(&evsel->node)); 1294 1294 assert(evsel->evlist == NULL); 1295 + perf_evsel__free_counts(evsel); 1295 1296 perf_evsel__free_fd(evsel); 1296 1297 perf_evsel__free_id(evsel); 1297 1298 perf_evsel__free_config_terms(evsel); ··· 1343 1342 count->val = 0; 1344 1343 } else if (count->run < count->ena) { 1345 1344 scaled = 1; 1346 - count->val = (u64)((double) count->val * count->ena / count->run + 0.5); 1345 + count->val = (u64)((double) count->val * count->ena / count->run); 1347 1346 } 1348 - } else 1349 - count->ena = count->run = 0; 1347 + } 1350 1348 1351 1349 if (pscaled) 1352 1350 *pscaled = scaled;
+6
tools/perf/util/evsel.h
··· 73 73 74 74 struct perf_stat_evsel; 75 75 76 + typedef int (perf_evsel__sb_cb_t)(union perf_event *event, void *data); 77 + 76 78 /** struct perf_evsel - event selector 77 79 * 78 80 * @evlist - evlist this evsel is in, if it is in one. ··· 153 151 bool collect_stat; 154 152 bool weak_group; 155 153 const char *pmu_name; 154 + struct { 155 + perf_evsel__sb_cb_t *cb; 156 + void *data; 157 + } side_band; 156 158 }; 157 159 158 160 union u64_swap {
+294 -1
tools/perf/util/header.c
··· 18 18 #include <sys/utsname.h> 19 19 #include <linux/time64.h> 20 20 #include <dirent.h> 21 + #include <bpf/libbpf.h> 21 22 22 23 #include "evlist.h" 23 24 #include "evsel.h" ··· 41 40 #include "time-utils.h" 42 41 #include "units.h" 43 42 #include "cputopo.h" 43 + #include "bpf-event.h" 44 44 45 45 #include "sane_ctype.h" 46 46 ··· 863 861 sizeof(ff->ph->env.clockid_res_ns)); 864 862 } 865 863 864 + static int write_dir_format(struct feat_fd *ff, 865 + struct perf_evlist *evlist __maybe_unused) 866 + { 867 + struct perf_session *session; 868 + struct perf_data *data; 869 + 870 + session = container_of(ff->ph, struct perf_session, header); 871 + data = session->data; 872 + 873 + if (WARN_ON(!perf_data__is_dir(data))) 874 + return -1; 875 + 876 + return do_write(ff, &data->dir.version, sizeof(data->dir.version)); 877 + } 878 + 879 + #ifdef HAVE_LIBBPF_SUPPORT 880 + static int write_bpf_prog_info(struct feat_fd *ff, 881 + struct perf_evlist *evlist __maybe_unused) 882 + { 883 + struct perf_env *env = &ff->ph->env; 884 + struct rb_root *root; 885 + struct rb_node *next; 886 + int ret; 887 + 888 + down_read(&env->bpf_progs.lock); 889 + 890 + ret = do_write(ff, &env->bpf_progs.infos_cnt, 891 + sizeof(env->bpf_progs.infos_cnt)); 892 + if (ret < 0) 893 + goto out; 894 + 895 + root = &env->bpf_progs.infos; 896 + next = rb_first(root); 897 + while (next) { 898 + struct bpf_prog_info_node *node; 899 + size_t len; 900 + 901 + node = rb_entry(next, struct bpf_prog_info_node, rb_node); 902 + next = rb_next(&node->rb_node); 903 + len = sizeof(struct bpf_prog_info_linear) + 904 + node->info_linear->data_len; 905 + 906 + /* before writing to file, translate address to offset */ 907 + bpf_program__bpil_addr_to_offs(node->info_linear); 908 + ret = do_write(ff, node->info_linear, len); 909 + /* 910 + * translate back to address even when do_write() fails, 911 + * so that this function never changes the data. 912 + */ 913 + bpf_program__bpil_offs_to_addr(node->info_linear); 914 + if (ret < 0) 915 + goto out; 916 + } 917 + out: 918 + up_read(&env->bpf_progs.lock); 919 + return ret; 920 + } 921 + #else // HAVE_LIBBPF_SUPPORT 922 + static int write_bpf_prog_info(struct feat_fd *ff __maybe_unused, 923 + struct perf_evlist *evlist __maybe_unused) 924 + { 925 + return 0; 926 + } 927 + #endif // HAVE_LIBBPF_SUPPORT 928 + 929 + static int write_bpf_btf(struct feat_fd *ff, 930 + struct perf_evlist *evlist __maybe_unused) 931 + { 932 + struct perf_env *env = &ff->ph->env; 933 + struct rb_root *root; 934 + struct rb_node *next; 935 + int ret; 936 + 937 + down_read(&env->bpf_progs.lock); 938 + 939 + ret = do_write(ff, &env->bpf_progs.btfs_cnt, 940 + sizeof(env->bpf_progs.btfs_cnt)); 941 + 942 + if (ret < 0) 943 + goto out; 944 + 945 + root = &env->bpf_progs.btfs; 946 + next = rb_first(root); 947 + while (next) { 948 + struct btf_node *node; 949 + 950 + node = rb_entry(next, struct btf_node, rb_node); 951 + next = rb_next(&node->rb_node); 952 + ret = do_write(ff, &node->id, 953 + sizeof(u32) * 2 + node->data_size); 954 + if (ret < 0) 955 + goto out; 956 + } 957 + out: 958 + up_read(&env->bpf_progs.lock); 959 + return ret; 960 + } 961 + 866 962 static int cpu_cache_level__sort(const void *a, const void *b) 867 963 { 868 964 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a; ··· 1439 1339 { 1440 1340 fprintf(fp, "# clockid frequency: %"PRIu64" MHz\n", 1441 1341 ff->ph->env.clockid_res_ns * 1000); 1342 + } 1343 + 1344 + static void print_dir_format(struct feat_fd *ff, FILE *fp) 1345 + { 1346 + struct perf_session *session; 1347 + struct perf_data *data; 1348 + 1349 + session = container_of(ff->ph, struct perf_session, header); 1350 + data = session->data; 1351 + 1352 + fprintf(fp, "# directory data version : %"PRIu64"\n", data->dir.version); 1353 + } 1354 + 1355 + static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp) 1356 + { 1357 + struct perf_env *env = &ff->ph->env; 1358 + struct rb_root *root; 1359 + struct rb_node *next; 1360 + 1361 + down_read(&env->bpf_progs.lock); 1362 + 1363 + root = &env->bpf_progs.infos; 1364 + next = rb_first(root); 1365 + 1366 + while (next) { 1367 + struct bpf_prog_info_node *node; 1368 + 1369 + node = rb_entry(next, struct bpf_prog_info_node, rb_node); 1370 + next = rb_next(&node->rb_node); 1371 + 1372 + bpf_event__print_bpf_prog_info(&node->info_linear->info, 1373 + env, fp); 1374 + } 1375 + 1376 + up_read(&env->bpf_progs.lock); 1377 + } 1378 + 1379 + static void print_bpf_btf(struct feat_fd *ff, FILE *fp) 1380 + { 1381 + struct perf_env *env = &ff->ph->env; 1382 + struct rb_root *root; 1383 + struct rb_node *next; 1384 + 1385 + down_read(&env->bpf_progs.lock); 1386 + 1387 + root = &env->bpf_progs.btfs; 1388 + next = rb_first(root); 1389 + 1390 + while (next) { 1391 + struct btf_node *node; 1392 + 1393 + node = rb_entry(next, struct btf_node, rb_node); 1394 + next = rb_next(&node->rb_node); 1395 + fprintf(fp, "# btf info of id %u\n", node->id); 1396 + } 1397 + 1398 + up_read(&env->bpf_progs.lock); 1442 1399 } 1443 1400 1444 1401 static void free_event_desc(struct perf_evsel *events) ··· 2530 2373 return 0; 2531 2374 } 2532 2375 2376 + static int process_dir_format(struct feat_fd *ff, 2377 + void *_data __maybe_unused) 2378 + { 2379 + struct perf_session *session; 2380 + struct perf_data *data; 2381 + 2382 + session = container_of(ff->ph, struct perf_session, header); 2383 + data = session->data; 2384 + 2385 + if (WARN_ON(!perf_data__is_dir(data))) 2386 + return -1; 2387 + 2388 + return do_read_u64(ff, &data->dir.version); 2389 + } 2390 + 2391 + #ifdef HAVE_LIBBPF_SUPPORT 2392 + static int process_bpf_prog_info(struct feat_fd *ff, void *data __maybe_unused) 2393 + { 2394 + struct bpf_prog_info_linear *info_linear; 2395 + struct bpf_prog_info_node *info_node; 2396 + struct perf_env *env = &ff->ph->env; 2397 + u32 count, i; 2398 + int err = -1; 2399 + 2400 + if (ff->ph->needs_swap) { 2401 + pr_warning("interpreting bpf_prog_info from systems with endianity is not yet supported\n"); 2402 + return 0; 2403 + } 2404 + 2405 + if (do_read_u32(ff, &count)) 2406 + return -1; 2407 + 2408 + down_write(&env->bpf_progs.lock); 2409 + 2410 + for (i = 0; i < count; ++i) { 2411 + u32 info_len, data_len; 2412 + 2413 + info_linear = NULL; 2414 + info_node = NULL; 2415 + if (do_read_u32(ff, &info_len)) 2416 + goto out; 2417 + if (do_read_u32(ff, &data_len)) 2418 + goto out; 2419 + 2420 + if (info_len > sizeof(struct bpf_prog_info)) { 2421 + pr_warning("detected invalid bpf_prog_info\n"); 2422 + goto out; 2423 + } 2424 + 2425 + info_linear = malloc(sizeof(struct bpf_prog_info_linear) + 2426 + data_len); 2427 + if (!info_linear) 2428 + goto out; 2429 + info_linear->info_len = sizeof(struct bpf_prog_info); 2430 + info_linear->data_len = data_len; 2431 + if (do_read_u64(ff, (u64 *)(&info_linear->arrays))) 2432 + goto out; 2433 + if (__do_read(ff, &info_linear->info, info_len)) 2434 + goto out; 2435 + if (info_len < sizeof(struct bpf_prog_info)) 2436 + memset(((void *)(&info_linear->info)) + info_len, 0, 2437 + sizeof(struct bpf_prog_info) - info_len); 2438 + 2439 + if (__do_read(ff, info_linear->data, data_len)) 2440 + goto out; 2441 + 2442 + info_node = malloc(sizeof(struct bpf_prog_info_node)); 2443 + if (!info_node) 2444 + goto out; 2445 + 2446 + /* after reading from file, translate offset to address */ 2447 + bpf_program__bpil_offs_to_addr(info_linear); 2448 + info_node->info_linear = info_linear; 2449 + perf_env__insert_bpf_prog_info(env, info_node); 2450 + } 2451 + 2452 + return 0; 2453 + out: 2454 + free(info_linear); 2455 + free(info_node); 2456 + up_write(&env->bpf_progs.lock); 2457 + return err; 2458 + } 2459 + #else // HAVE_LIBBPF_SUPPORT 2460 + static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data __maybe_unused) 2461 + { 2462 + return 0; 2463 + } 2464 + #endif // HAVE_LIBBPF_SUPPORT 2465 + 2466 + static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused) 2467 + { 2468 + struct perf_env *env = &ff->ph->env; 2469 + u32 count, i; 2470 + 2471 + if (ff->ph->needs_swap) { 2472 + pr_warning("interpreting btf from systems with endianity is not yet supported\n"); 2473 + return 0; 2474 + } 2475 + 2476 + if (do_read_u32(ff, &count)) 2477 + return -1; 2478 + 2479 + down_write(&env->bpf_progs.lock); 2480 + 2481 + for (i = 0; i < count; ++i) { 2482 + struct btf_node *node; 2483 + u32 id, data_size; 2484 + 2485 + if (do_read_u32(ff, &id)) 2486 + return -1; 2487 + if (do_read_u32(ff, &data_size)) 2488 + return -1; 2489 + 2490 + node = malloc(sizeof(struct btf_node) + data_size); 2491 + if (!node) 2492 + return -1; 2493 + 2494 + node->id = id; 2495 + node->data_size = data_size; 2496 + 2497 + if (__do_read(ff, node->data, data_size)) { 2498 + free(node); 2499 + return -1; 2500 + } 2501 + 2502 + perf_env__insert_btf(env, node); 2503 + } 2504 + 2505 + up_write(&env->bpf_progs.lock); 2506 + return 0; 2507 + } 2508 + 2533 2509 struct feature_ops { 2534 2510 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); 2535 2511 void (*print)(struct feat_fd *ff, FILE *fp); ··· 2722 2432 FEAT_OPN(CACHE, cache, true), 2723 2433 FEAT_OPR(SAMPLE_TIME, sample_time, false), 2724 2434 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true), 2725 - FEAT_OPR(CLOCKID, clockid, false) 2435 + FEAT_OPR(CLOCKID, clockid, false), 2436 + FEAT_OPN(DIR_FORMAT, dir_format, false), 2437 + FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false), 2438 + FEAT_OPR(BPF_BTF, bpf_btf, false), 2726 2439 }; 2727 2440 2728 2441 struct header_print_data {
+7
tools/perf/util/header.h
··· 39 39 HEADER_SAMPLE_TIME, 40 40 HEADER_MEM_TOPOLOGY, 41 41 HEADER_CLOCKID, 42 + HEADER_DIR_FORMAT, 43 + HEADER_BPF_PROG_INFO, 44 + HEADER_BPF_BTF, 42 45 HEADER_LAST_FEATURE, 43 46 HEADER_FEAT_BITS = 256, 44 47 }; ··· 49 46 enum perf_header_version { 50 47 PERF_HEADER_VERSION_1, 51 48 PERF_HEADER_VERSION_2, 49 + }; 50 + 51 + enum perf_dir_version { 52 + PERF_DIR_VERSION = 1, 52 53 }; 53 54 54 55 struct perf_file_section {
+53 -1
tools/perf/util/hist.c
··· 19 19 #include <math.h> 20 20 #include <inttypes.h> 21 21 #include <sys/param.h> 22 + #include <linux/time64.h> 22 23 23 24 static bool hists__filter_entry_by_dso(struct hists *hists, 24 25 struct hist_entry *he); ··· 193 192 hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3); 194 193 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); 195 194 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); 195 + hists__new_col_len(hists, HISTC_TIME, 12); 196 196 197 197 if (h->srcline) { 198 198 len = MAX(strlen(h->srcline), strlen(sort_srcline.se_header)); ··· 246 244 default: 247 245 break; 248 246 } 247 + } 248 + 249 + static long hist_time(unsigned long htime) 250 + { 251 + unsigned long time_quantum = symbol_conf.time_quantum; 252 + if (time_quantum) 253 + return (htime / time_quantum) * time_quantum; 254 + return htime; 249 255 } 250 256 251 257 static void he_stat__add_period(struct he_stat *he_stat, u64 period, ··· 436 426 goto err_rawdata; 437 427 } 438 428 429 + if (symbol_conf.res_sample) { 430 + he->res_samples = calloc(sizeof(struct res_sample), 431 + symbol_conf.res_sample); 432 + if (!he->res_samples) 433 + goto err_srcline; 434 + } 435 + 439 436 INIT_LIST_HEAD(&he->pairs.node); 440 437 thread__get(he->thread); 441 438 he->hroot_in = RB_ROOT_CACHED; ··· 452 435 he->leaf = true; 453 436 454 437 return 0; 438 + 439 + err_srcline: 440 + free(he->srcline); 455 441 456 442 err_rawdata: 457 443 free(he->raw_data); ··· 613 593 return he; 614 594 } 615 595 596 + static unsigned random_max(unsigned high) 597 + { 598 + unsigned thresh = -high % high; 599 + for (;;) { 600 + unsigned r = random(); 601 + if (r >= thresh) 602 + return r % high; 603 + } 604 + } 605 + 606 + static void hists__res_sample(struct hist_entry *he, struct perf_sample *sample) 607 + { 608 + struct res_sample *r; 609 + int j; 610 + 611 + if (he->num_res < symbol_conf.res_sample) { 612 + j = he->num_res++; 613 + } else { 614 + j = random_max(symbol_conf.res_sample); 615 + } 616 + r = &he->res_samples[j]; 617 + r->time = sample->time; 618 + r->cpu = sample->cpu; 619 + r->tid = sample->tid; 620 + } 621 + 616 622 static struct hist_entry* 617 623 __hists__add_entry(struct hists *hists, 618 624 struct addr_location *al, ··· 681 635 .raw_data = sample->raw_data, 682 636 .raw_size = sample->raw_size, 683 637 .ops = ops, 638 + .time = hist_time(sample->time), 684 639 }, *he = hists__findnew_entry(hists, &entry, al, sample_self); 685 640 686 641 if (!hists->has_callchains && he && he->callchain_size != 0) 687 642 hists->has_callchains = true; 643 + if (he && symbol_conf.res_sample) 644 + hists__res_sample(he, sample); 688 645 return he; 689 646 } 690 647 ··· 1111 1062 1112 1063 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, 1113 1064 iter->evsel, al, max_stack_depth); 1114 - if (err) 1065 + if (err) { 1066 + map__put(alm); 1115 1067 return err; 1068 + } 1116 1069 1117 1070 err = iter->ops->prepare_entry(iter, al); 1118 1071 if (err) ··· 1213 1162 mem_info__zput(he->mem_info); 1214 1163 } 1215 1164 1165 + zfree(&he->res_samples); 1216 1166 zfree(&he->stat_acc); 1217 1167 free_srcline(he->srcline); 1218 1168 if (he->srcfile && he->srcfile[0])
+29 -2
tools/perf/util/hist.h
··· 31 31 32 32 enum hist_column { 33 33 HISTC_SYMBOL, 34 + HISTC_TIME, 34 35 HISTC_DSO, 35 36 HISTC_THREAD, 36 37 HISTC_COMM, ··· 433 432 }; 434 433 435 434 struct annotation_options; 435 + struct res_sample; 436 + 437 + enum rstype { 438 + A_NORMAL, 439 + A_ASM, 440 + A_SOURCE 441 + }; 436 442 437 443 #ifdef HAVE_SLANG_SUPPORT 438 444 #include "../ui/keysyms.h" 445 + void attr_to_script(char *buf, struct perf_event_attr *attr); 446 + 439 447 int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 440 448 struct hist_browser_timer *hbt, 441 449 struct annotation_options *annotation_opts); ··· 459 449 struct perf_env *env, 460 450 bool warn_lost_event, 461 451 struct annotation_options *annotation_options); 462 - int script_browse(const char *script_opt); 452 + 453 + int script_browse(const char *script_opt, struct perf_evsel *evsel); 454 + 455 + void run_script(char *cmd); 456 + int res_sample_browse(struct res_sample *res_samples, int num_res, 457 + struct perf_evsel *evsel, enum rstype rstype); 458 + void res_sample_init(void); 463 459 #else 464 460 static inline 465 461 int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, ··· 494 478 return 0; 495 479 } 496 480 497 - static inline int script_browse(const char *script_opt __maybe_unused) 481 + static inline int script_browse(const char *script_opt __maybe_unused, 482 + struct perf_evsel *evsel __maybe_unused) 498 483 { 499 484 return 0; 500 485 } 486 + 487 + static inline int res_sample_browse(struct res_sample *res_samples __maybe_unused, 488 + int num_res __maybe_unused, 489 + struct perf_evsel *evsel __maybe_unused, 490 + enum rstype rstype __maybe_unused) 491 + { 492 + return 0; 493 + } 494 + 495 + static inline void res_sample_init(void) {} 501 496 502 497 #define K_LEFT -1000 503 498 #define K_RIGHT -2000
+18
tools/perf/util/map.c
··· 577 577 } 578 578 } 579 579 580 + static void __maps__purge_names(struct maps *maps) 581 + { 582 + struct rb_root *root = &maps->names; 583 + struct rb_node *next = rb_first(root); 584 + 585 + while (next) { 586 + struct map *pos = rb_entry(next, struct map, rb_node_name); 587 + 588 + next = rb_next(&pos->rb_node_name); 589 + rb_erase_init(&pos->rb_node_name, root); 590 + map__put(pos); 591 + } 592 + } 593 + 580 594 static void maps__exit(struct maps *maps) 581 595 { 582 596 down_write(&maps->lock); 583 597 __maps__purge(maps); 598 + __maps__purge_names(maps); 584 599 up_write(&maps->lock); 585 600 } 586 601 ··· 931 916 static void __maps__remove(struct maps *maps, struct map *map) 932 917 { 933 918 rb_erase_init(&map->rb_node, &maps->entries); 919 + map__put(map); 920 + 921 + rb_erase_init(&map->rb_node_name, &maps->names); 934 922 map__put(map); 935 923 } 936 924
+2
tools/perf/util/ordered-events.c
··· 270 270 "FINAL", 271 271 "ROUND", 272 272 "HALF ", 273 + "TOP ", 274 + "TIME ", 273 275 }; 274 276 int err; 275 277 bool show_progress = false;
+2
tools/perf/util/parse-events.c
··· 2271 2271 perf_evsel__delete(evsel); 2272 2272 } 2273 2273 2274 + thread_map__put(tmap); 2274 2275 return ret; 2275 2276 } 2276 2277 ··· 2342 2341 printf(" %-50s [%s]\n", buf, "SDT event"); 2343 2342 free(buf); 2344 2343 } 2344 + free(path); 2345 2345 } else 2346 2346 printf(" %-50s [%s]\n", nd->s, "SDT event"); 2347 2347 if (nd2) {
+4 -2
tools/perf/util/probe-event.c
··· 160 160 if (module && strchr(module, '/')) 161 161 return dso__new_map(module); 162 162 163 - if (!module) 164 - module = "kernel"; 163 + if (!module) { 164 + pos = machine__kernel_map(host_machine); 165 + return map__get(pos); 166 + } 165 167 166 168 for (pos = maps__first(maps); pos; pos = map__next(pos)) { 167 169 /* short_name is "[module]" */
+24 -4
tools/perf/util/session.c
··· 132 132 ordered_events__init(&session->ordered_events, 133 133 ordered_events__deliver_event, NULL); 134 134 135 + perf_env__init(&session->header.env); 135 136 if (data) { 136 137 if (perf_data__open(data)) 137 138 goto out_delete; ··· 153 152 } 154 153 155 154 perf_evlist__init_trace_event_sample_raw(session->evlist); 155 + 156 + /* Open the directory data. */ 157 + if (data->is_dir && perf_data__open_dir(data)) 158 + goto out_delete; 156 159 } 157 160 } else { 158 161 session->machines.host.env = &perf_env; ··· 1848 1843 #define NUM_MMAPS 128 1849 1844 #endif 1850 1845 1846 + struct reader; 1847 + 1848 + typedef s64 (*reader_cb_t)(struct perf_session *session, 1849 + union perf_event *event, 1850 + u64 file_offset); 1851 + 1851 1852 struct reader { 1852 - int fd; 1853 - u64 data_size; 1854 - u64 data_offset; 1853 + int fd; 1854 + u64 data_size; 1855 + u64 data_offset; 1856 + reader_cb_t process; 1855 1857 }; 1856 1858 1857 1859 static int ··· 1929 1917 size = event->header.size; 1930 1918 1931 1919 if (size < sizeof(struct perf_event_header) || 1932 - (skip = perf_session__process_event(session, event, file_pos)) < 0) { 1920 + (skip = rd->process(session, event, file_pos)) < 0) { 1933 1921 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1934 1922 file_offset + head, event->header.size, 1935 1923 event->header.type); ··· 1955 1943 return err; 1956 1944 } 1957 1945 1946 + static s64 process_simple(struct perf_session *session, 1947 + union perf_event *event, 1948 + u64 file_offset) 1949 + { 1950 + return perf_session__process_event(session, event, file_offset); 1951 + } 1952 + 1958 1953 static int __perf_session__process_events(struct perf_session *session) 1959 1954 { 1960 1955 struct reader rd = { 1961 1956 .fd = perf_data__fd(session->data), 1962 1957 .data_size = session->header.data_size, 1963 1958 .data_offset = session->header.data_offset, 1959 + .process = process_simple, 1964 1960 }; 1965 1961 struct ordered_events *oe = &session->ordered_events; 1966 1962 struct perf_tool *tool = session->tool;
+91
tools/perf/util/sort.c
··· 3 3 #include <inttypes.h> 4 4 #include <regex.h> 5 5 #include <linux/mman.h> 6 + #include <linux/time64.h> 6 7 #include "sort.h" 7 8 #include "hist.h" 8 9 #include "comm.h" ··· 13 12 #include "evsel.h" 14 13 #include "evlist.h" 15 14 #include "strlist.h" 15 + #include "strbuf.h" 16 16 #include <traceevent/event-parse.h> 17 17 #include "mem-events.h" 18 18 #include "annotate.h" 19 + #include "time-utils.h" 19 20 #include <linux/kernel.h> 20 21 21 22 regex_t parent_regex; ··· 655 652 .se_snprintf = hist_entry__socket_snprintf, 656 653 .se_filter = hist_entry__socket_filter, 657 654 .se_width_idx = HISTC_SOCKET, 655 + }; 656 + 657 + /* --sort time */ 658 + 659 + static int64_t 660 + sort__time_cmp(struct hist_entry *left, struct hist_entry *right) 661 + { 662 + return right->time - left->time; 663 + } 664 + 665 + static int hist_entry__time_snprintf(struct hist_entry *he, char *bf, 666 + size_t size, unsigned int width) 667 + { 668 + unsigned long secs; 669 + unsigned long long nsecs; 670 + char he_time[32]; 671 + 672 + nsecs = he->time; 673 + secs = nsecs / NSEC_PER_SEC; 674 + nsecs -= secs * NSEC_PER_SEC; 675 + 676 + if (symbol_conf.nanosecs) 677 + snprintf(he_time, sizeof he_time, "%5lu.%09llu: ", 678 + secs, nsecs); 679 + else 680 + timestamp__scnprintf_usec(he->time, he_time, 681 + sizeof(he_time)); 682 + 683 + return repsep_snprintf(bf, size, "%-.*s", width, he_time); 684 + } 685 + 686 + struct sort_entry sort_time = { 687 + .se_header = "Time", 688 + .se_cmp = sort__time_cmp, 689 + .se_snprintf = hist_entry__time_snprintf, 690 + .se_width_idx = HISTC_TIME, 658 691 }; 659 692 660 693 /* --sort trace */ ··· 1673 1634 DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size), 1674 1635 DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), 1675 1636 DIM(SORT_SYM_IPC_NULL, "ipc_null", sort_sym_ipc_null), 1637 + DIM(SORT_TIME, "time", sort_time), 1676 1638 }; 1677 1639 1678 1640 #undef DIM ··· 3107 3067 3108 3068 reset_dimensions(); 3109 3069 perf_hpp__reset_output_field(&perf_hpp_list); 3070 + } 3071 + 3072 + #define INDENT (3*8 + 1) 3073 + 3074 + static void add_key(struct strbuf *sb, const char *str, int *llen) 3075 + { 3076 + if (*llen >= 75) { 3077 + strbuf_addstr(sb, "\n\t\t\t "); 3078 + *llen = INDENT; 3079 + } 3080 + strbuf_addf(sb, " %s", str); 3081 + *llen += strlen(str) + 1; 3082 + } 3083 + 3084 + static void add_sort_string(struct strbuf *sb, struct sort_dimension *s, int n, 3085 + int *llen) 3086 + { 3087 + int i; 3088 + 3089 + for (i = 0; i < n; i++) 3090 + add_key(sb, s[i].name, llen); 3091 + } 3092 + 3093 + static void add_hpp_sort_string(struct strbuf *sb, struct hpp_dimension *s, int n, 3094 + int *llen) 3095 + { 3096 + int i; 3097 + 3098 + for (i = 0; i < n; i++) 3099 + add_key(sb, s[i].name, llen); 3100 + } 3101 + 3102 + const char *sort_help(const char *prefix) 3103 + { 3104 + struct strbuf sb; 3105 + char *s; 3106 + int len = strlen(prefix) + INDENT; 3107 + 3108 + strbuf_init(&sb, 300); 3109 + strbuf_addstr(&sb, prefix); 3110 + add_hpp_sort_string(&sb, hpp_sort_dimensions, 3111 + ARRAY_SIZE(hpp_sort_dimensions), &len); 3112 + add_sort_string(&sb, common_sort_dimensions, 3113 + ARRAY_SIZE(common_sort_dimensions), &len); 3114 + add_sort_string(&sb, bstack_sort_dimensions, 3115 + ARRAY_SIZE(bstack_sort_dimensions), &len); 3116 + add_sort_string(&sb, memory_sort_dimensions, 3117 + ARRAY_SIZE(memory_sort_dimensions), &len); 3118 + s = strbuf_detach(&sb, NULL); 3119 + strbuf_release(&sb); 3120 + return s; 3110 3121 }
+12
tools/perf/util/sort.h
··· 47 47 extern enum sort_type sort__first_dimension; 48 48 extern const char default_mem_sort_order[]; 49 49 50 + struct res_sample { 51 + u64 time; 52 + int cpu; 53 + int tid; 54 + }; 55 + 50 56 struct he_stat { 51 57 u64 period; 52 58 u64 period_sys; ··· 141 135 char *srcfile; 142 136 struct symbol *parent; 143 137 struct branch_info *branch_info; 138 + long time; 144 139 struct hists *hists; 145 140 struct mem_info *mem_info; 146 141 void *raw_data; 147 142 u32 raw_size; 143 + int num_res; 144 + struct res_sample *res_samples; 148 145 void *trace_output; 149 146 struct perf_hpp_list *hpp_list; 150 147 struct hist_entry *parent_he; ··· 240 231 SORT_DSO_SIZE, 241 232 SORT_CGROUP_ID, 242 233 SORT_SYM_IPC_NULL, 234 + SORT_TIME, 243 235 244 236 /* branch stack specific sort keys */ 245 237 __SORT_BRANCH_STACK, ··· 295 285 void reset_output_field(void); 296 286 void sort__setup_elide(FILE *fp); 297 287 void perf_hpp__set_elide(int idx, bool elide); 288 + 289 + const char *sort_help(const char *prefix); 298 290 299 291 int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); 300 292
+4 -8
tools/perf/util/stat.c
··· 291 291 break; 292 292 case AGGR_GLOBAL: 293 293 aggr->val += count->val; 294 - if (config->scale) { 295 - aggr->ena += count->ena; 296 - aggr->run += count->run; 297 - } 294 + aggr->ena += count->ena; 295 + aggr->run += count->run; 298 296 case AGGR_UNSET: 299 297 default: 300 298 break; ··· 440 442 struct perf_event_attr *attr = &evsel->attr; 441 443 struct perf_evsel *leader = evsel->leader; 442 444 443 - if (config->scale) { 444 - attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 445 - PERF_FORMAT_TOTAL_TIME_RUNNING; 446 - } 445 + attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 446 + PERF_FORMAT_TOTAL_TIME_RUNNING; 447 447 448 448 /* 449 449 * The event is part of non trivial group, let's enable
+5
tools/perf/util/symbol.c
··· 6 6 #include <string.h> 7 7 #include <linux/kernel.h> 8 8 #include <linux/mman.h> 9 + #include <linux/time64.h> 9 10 #include <sys/types.h> 10 11 #include <sys/stat.h> 11 12 #include <sys/param.h> ··· 40 39 char **vmlinux_path; 41 40 42 41 struct symbol_conf symbol_conf = { 42 + .nanosecs = false, 43 43 .use_modules = true, 44 44 .try_vmlinux_path = true, 45 45 .demangle = true, 46 46 .demangle_kernel = false, 47 47 .cumulate_callchain = true, 48 + .time_quantum = 100 * NSEC_PER_MSEC, /* 100ms */ 48 49 .show_hist_headers = true, 49 50 .symfs = "", 50 51 .event_group = true, 51 52 .inline_name = true, 53 + .res_sample = 0, 52 54 }; 53 55 54 56 static enum dso_binary_type binary_type_symtab[] = { ··· 1455 1451 case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: 1456 1452 return true; 1457 1453 1454 + case DSO_BINARY_TYPE__BPF_PROG_INFO: 1458 1455 case DSO_BINARY_TYPE__NOT_FOUND: 1459 1456 default: 1460 1457 return false;
+3
tools/perf/util/symbol_conf.h
··· 8 8 struct intlist; 9 9 10 10 struct symbol_conf { 11 + bool nanosecs; 11 12 unsigned short priv_size; 12 13 bool try_vmlinux_path, 13 14 init_annotation, ··· 56 55 *sym_list_str, 57 56 *col_width_list_str, 58 57 *bt_stop_list_str; 58 + unsigned long time_quantum; 59 59 struct strlist *dso_list, 60 60 *comm_list, 61 61 *sym_list, ··· 68 66 struct intlist *pid_list, 69 67 *tid_list; 70 68 const char *symfs; 69 + int res_sample; 71 70 }; 72 71 73 72 extern struct symbol_conf symbol_conf;
+8
tools/perf/util/time-utils.c
··· 453 453 return scnprintf(buf, sz, "%"PRIu64".%06"PRIu64, sec, usec); 454 454 } 455 455 456 + int timestamp__scnprintf_nsec(u64 timestamp, char *buf, size_t sz) 457 + { 458 + u64 sec = timestamp / NSEC_PER_SEC, 459 + nsec = timestamp % NSEC_PER_SEC; 460 + 461 + return scnprintf(buf, sz, "%" PRIu64 ".%09" PRIu64, sec, nsec); 462 + } 463 + 456 464 int fetch_current_timestamp(char *buf, size_t sz) 457 465 { 458 466 struct timeval tv;
+1
tools/perf/util/time-utils.h
··· 30 30 int *range_size, int *range_num); 31 31 32 32 int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz); 33 + int timestamp__scnprintf_nsec(u64 timestamp, char *buf, size_t sz); 33 34 34 35 int fetch_current_timestamp(char *buf, size_t sz); 35 36