aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/bpf/bpftool/prog.c266
-rw-r--r--tools/build/Makefile.feature6
-rw-r--r--tools/build/feature/test-all.c5
-rw-r--r--tools/lib/bpf/libbpf.c253
-rw-r--r--tools/lib/bpf/libbpf.h63
-rw-r--r--tools/lib/bpf/libbpf.map3
-rw-r--r--tools/perf/Documentation/Build.txt24
-rw-r--r--tools/perf/Documentation/perf-config.txt2
-rw-r--r--tools/perf/Documentation/perf-record.txt4
-rw-r--r--tools/perf/Documentation/perf-script.txt3
-rw-r--r--tools/perf/Documentation/perf-stat.txt5
-rw-r--r--tools/perf/Makefile.config15
-rw-r--r--tools/perf/bench/epoll-ctl.c2
-rw-r--r--tools/perf/bench/epoll-wait.c2
-rw-r--r--tools/perf/builtin-list.c2
-rw-r--r--tools/perf/builtin-record.c50
-rw-r--r--tools/perf/builtin-report.c5
-rw-r--r--tools/perf/builtin-script.c18
-rw-r--r--tools/perf/builtin-stat.c3
-rw-r--r--tools/perf/builtin-top.c62
-rw-r--r--tools/perf/perf.c1
-rw-r--r--tools/perf/perf.h2
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/other.json594
-rw-r--r--tools/perf/tests/attr/test-record-C02
-rw-r--r--tools/perf/tests/attr/test-record-basic2
-rw-r--r--tools/perf/tests/attr/test-record-branch-any2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any_call2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any_ret2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-hv2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-ind_call2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-k2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-u2
-rw-r--r--tools/perf/tests/attr/test-record-count2
-rw-r--r--tools/perf/tests/attr/test-record-data2
-rw-r--r--tools/perf/tests/attr/test-record-freq2
-rw-r--r--tools/perf/tests/attr/test-record-graph-default2
-rw-r--r--tools/perf/tests/attr/test-record-graph-dwarf2
-rw-r--r--tools/perf/tests/attr/test-record-graph-fp2
-rw-r--r--tools/perf/tests/attr/test-record-group2
-rw-r--r--tools/perf/tests/attr/test-record-group-sampling2
-rw-r--r--tools/perf/tests/attr/test-record-group12
-rw-r--r--tools/perf/tests/attr/test-record-no-buffering2
-rw-r--r--tools/perf/tests/attr/test-record-no-inherit2
-rw-r--r--tools/perf/tests/attr/test-record-no-samples2
-rw-r--r--tools/perf/tests/attr/test-record-period2
-rw-r--r--tools/perf/tests/attr/test-record-raw2
-rw-r--r--tools/perf/tests/backward-ring-buffer.c2
-rw-r--r--tools/perf/tests/evsel-tp-sched.c1
-rw-r--r--tools/perf/tests/expr.c5
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c4
-rw-r--r--tools/perf/util/annotate.c163
-rw-r--r--tools/perf/util/annotate.h1
-rw-r--r--tools/perf/util/bpf-event.c425
-rw-r--r--tools/perf/util/bpf-event.h42
-rw-r--r--tools/perf/util/build-id.c1
-rw-r--r--tools/perf/util/config.c3
-rw-r--r--tools/perf/util/data.c11
-rw-r--r--tools/perf/util/data.h2
-rw-r--r--tools/perf/util/dso.c43
-rw-r--r--tools/perf/util/dso.h8
-rw-r--r--tools/perf/util/env.c155
-rw-r--r--tools/perf/util/env.h24
-rw-r--r--tools/perf/util/evlist.c119
-rw-r--r--tools/perf/util/evlist.h12
-rw-r--r--tools/perf/util/evsel.c8
-rw-r--r--tools/perf/util/evsel.h6
-rw-r--r--tools/perf/util/header.c253
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/hist.c4
-rw-r--r--tools/perf/util/map.c18
-rw-r--r--tools/perf/util/ordered-events.c2
-rw-r--r--tools/perf/util/parse-events.c2
-rw-r--r--tools/perf/util/session.c1
-rw-r--r--tools/perf/util/sort.c52
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/stat.c12
-rw-r--r--tools/perf/util/symbol.c1
78 files changed, 1794 insertions, 1028 deletions
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 8ef80d65a474..d2be5a06c339 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -401,41 +401,31 @@ static int do_show(int argc, char **argv)
401 401
402static int do_dump(int argc, char **argv) 402static int do_dump(int argc, char **argv)
403{ 403{
404 unsigned int finfo_rec_size, linfo_rec_size, jited_linfo_rec_size; 404 struct bpf_prog_info_linear *info_linear;
405 void *func_info = NULL, *linfo = NULL, *jited_linfo = NULL;
406 unsigned int nr_finfo, nr_linfo = 0, nr_jited_linfo = 0;
407 struct bpf_prog_linfo *prog_linfo = NULL; 405 struct bpf_prog_linfo *prog_linfo = NULL;
408 unsigned long *func_ksyms = NULL; 406 enum {DUMP_JITED, DUMP_XLATED} mode;
409 struct bpf_prog_info info = {};
410 unsigned int *func_lens = NULL;
411 const char *disasm_opt = NULL; 407 const char *disasm_opt = NULL;
412 unsigned int nr_func_ksyms; 408 struct bpf_prog_info *info;
413 unsigned int nr_func_lens;
414 struct dump_data dd = {}; 409 struct dump_data dd = {};
415 __u32 len = sizeof(info); 410 void *func_info = NULL;
416 struct btf *btf = NULL; 411 struct btf *btf = NULL;
417 unsigned int buf_size;
418 char *filepath = NULL; 412 char *filepath = NULL;
419 bool opcodes = false; 413 bool opcodes = false;
420 bool visual = false; 414 bool visual = false;
421 char func_sig[1024]; 415 char func_sig[1024];
422 unsigned char *buf; 416 unsigned char *buf;
423 bool linum = false; 417 bool linum = false;
424 __u32 *member_len; 418 __u32 member_len;
425 __u64 *member_ptr; 419 __u64 arrays;
426 ssize_t n; 420 ssize_t n;
427 int err;
428 int fd; 421 int fd;
429 422
430 if (is_prefix(*argv, "jited")) { 423 if (is_prefix(*argv, "jited")) {
431 if (disasm_init()) 424 if (disasm_init())
432 return -1; 425 return -1;
433 426 mode = DUMP_JITED;
434 member_len = &info.jited_prog_len;
435 member_ptr = &info.jited_prog_insns;
436 } else if (is_prefix(*argv, "xlated")) { 427 } else if (is_prefix(*argv, "xlated")) {
437 member_len = &info.xlated_prog_len; 428 mode = DUMP_XLATED;
438 member_ptr = &info.xlated_prog_insns;
439 } else { 429 } else {
440 p_err("expected 'xlated' or 'jited', got: %s", *argv); 430 p_err("expected 'xlated' or 'jited', got: %s", *argv);
441 return -1; 431 return -1;
@@ -474,175 +464,50 @@ static int do_dump(int argc, char **argv)
474 return -1; 464 return -1;
475 } 465 }
476 466
477 err = bpf_obj_get_info_by_fd(fd, &info, &len); 467 if (mode == DUMP_JITED)
478 if (err) { 468 arrays = 1UL << BPF_PROG_INFO_JITED_INSNS;
479 p_err("can't get prog info: %s", strerror(errno)); 469 else
480 return -1; 470 arrays = 1UL << BPF_PROG_INFO_XLATED_INSNS;
481 }
482
483 if (!*member_len) {
484 p_info("no instructions returned");
485 close(fd);
486 return 0;
487 }
488 471
489 buf_size = *member_len; 472 arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS;
473 arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS;
474 arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO;
475 arrays |= 1UL << BPF_PROG_INFO_LINE_INFO;
476 arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO;
490 477
491 buf = malloc(buf_size); 478 info_linear = bpf_program__get_prog_info_linear(fd, arrays);
492 if (!buf) { 479 close(fd);
493 p_err("mem alloc failed"); 480 if (IS_ERR_OR_NULL(info_linear)) {
494 close(fd); 481 p_err("can't get prog info: %s", strerror(errno));
495 return -1; 482 return -1;
496 } 483 }
497 484
498 nr_func_ksyms = info.nr_jited_ksyms; 485 info = &info_linear->info;
499 if (nr_func_ksyms) { 486 if (mode == DUMP_JITED) {
500 func_ksyms = malloc(nr_func_ksyms * sizeof(__u64)); 487 if (info->jited_prog_len == 0) {
501 if (!func_ksyms) { 488 p_info("no instructions returned");
502 p_err("mem alloc failed");
503 close(fd);
504 goto err_free;
505 }
506 }
507
508 nr_func_lens = info.nr_jited_func_lens;
509 if (nr_func_lens) {
510 func_lens = malloc(nr_func_lens * sizeof(__u32));
511 if (!func_lens) {
512 p_err("mem alloc failed");
513 close(fd);
514 goto err_free; 489 goto err_free;
515 } 490 }
516 } 491 buf = (unsigned char *)(info->jited_prog_insns);
517 492 member_len = info->jited_prog_len;
518 nr_finfo = info.nr_func_info; 493 } else { /* DUMP_XLATED */
519 finfo_rec_size = info.func_info_rec_size; 494 if (info->xlated_prog_len == 0) {
520 if (nr_finfo && finfo_rec_size) { 495 p_err("error retrieving insn dump: kernel.kptr_restrict set?");
521 func_info = malloc(nr_finfo * finfo_rec_size);
522 if (!func_info) {
523 p_err("mem alloc failed");
524 close(fd);
525 goto err_free; 496 goto err_free;
526 } 497 }
498 buf = (unsigned char *)info->xlated_prog_insns;
499 member_len = info->xlated_prog_len;
527 } 500 }
528 501
529 linfo_rec_size = info.line_info_rec_size; 502 if (info->btf_id && btf__get_from_id(info->btf_id, &btf)) {
530 if (info.nr_line_info && linfo_rec_size && info.btf_id) {
531 nr_linfo = info.nr_line_info;
532 linfo = malloc(nr_linfo * linfo_rec_size);
533 if (!linfo) {
534 p_err("mem alloc failed");
535 close(fd);
536 goto err_free;
537 }
538 }
539
540 jited_linfo_rec_size = info.jited_line_info_rec_size;
541 if (info.nr_jited_line_info &&
542 jited_linfo_rec_size &&
543 info.nr_jited_ksyms &&
544 info.nr_jited_func_lens &&
545 info.btf_id) {
546 nr_jited_linfo = info.nr_jited_line_info;
547 jited_linfo = malloc(nr_jited_linfo * jited_linfo_rec_size);
548 if (!jited_linfo) {
549 p_err("mem alloc failed");
550 close(fd);
551 goto err_free;
552 }
553 }
554
555 memset(&info, 0, sizeof(info));
556
557 *member_ptr = ptr_to_u64(buf);
558 *member_len = buf_size;
559 info.jited_ksyms = ptr_to_u64(func_ksyms);
560 info.nr_jited_ksyms = nr_func_ksyms;
561 info.jited_func_lens = ptr_to_u64(func_lens);
562 info.nr_jited_func_lens = nr_func_lens;
563 info.nr_func_info = nr_finfo;
564 info.func_info_rec_size = finfo_rec_size;
565 info.func_info = ptr_to_u64(func_info);
566 info.nr_line_info = nr_linfo;
567 info.line_info_rec_size = linfo_rec_size;
568 info.line_info = ptr_to_u64(linfo);
569 info.nr_jited_line_info = nr_jited_linfo;
570 info.jited_line_info_rec_size = jited_linfo_rec_size;
571 info.jited_line_info = ptr_to_u64(jited_linfo);
572
573 err = bpf_obj_get_info_by_fd(fd, &info, &len);
574 close(fd);
575 if (err) {
576 p_err("can't get prog info: %s", strerror(errno));
577 goto err_free;
578 }
579
580 if (*member_len > buf_size) {
581 p_err("too many instructions returned");
582 goto err_free;
583 }
584
585 if (info.nr_jited_ksyms > nr_func_ksyms) {
586 p_err("too many addresses returned");
587 goto err_free;
588 }
589
590 if (info.nr_jited_func_lens > nr_func_lens) {
591 p_err("too many values returned");
592 goto err_free;
593 }
594
595 if (info.nr_func_info != nr_finfo) {
596 p_err("incorrect nr_func_info %d vs. expected %d",
597 info.nr_func_info, nr_finfo);
598 goto err_free;
599 }
600
601 if (info.func_info_rec_size != finfo_rec_size) {
602 p_err("incorrect func_info_rec_size %d vs. expected %d",
603 info.func_info_rec_size, finfo_rec_size);
604 goto err_free;
605 }
606
607 if (linfo && info.nr_line_info != nr_linfo) {
608 p_err("incorrect nr_line_info %u vs. expected %u",
609 info.nr_line_info, nr_linfo);
610 goto err_free;
611 }
612
613 if (info.line_info_rec_size != linfo_rec_size) {
614 p_err("incorrect line_info_rec_size %u vs. expected %u",
615 info.line_info_rec_size, linfo_rec_size);
616 goto err_free;
617 }
618
619 if (jited_linfo && info.nr_jited_line_info != nr_jited_linfo) {
620 p_err("incorrect nr_jited_line_info %u vs. expected %u",
621 info.nr_jited_line_info, nr_jited_linfo);
622 goto err_free;
623 }
624
625 if (info.jited_line_info_rec_size != jited_linfo_rec_size) {
626 p_err("incorrect jited_line_info_rec_size %u vs. expected %u",
627 info.jited_line_info_rec_size, jited_linfo_rec_size);
628 goto err_free;
629 }
630
631 if ((member_len == &info.jited_prog_len &&
632 info.jited_prog_insns == 0) ||
633 (member_len == &info.xlated_prog_len &&
634 info.xlated_prog_insns == 0)) {
635 p_err("error retrieving insn dump: kernel.kptr_restrict set?");
636 goto err_free;
637 }
638
639 if (info.btf_id && btf__get_from_id(info.btf_id, &btf)) {
640 p_err("failed to get btf"); 503 p_err("failed to get btf");
641 goto err_free; 504 goto err_free;
642 } 505 }
643 506
644 if (nr_linfo) { 507 func_info = (void *)info->func_info;
645 prog_linfo = bpf_prog_linfo__new(&info); 508
509 if (info->nr_line_info) {
510 prog_linfo = bpf_prog_linfo__new(info);
646 if (!prog_linfo) 511 if (!prog_linfo)
647 p_info("error in processing bpf_line_info. continue without it."); 512 p_info("error in processing bpf_line_info. continue without it.");
648 } 513 }
@@ -655,9 +520,9 @@ static int do_dump(int argc, char **argv)
655 goto err_free; 520 goto err_free;
656 } 521 }
657 522
658 n = write(fd, buf, *member_len); 523 n = write(fd, buf, member_len);
659 close(fd); 524 close(fd);
660 if (n != *member_len) { 525 if (n != member_len) {
661 p_err("error writing output file: %s", 526 p_err("error writing output file: %s",
662 n < 0 ? strerror(errno) : "short write"); 527 n < 0 ? strerror(errno) : "short write");
663 goto err_free; 528 goto err_free;
@@ -665,19 +530,19 @@ static int do_dump(int argc, char **argv)
665 530
666 if (json_output) 531 if (json_output)
667 jsonw_null(json_wtr); 532 jsonw_null(json_wtr);
668 } else if (member_len == &info.jited_prog_len) { 533 } else if (mode == DUMP_JITED) {
669 const char *name = NULL; 534 const char *name = NULL;
670 535
671 if (info.ifindex) { 536 if (info->ifindex) {
672 name = ifindex_to_bfd_params(info.ifindex, 537 name = ifindex_to_bfd_params(info->ifindex,
673 info.netns_dev, 538 info->netns_dev,
674 info.netns_ino, 539 info->netns_ino,
675 &disasm_opt); 540 &disasm_opt);
676 if (!name) 541 if (!name)
677 goto err_free; 542 goto err_free;
678 } 543 }
679 544
680 if (info.nr_jited_func_lens && info.jited_func_lens) { 545 if (info->nr_jited_func_lens && info->jited_func_lens) {
681 struct kernel_sym *sym = NULL; 546 struct kernel_sym *sym = NULL;
682 struct bpf_func_info *record; 547 struct bpf_func_info *record;
683 char sym_name[SYM_MAX_NAME]; 548 char sym_name[SYM_MAX_NAME];
@@ -685,17 +550,16 @@ static int do_dump(int argc, char **argv)
685 __u64 *ksyms = NULL; 550 __u64 *ksyms = NULL;
686 __u32 *lens; 551 __u32 *lens;
687 __u32 i; 552 __u32 i;
688 553 if (info->nr_jited_ksyms) {
689 if (info.nr_jited_ksyms) {
690 kernel_syms_load(&dd); 554 kernel_syms_load(&dd);
691 ksyms = (__u64 *) info.jited_ksyms; 555 ksyms = (__u64 *) info->jited_ksyms;
692 } 556 }
693 557
694 if (json_output) 558 if (json_output)
695 jsonw_start_array(json_wtr); 559 jsonw_start_array(json_wtr);
696 560
697 lens = (__u32 *) info.jited_func_lens; 561 lens = (__u32 *) info->jited_func_lens;
698 for (i = 0; i < info.nr_jited_func_lens; i++) { 562 for (i = 0; i < info->nr_jited_func_lens; i++) {
699 if (ksyms) { 563 if (ksyms) {
700 sym = kernel_syms_search(&dd, ksyms[i]); 564 sym = kernel_syms_search(&dd, ksyms[i]);
701 if (sym) 565 if (sym)
@@ -707,7 +571,7 @@ static int do_dump(int argc, char **argv)
707 } 571 }
708 572
709 if (func_info) { 573 if (func_info) {
710 record = func_info + i * finfo_rec_size; 574 record = func_info + i * info->func_info_rec_size;
711 btf_dumper_type_only(btf, record->type_id, 575 btf_dumper_type_only(btf, record->type_id,
712 func_sig, 576 func_sig,
713 sizeof(func_sig)); 577 sizeof(func_sig));
@@ -744,49 +608,37 @@ static int do_dump(int argc, char **argv)
744 if (json_output) 608 if (json_output)
745 jsonw_end_array(json_wtr); 609 jsonw_end_array(json_wtr);
746 } else { 610 } else {
747 disasm_print_insn(buf, *member_len, opcodes, name, 611 disasm_print_insn(buf, member_len, opcodes, name,
748 disasm_opt, btf, NULL, 0, 0, false); 612 disasm_opt, btf, NULL, 0, 0, false);
749 } 613 }
750 } else if (visual) { 614 } else if (visual) {
751 if (json_output) 615 if (json_output)
752 jsonw_null(json_wtr); 616 jsonw_null(json_wtr);
753 else 617 else
754 dump_xlated_cfg(buf, *member_len); 618 dump_xlated_cfg(buf, member_len);
755 } else { 619 } else {
756 kernel_syms_load(&dd); 620 kernel_syms_load(&dd);
757 dd.nr_jited_ksyms = info.nr_jited_ksyms; 621 dd.nr_jited_ksyms = info->nr_jited_ksyms;
758 dd.jited_ksyms = (__u64 *) info.jited_ksyms; 622 dd.jited_ksyms = (__u64 *) info->jited_ksyms;
759 dd.btf = btf; 623 dd.btf = btf;
760 dd.func_info = func_info; 624 dd.func_info = func_info;
761 dd.finfo_rec_size = finfo_rec_size; 625 dd.finfo_rec_size = info->func_info_rec_size;
762 dd.prog_linfo = prog_linfo; 626 dd.prog_linfo = prog_linfo;
763 627
764 if (json_output) 628 if (json_output)
765 dump_xlated_json(&dd, buf, *member_len, opcodes, 629 dump_xlated_json(&dd, buf, member_len, opcodes,
766 linum); 630 linum);
767 else 631 else
768 dump_xlated_plain(&dd, buf, *member_len, opcodes, 632 dump_xlated_plain(&dd, buf, member_len, opcodes,
769 linum); 633 linum);
770 kernel_syms_destroy(&dd); 634 kernel_syms_destroy(&dd);
771 } 635 }
772 636
773 free(buf); 637 free(info_linear);
774 free(func_ksyms);
775 free(func_lens);
776 free(func_info);
777 free(linfo);
778 free(jited_linfo);
779 bpf_prog_linfo__free(prog_linfo);
780 return 0; 638 return 0;
781 639
782err_free: 640err_free:
783 free(buf); 641 free(info_linear);
784 free(func_ksyms);
785 free(func_lens);
786 free(func_info);
787 free(linfo);
788 free(jited_linfo);
789 bpf_prog_linfo__free(prog_linfo);
790 return -1; 642 return -1;
791} 643}
792 644
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 61e46d54a67c..8d3864b061f3 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -66,7 +66,8 @@ FEATURE_TESTS_BASIC := \
66 sched_getcpu \ 66 sched_getcpu \
67 sdt \ 67 sdt \
68 setns \ 68 setns \
69 libaio 69 libaio \
70 disassembler-four-args
70 71
71# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list 72# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
72# of all feature tests 73# of all feature tests
@@ -118,7 +119,8 @@ FEATURE_DISPLAY ?= \
118 lzma \ 119 lzma \
119 get_cpuid \ 120 get_cpuid \
120 bpf \ 121 bpf \
121 libaio 122 libaio \
123 disassembler-four-args
122 124
123# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. 125# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
124# If in the future we need per-feature checks/flags for features not 126# If in the future we need per-feature checks/flags for features not
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index e903b86b742f..7853e6d91090 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -178,6 +178,10 @@
178# include "test-reallocarray.c" 178# include "test-reallocarray.c"
179#undef main 179#undef main
180 180
181#define main main_test_disassembler_four_args
182# include "test-disassembler-four-args.c"
183#undef main
184
181int main(int argc, char *argv[]) 185int main(int argc, char *argv[])
182{ 186{
183 main_test_libpython(); 187 main_test_libpython();
@@ -219,6 +223,7 @@ int main(int argc, char *argv[])
219 main_test_setns(); 223 main_test_setns();
220 main_test_libaio(); 224 main_test_libaio();
221 main_test_reallocarray(); 225 main_test_reallocarray();
226 main_test_disassembler_four_args();
222 227
223 return 0; 228 return 0;
224} 229}
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index d5b830d60601..e6ad87512519 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -112,6 +112,11 @@ void libbpf_print(enum libbpf_print_level level, const char *format, ...)
112# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ 112# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
113#endif 113#endif
114 114
115static inline __u64 ptr_to_u64(const void *ptr)
116{
117 return (__u64) (unsigned long) ptr;
118}
119
115struct bpf_capabilities { 120struct bpf_capabilities {
116 /* v4.14: kernel support for program & map names. */ 121 /* v4.14: kernel support for program & map names. */
117 __u32 name:1; 122 __u32 name:1;
@@ -622,7 +627,7 @@ bpf_object__init_maps(struct bpf_object *obj, int flags)
622 bool strict = !(flags & MAPS_RELAX_COMPAT); 627 bool strict = !(flags & MAPS_RELAX_COMPAT);
623 int i, map_idx, map_def_sz, nr_maps = 0; 628 int i, map_idx, map_def_sz, nr_maps = 0;
624 Elf_Scn *scn; 629 Elf_Scn *scn;
625 Elf_Data *data; 630 Elf_Data *data = NULL;
626 Elf_Data *symbols = obj->efile.symbols; 631 Elf_Data *symbols = obj->efile.symbols;
627 632
628 if (obj->efile.maps_shndx < 0) 633 if (obj->efile.maps_shndx < 0)
@@ -2999,3 +3004,249 @@ bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size,
2999 ring_buffer_write_tail(header, data_tail); 3004 ring_buffer_write_tail(header, data_tail);
3000 return ret; 3005 return ret;
3001} 3006}
3007
3008struct bpf_prog_info_array_desc {
3009 int array_offset; /* e.g. offset of jited_prog_insns */
3010 int count_offset; /* e.g. offset of jited_prog_len */
3011 int size_offset; /* > 0: offset of rec size,
3012 * < 0: fix size of -size_offset
3013 */
3014};
3015
3016static struct bpf_prog_info_array_desc bpf_prog_info_array_desc[] = {
3017 [BPF_PROG_INFO_JITED_INSNS] = {
3018 offsetof(struct bpf_prog_info, jited_prog_insns),
3019 offsetof(struct bpf_prog_info, jited_prog_len),
3020 -1,
3021 },
3022 [BPF_PROG_INFO_XLATED_INSNS] = {
3023 offsetof(struct bpf_prog_info, xlated_prog_insns),
3024 offsetof(struct bpf_prog_info, xlated_prog_len),
3025 -1,
3026 },
3027 [BPF_PROG_INFO_MAP_IDS] = {
3028 offsetof(struct bpf_prog_info, map_ids),
3029 offsetof(struct bpf_prog_info, nr_map_ids),
3030 -(int)sizeof(__u32),
3031 },
3032 [BPF_PROG_INFO_JITED_KSYMS] = {
3033 offsetof(struct bpf_prog_info, jited_ksyms),
3034 offsetof(struct bpf_prog_info, nr_jited_ksyms),
3035 -(int)sizeof(__u64),
3036 },
3037 [BPF_PROG_INFO_JITED_FUNC_LENS] = {
3038 offsetof(struct bpf_prog_info, jited_func_lens),
3039 offsetof(struct bpf_prog_info, nr_jited_func_lens),
3040 -(int)sizeof(__u32),
3041 },
3042 [BPF_PROG_INFO_FUNC_INFO] = {
3043 offsetof(struct bpf_prog_info, func_info),
3044 offsetof(struct bpf_prog_info, nr_func_info),
3045 offsetof(struct bpf_prog_info, func_info_rec_size),
3046 },
3047 [BPF_PROG_INFO_LINE_INFO] = {
3048 offsetof(struct bpf_prog_info, line_info),
3049 offsetof(struct bpf_prog_info, nr_line_info),
3050 offsetof(struct bpf_prog_info, line_info_rec_size),
3051 },
3052 [BPF_PROG_INFO_JITED_LINE_INFO] = {
3053 offsetof(struct bpf_prog_info, jited_line_info),
3054 offsetof(struct bpf_prog_info, nr_jited_line_info),
3055 offsetof(struct bpf_prog_info, jited_line_info_rec_size),
3056 },
3057 [BPF_PROG_INFO_PROG_TAGS] = {
3058 offsetof(struct bpf_prog_info, prog_tags),
3059 offsetof(struct bpf_prog_info, nr_prog_tags),
3060 -(int)sizeof(__u8) * BPF_TAG_SIZE,
3061 },
3062
3063};
3064
3065static __u32 bpf_prog_info_read_offset_u32(struct bpf_prog_info *info, int offset)
3066{
3067 __u32 *array = (__u32 *)info;
3068
3069 if (offset >= 0)
3070 return array[offset / sizeof(__u32)];
3071 return -(int)offset;
3072}
3073
3074static __u64 bpf_prog_info_read_offset_u64(struct bpf_prog_info *info, int offset)
3075{
3076 __u64 *array = (__u64 *)info;
3077
3078 if (offset >= 0)
3079 return array[offset / sizeof(__u64)];
3080 return -(int)offset;
3081}
3082
3083static void bpf_prog_info_set_offset_u32(struct bpf_prog_info *info, int offset,
3084 __u32 val)
3085{
3086 __u32 *array = (__u32 *)info;
3087
3088 if (offset >= 0)
3089 array[offset / sizeof(__u32)] = val;
3090}
3091
3092static void bpf_prog_info_set_offset_u64(struct bpf_prog_info *info, int offset,
3093 __u64 val)
3094{
3095 __u64 *array = (__u64 *)info;
3096
3097 if (offset >= 0)
3098 array[offset / sizeof(__u64)] = val;
3099}
3100
3101struct bpf_prog_info_linear *
3102bpf_program__get_prog_info_linear(int fd, __u64 arrays)
3103{
3104 struct bpf_prog_info_linear *info_linear;
3105 struct bpf_prog_info info = {};
3106 __u32 info_len = sizeof(info);
3107 __u32 data_len = 0;
3108 int i, err;
3109 void *ptr;
3110
3111 if (arrays >> BPF_PROG_INFO_LAST_ARRAY)
3112 return ERR_PTR(-EINVAL);
3113
3114 /* step 1: get array dimensions */
3115 err = bpf_obj_get_info_by_fd(fd, &info, &info_len);
3116 if (err) {
3117 pr_debug("can't get prog info: %s", strerror(errno));
3118 return ERR_PTR(-EFAULT);
3119 }
3120
3121 /* step 2: calculate total size of all arrays */
3122 for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
3123 bool include_array = (arrays & (1UL << i)) > 0;
3124 struct bpf_prog_info_array_desc *desc;
3125 __u32 count, size;
3126
3127 desc = bpf_prog_info_array_desc + i;
3128
3129 /* kernel is too old to support this field */
3130 if (info_len < desc->array_offset + sizeof(__u32) ||
3131 info_len < desc->count_offset + sizeof(__u32) ||
3132 (desc->size_offset > 0 && info_len < desc->size_offset))
3133 include_array = false;
3134
3135 if (!include_array) {
3136 arrays &= ~(1UL << i); /* clear the bit */
3137 continue;
3138 }
3139
3140 count = bpf_prog_info_read_offset_u32(&info, desc->count_offset);
3141 size = bpf_prog_info_read_offset_u32(&info, desc->size_offset);
3142
3143 data_len += count * size;
3144 }
3145
3146 /* step 3: allocate continuous memory */
3147 data_len = roundup(data_len, sizeof(__u64));
3148 info_linear = malloc(sizeof(struct bpf_prog_info_linear) + data_len);
3149 if (!info_linear)
3150 return ERR_PTR(-ENOMEM);
3151
3152 /* step 4: fill data to info_linear->info */
3153 info_linear->arrays = arrays;
3154 memset(&info_linear->info, 0, sizeof(info));
3155 ptr = info_linear->data;
3156
3157 for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
3158 struct bpf_prog_info_array_desc *desc;
3159 __u32 count, size;
3160
3161 if ((arrays & (1UL << i)) == 0)
3162 continue;
3163
3164 desc = bpf_prog_info_array_desc + i;
3165 count = bpf_prog_info_read_offset_u32(&info, desc->count_offset);
3166 size = bpf_prog_info_read_offset_u32(&info, desc->size_offset);
3167 bpf_prog_info_set_offset_u32(&info_linear->info,
3168 desc->count_offset, count);
3169 bpf_prog_info_set_offset_u32(&info_linear->info,
3170 desc->size_offset, size);
3171 bpf_prog_info_set_offset_u64(&info_linear->info,
3172 desc->array_offset,
3173 ptr_to_u64(ptr));
3174 ptr += count * size;
3175 }
3176
3177 /* step 5: call syscall again to get required arrays */
3178 err = bpf_obj_get_info_by_fd(fd, &info_linear->info, &info_len);
3179 if (err) {
3180 pr_debug("can't get prog info: %s", strerror(errno));
3181 free(info_linear);
3182 return ERR_PTR(-EFAULT);
3183 }
3184
3185 /* step 6: verify the data */
3186 for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
3187 struct bpf_prog_info_array_desc *desc;
3188 __u32 v1, v2;
3189
3190 if ((arrays & (1UL << i)) == 0)
3191 continue;
3192
3193 desc = bpf_prog_info_array_desc + i;
3194 v1 = bpf_prog_info_read_offset_u32(&info, desc->count_offset);
3195 v2 = bpf_prog_info_read_offset_u32(&info_linear->info,
3196 desc->count_offset);
3197 if (v1 != v2)
3198 pr_warning("%s: mismatch in element count\n", __func__);
3199
3200 v1 = bpf_prog_info_read_offset_u32(&info, desc->size_offset);
3201 v2 = bpf_prog_info_read_offset_u32(&info_linear->info,
3202 desc->size_offset);
3203 if (v1 != v2)
3204 pr_warning("%s: mismatch in rec size\n", __func__);
3205 }
3206
3207 /* step 7: update info_len and data_len */
3208 info_linear->info_len = sizeof(struct bpf_prog_info);
3209 info_linear->data_len = data_len;
3210
3211 return info_linear;
3212}
3213
3214void bpf_program__bpil_addr_to_offs(struct bpf_prog_info_linear *info_linear)
3215{
3216 int i;
3217
3218 for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
3219 struct bpf_prog_info_array_desc *desc;
3220 __u64 addr, offs;
3221
3222 if ((info_linear->arrays & (1UL << i)) == 0)
3223 continue;
3224
3225 desc = bpf_prog_info_array_desc + i;
3226 addr = bpf_prog_info_read_offset_u64(&info_linear->info,
3227 desc->array_offset);
3228 offs = addr - ptr_to_u64(info_linear->data);
3229 bpf_prog_info_set_offset_u64(&info_linear->info,
3230 desc->array_offset, offs);
3231 }
3232}
3233
3234void bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear)
3235{
3236 int i;
3237
3238 for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
3239 struct bpf_prog_info_array_desc *desc;
3240 __u64 addr, offs;
3241
3242 if ((info_linear->arrays & (1UL << i)) == 0)
3243 continue;
3244
3245 desc = bpf_prog_info_array_desc + i;
3246 offs = bpf_prog_info_read_offset_u64(&info_linear->info,
3247 desc->array_offset);
3248 addr = offs + ptr_to_u64(info_linear->data);
3249 bpf_prog_info_set_offset_u64(&info_linear->info,
3250 desc->array_offset, addr);
3251 }
3252}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index aa1521a51687..c70785cc8ef5 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -378,6 +378,69 @@ LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
378LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id, 378LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id,
379 enum bpf_prog_type prog_type, __u32 ifindex); 379 enum bpf_prog_type prog_type, __u32 ifindex);
380 380
381/*
382 * Get bpf_prog_info in continuous memory
383 *
384 * struct bpf_prog_info has multiple arrays. The user has option to choose
385 * arrays to fetch from kernel. The following APIs provide an uniform way to
386 * fetch these data. All arrays in bpf_prog_info are stored in a single
387 * continuous memory region. This makes it easy to store the info in a
388 * file.
389 *
390 * Before writing bpf_prog_info_linear to files, it is necessary to
391 * translate pointers in bpf_prog_info to offsets. Helper functions
392 * bpf_program__bpil_addr_to_offs() and bpf_program__bpil_offs_to_addr()
393 * are introduced to switch between pointers and offsets.
394 *
395 * Examples:
396 * # To fetch map_ids and prog_tags:
397 * __u64 arrays = (1UL << BPF_PROG_INFO_MAP_IDS) |
398 * (1UL << BPF_PROG_INFO_PROG_TAGS);
399 * struct bpf_prog_info_linear *info_linear =
400 * bpf_program__get_prog_info_linear(fd, arrays);
401 *
402 * # To save data in file
403 * bpf_program__bpil_addr_to_offs(info_linear);
404 * write(f, info_linear, sizeof(*info_linear) + info_linear->data_len);
405 *
406 * # To read data from file
407 * read(f, info_linear, <proper_size>);
408 * bpf_program__bpil_offs_to_addr(info_linear);
409 */
410enum bpf_prog_info_array {
411 BPF_PROG_INFO_FIRST_ARRAY = 0,
412 BPF_PROG_INFO_JITED_INSNS = 0,
413 BPF_PROG_INFO_XLATED_INSNS,
414 BPF_PROG_INFO_MAP_IDS,
415 BPF_PROG_INFO_JITED_KSYMS,
416 BPF_PROG_INFO_JITED_FUNC_LENS,
417 BPF_PROG_INFO_FUNC_INFO,
418 BPF_PROG_INFO_LINE_INFO,
419 BPF_PROG_INFO_JITED_LINE_INFO,
420 BPF_PROG_INFO_PROG_TAGS,
421 BPF_PROG_INFO_LAST_ARRAY,
422};
423
424struct bpf_prog_info_linear {
425 /* size of struct bpf_prog_info, when the tool is compiled */
426 __u32 info_len;
427 /* total bytes allocated for data, round up to 8 bytes */
428 __u32 data_len;
429 /* which arrays are included in data */
430 __u64 arrays;
431 struct bpf_prog_info info;
432 __u8 data[];
433};
434
435LIBBPF_API struct bpf_prog_info_linear *
436bpf_program__get_prog_info_linear(int fd, __u64 arrays);
437
438LIBBPF_API void
439bpf_program__bpil_addr_to_offs(struct bpf_prog_info_linear *info_linear);
440
441LIBBPF_API void
442bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear);
443
381#ifdef __cplusplus 444#ifdef __cplusplus
382} /* extern "C" */ 445} /* extern "C" */
383#endif 446#endif
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 778a26702a70..f3ce50500cf2 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -153,4 +153,7 @@ LIBBPF_0.0.2 {
153 xsk_socket__delete; 153 xsk_socket__delete;
154 xsk_umem__fd; 154 xsk_umem__fd;
155 xsk_socket__fd; 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} LIBBPF_0.0.1; 159} LIBBPF_0.0.1;
diff --git a/tools/perf/Documentation/Build.txt b/tools/perf/Documentation/Build.txt
index f6fc6507ba55..3766886c4bca 100644
--- a/tools/perf/Documentation/Build.txt
+++ b/tools/perf/Documentation/Build.txt
@@ -47,3 +47,27 @@ Those objects are then used in final linking:
47 47
48NOTE this description is omitting other libraries involved, only 48NOTE this description is omitting other libraries involved, only
49 focusing on build framework outcomes 49 focusing on build framework outcomes
50
513) Build with ASan or UBSan
52==========================
53 $ cd tools/perf
54 $ make DESTDIR=/usr
55 $ make DESTDIR=/usr install
56
57AddressSanitizer (or ASan) is a GCC feature that detects memory corruption bugs
58such 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
64ASan outputs all detected issues into a log file named 'asan.log.<pid>'.
65
66UndefinedBehaviorSanitizer (or UBSan) is a fast undefined behavior detector
67supported 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
73If UBSan detects any problem at runtime, it outputs a “runtime error:” message.
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 95054a8176a2..462b3cde0675 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -114,7 +114,7 @@ Given a $HOME/.perfconfig like this:
114 114
115 [report] 115 [report]
116 # Defaults 116 # Defaults
117 sort-order = comm,dso,symbol 117 sort_order = comm,dso,symbol
118 percent-limit = 0 118 percent-limit = 0
119 queue-size = 0 119 queue-size = 0
120 children = true 120 children = true
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 8f0c2be34848..8fe4dffcadd0 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -495,6 +495,10 @@ overhead. You can still switch them on with:
495 495
496 --switch-output --no-no-buildid --no-no-buildid-cache 496 --switch-output --no-no-buildid --no-no-buildid-cache
497 497
498--switch-max-files=N::
499
500When rotating perf.data with --switch-output, only keep N files.
501
498--dry-run:: 502--dry-run::
499Parse options then exit. --dry-run can be used to detect errors in cmdline 503Parse options then exit. --dry-run can be used to detect errors in cmdline
500options. 504options.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 2e19fd7ffe35..9b0d04dd2a61 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -380,6 +380,9 @@ include::itrace.txt[]
380 Set the maximum number of program blocks to print with brstackasm for 380 Set the maximum number of program blocks to print with brstackasm for
381 each sample. 381 each sample.
382 382
383--reltime::
384 Print time stamps relative to trace start.
385
383--per-event-dump:: 386--per-event-dump::
384 Create per event files with a "perf.data.EVENT.dump" name instead of 387 Create per event files with a "perf.data.EVENT.dump" name instead of
385 printing to stdout, useful, for instance, for generating flamegraphs. 388 printing to stdout, useful, for instance, for generating flamegraphs.
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 4bc2085e5197..39c05f89104e 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -72,9 +72,8 @@ report::
72--all-cpus:: 72--all-cpus::
73 system-wide collection from all CPUs (default if no target is specified) 73 system-wide collection from all CPUs (default if no target is specified)
74 74
75-c:: 75--no-scale::
76--scale:: 76 Don't scale/normalize counter values
77 scale/normalize counter values
78 77
79-d:: 78-d::
80--detailed:: 79--detailed::
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 0f11d5891301..fe3f97e342fa 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -227,6 +227,8 @@ FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
227 227
228FEATURE_CHECK_LDFLAGS-libaio = -lrt 228FEATURE_CHECK_LDFLAGS-libaio = -lrt
229 229
230FEATURE_CHECK_LDFLAGS-disassembler-four-args = -lbfd -lopcodes
231
230CFLAGS += -fno-omit-frame-pointer 232CFLAGS += -fno-omit-frame-pointer
231CFLAGS += -ggdb3 233CFLAGS += -ggdb3
232CFLAGS += -funwind-tables 234CFLAGS += -funwind-tables
@@ -713,7 +715,7 @@ else
713endif 715endif
714 716
715ifeq ($(feature-libbfd), 1) 717ifeq ($(feature-libbfd), 1)
716 EXTLIBS += -lbfd 718 EXTLIBS += -lbfd -lopcodes
717else 719else
718 # we are on a system that requires -liberty and (maybe) -lz 720 # we are on a system that requires -liberty and (maybe) -lz
719 # to link against -lbfd; test each case individually here 721 # to link against -lbfd; test each case individually here
@@ -724,12 +726,15 @@ else
724 $(call feature_check,libbfd-liberty-z) 726 $(call feature_check,libbfd-liberty-z)
725 727
726 ifeq ($(feature-libbfd-liberty), 1) 728 ifeq ($(feature-libbfd-liberty), 1)
727 EXTLIBS += -lbfd -liberty 729 EXTLIBS += -lbfd -lopcodes -liberty
730 FEATURE_CHECK_LDFLAGS-disassembler-four-args += -liberty -ldl
728 else 731 else
729 ifeq ($(feature-libbfd-liberty-z), 1) 732 ifeq ($(feature-libbfd-liberty-z), 1)
730 EXTLIBS += -lbfd -liberty -lz 733 EXTLIBS += -lbfd -lopcodes -liberty -lz
734 FEATURE_CHECK_LDFLAGS-disassembler-four-args += -liberty -lz -ldl
731 endif 735 endif
732 endif 736 endif
737 $(call feature_check,disassembler-four-args)
733endif 738endif
734 739
735ifdef NO_DEMANGLE 740ifdef NO_DEMANGLE
@@ -808,6 +813,10 @@ ifdef HAVE_KVM_STAT_SUPPORT
808 CFLAGS += -DHAVE_KVM_STAT_SUPPORT 813 CFLAGS += -DHAVE_KVM_STAT_SUPPORT
809endif 814endif
810 815
816ifeq ($(feature-disassembler-four-args), 1)
817 CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
818endif
819
811ifeq (${IS_64_BIT}, 1) 820ifeq (${IS_64_BIT}, 1)
812 ifndef NO_PERF_READ_VDSO32 821 ifndef NO_PERF_READ_VDSO32
813 $(call feature_check,compile-32) 822 $(call feature_check,compile-32)
diff --git a/tools/perf/bench/epoll-ctl.c b/tools/perf/bench/epoll-ctl.c
index 0c0a6e824934..2af067859966 100644
--- a/tools/perf/bench/epoll-ctl.c
+++ b/tools/perf/bench/epoll-ctl.c
@@ -224,7 +224,7 @@ static int do_threads(struct worker *worker, struct cpu_map *cpu)
224 pthread_attr_t thread_attr, *attrp = NULL; 224 pthread_attr_t thread_attr, *attrp = NULL;
225 cpu_set_t cpuset; 225 cpu_set_t cpuset;
226 unsigned int i, j; 226 unsigned int i, j;
227 int ret; 227 int ret = 0;
228 228
229 if (!noaffinity) 229 if (!noaffinity)
230 pthread_attr_init(&thread_attr); 230 pthread_attr_init(&thread_attr);
diff --git a/tools/perf/bench/epoll-wait.c b/tools/perf/bench/epoll-wait.c
index 5a11534e96a0..fe85448abd45 100644
--- a/tools/perf/bench/epoll-wait.c
+++ b/tools/perf/bench/epoll-wait.c
@@ -293,7 +293,7 @@ static int do_threads(struct worker *worker, struct cpu_map *cpu)
293 pthread_attr_t thread_attr, *attrp = NULL; 293 pthread_attr_t thread_attr, *attrp = NULL;
294 cpu_set_t cpuset; 294 cpu_set_t cpuset;
295 unsigned int i, j; 295 unsigned int i, j;
296 int ret, events = EPOLLIN; 296 int ret = 0, events = EPOLLIN;
297 297
298 if (oneshot) 298 if (oneshot)
299 events |= EPOLLONESHOT; 299 events |= EPOLLONESHOT;
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index c9f98d00c0e9..a8394b4f1167 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -119,7 +119,7 @@ int cmd_list(int argc, const char **argv)
119 details_flag); 119 details_flag);
120 print_tracepoint_events(NULL, s, raw_dump); 120 print_tracepoint_events(NULL, s, raw_dump);
121 print_sdt_events(NULL, s, raw_dump); 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 free(s); 123 free(s);
124 } 124 }
125 } 125 }
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a468d882e74f..4e2d953d4bc5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -62,6 +62,9 @@ struct switch_output {
62 unsigned long time; 62 unsigned long time;
63 const char *str; 63 const char *str;
64 bool set; 64 bool set;
65 char **filenames;
66 int num_files;
67 int cur_file;
65}; 68};
66 69
67struct record { 70struct record {
@@ -892,6 +895,7 @@ record__switch_output(struct record *rec, bool at_exit)
892{ 895{
893 struct perf_data *data = &rec->data; 896 struct perf_data *data = &rec->data;
894 int fd, err; 897 int fd, err;
898 char *new_filename;
895 899
896 /* Same Size: "2015122520103046"*/ 900 /* Same Size: "2015122520103046"*/
897 char timestamp[] = "InvalidTimestamp"; 901 char timestamp[] = "InvalidTimestamp";
@@ -912,7 +916,7 @@ record__switch_output(struct record *rec, bool at_exit)
912 916
913 fd = perf_data__switch(data, timestamp, 917 fd = perf_data__switch(data, timestamp,
914 rec->session->header.data_offset, 918 rec->session->header.data_offset,
915 at_exit); 919 at_exit, &new_filename);
916 if (fd >= 0 && !at_exit) { 920 if (fd >= 0 && !at_exit) {
917 rec->bytes_written = 0; 921 rec->bytes_written = 0;
918 rec->session->header.data_size = 0; 922 rec->session->header.data_size = 0;
@@ -922,6 +926,21 @@ record__switch_output(struct record *rec, bool at_exit)
922 fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 926 fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
923 data->path, timestamp); 927 data->path, timestamp);
924 928
929 if (rec->switch_output.num_files) {
930 int n = rec->switch_output.cur_file + 1;
931
932 if (n >= rec->switch_output.num_files)
933 n = 0;
934 rec->switch_output.cur_file = n;
935 if (rec->switch_output.filenames[n]) {
936 remove(rec->switch_output.filenames[n]);
937 free(rec->switch_output.filenames[n]);
938 }
939 rec->switch_output.filenames[n] = new_filename;
940 } else {
941 free(new_filename);
942 }
943
925 /* Output tracking events */ 944 /* Output tracking events */
926 if (!at_exit) { 945 if (!at_exit) {
927 record__synthesize(rec, false); 946 record__synthesize(rec, false);
@@ -1095,7 +1114,7 @@ static int record__synthesize(struct record *rec, bool tail)
1095 return err; 1114 return err;
1096 } 1115 }
1097 1116
1098 err = perf_event__synthesize_bpf_events(tool, process_synthesized_event, 1117 err = perf_event__synthesize_bpf_events(session, process_synthesized_event,
1099 machine, opts); 1118 machine, opts);
1100 if (err < 0) 1119 if (err < 0)
1101 pr_warning("Couldn't synthesize bpf events.\n"); 1120 pr_warning("Couldn't synthesize bpf events.\n");
@@ -1118,6 +1137,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
1118 struct perf_data *data = &rec->data; 1137 struct perf_data *data = &rec->data;
1119 struct perf_session *session; 1138 struct perf_session *session;
1120 bool disabled = false, draining = false; 1139 bool disabled = false, draining = false;
1140 struct perf_evlist *sb_evlist = NULL;
1121 int fd; 1141 int fd;
1122 1142
1123 atexit(record__sig_exit); 1143 atexit(record__sig_exit);
@@ -1218,6 +1238,14 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
1218 goto out_child; 1238 goto out_child;
1219 } 1239 }
1220 1240
1241 if (!opts->no_bpf_event)
1242 bpf_event__add_sb_event(&sb_evlist, &session->header.env);
1243
1244 if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) {
1245 pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
1246 opts->no_bpf_event = true;
1247 }
1248
1221 err = record__synthesize(rec, false); 1249 err = record__synthesize(rec, false);
1222 if (err < 0) 1250 if (err < 0)
1223 goto out_child; 1251 goto out_child;
@@ -1468,6 +1496,9 @@ out_child:
1468 1496
1469out_delete_session: 1497out_delete_session:
1470 perf_session__delete(session); 1498 perf_session__delete(session);
1499
1500 if (!opts->no_bpf_event)
1501 perf_evlist__stop_sb_thread(sb_evlist);
1471 return status; 1502 return status;
1472} 1503}
1473 1504
@@ -1872,7 +1903,7 @@ static struct option __record_options[] = {
1872 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 1903 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
1873 "synthesize non-sample events at the end of output"), 1904 "synthesize non-sample events at the end of output"),
1874 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 1905 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1875 OPT_BOOLEAN(0, "bpf-event", &record.opts.bpf_event, "record bpf events"), 1906 OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"),
1876 OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq, 1907 OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
1877 "Fail if the specified frequency can't be used"), 1908 "Fail if the specified frequency can't be used"),
1878 OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'", 1909 OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
@@ -1970,9 +2001,11 @@ static struct option __record_options[] = {
1970 OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, 2001 OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
1971 "Record timestamp boundary (time of first/last samples)"), 2002 "Record timestamp boundary (time of first/last samples)"),
1972 OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 2003 OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
1973 &record.switch_output.set, "signal,size,time", 2004 &record.switch_output.set, "signal or size[BKMG] or time[smhd]",
1974 "Switch output when receive SIGUSR2 or cross size,time threshold", 2005 "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold",
1975 "signal"), 2006 "signal"),
2007 OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files,
2008 "Limit number of switch output generated files"),
1976 OPT_BOOLEAN(0, "dry-run", &dry_run, 2009 OPT_BOOLEAN(0, "dry-run", &dry_run,
1977 "Parse options then exit"), 2010 "Parse options then exit"),
1978#ifdef HAVE_AIO_SUPPORT 2011#ifdef HAVE_AIO_SUPPORT
@@ -2059,6 +2092,13 @@ int cmd_record(int argc, const char **argv)
2059 alarm(rec->switch_output.time); 2092 alarm(rec->switch_output.time);
2060 } 2093 }
2061 2094
2095 if (rec->switch_output.num_files) {
2096 rec->switch_output.filenames = calloc(sizeof(char *),
2097 rec->switch_output.num_files);
2098 if (!rec->switch_output.filenames)
2099 return -EINVAL;
2100 }
2101
2062 /* 2102 /*
2063 * Allow aliases to facilitate the lookup of symbols for address 2103 * Allow aliases to facilitate the lookup of symbols for address
2064 * filters. Refer to auxtrace_parse_filters(). 2104 * filters. Refer to auxtrace_parse_filters().
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 1921aaa9cece..4054eb1f98ac 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1083,10 +1083,9 @@ int cmd_report(int argc, const char **argv)
1083 OPT_BOOLEAN(0, "header-only", &report.header_only, 1083 OPT_BOOLEAN(0, "header-only", &report.header_only,
1084 "Show only data header."), 1084 "Show only data header."),
1085 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1085 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1086 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." 1086 sort_help("sort by key(s):")),
1087 " Please refer the man page for the complete list."),
1088 OPT_STRING('F', "fields", &field_order, "key[,keys...]", 1087 OPT_STRING('F', "fields", &field_order, "key[,keys...]",
1089 "output field(s): overhead, period, sample plus all of sort keys"), 1088 sort_help("output field(s): overhead period sample ")),
1090 OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization, 1089 OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization,
1091 "Show sample percentage for different cpu modes"), 1090 "Show sample percentage for different cpu modes"),
1092 OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 1091 OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 2f93d60c5a17..61cfd8f70989 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -53,6 +53,8 @@
53 53
54static char const *script_name; 54static char const *script_name;
55static char const *generate_script_lang; 55static char const *generate_script_lang;
56static bool reltime;
57static u64 initial_time;
56static bool debug_mode; 58static bool debug_mode;
57static u64 last_timestamp; 59static u64 last_timestamp;
58static u64 nr_unordered; 60static u64 nr_unordered;
@@ -686,7 +688,13 @@ static int perf_sample__fprintf_start(struct perf_sample *sample,
686 } 688 }
687 689
688 if (PRINT_FIELD(TIME)) { 690 if (PRINT_FIELD(TIME)) {
689 nsecs = sample->time; 691 u64 t = sample->time;
692 if (reltime) {
693 if (!initial_time)
694 initial_time = sample->time;
695 t = sample->time - initial_time;
696 }
697 nsecs = t;
690 secs = nsecs / NSEC_PER_SEC; 698 secs = nsecs / NSEC_PER_SEC;
691 nsecs -= secs * NSEC_PER_SEC; 699 nsecs -= secs * NSEC_PER_SEC;
692 700
@@ -694,7 +702,7 @@ static int perf_sample__fprintf_start(struct perf_sample *sample,
694 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs); 702 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs);
695 else { 703 else {
696 char sample_time[32]; 704 char sample_time[32];
697 timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time)); 705 timestamp__scnprintf_usec(t, sample_time, sizeof(sample_time));
698 printed += fprintf(fp, "%12s: ", sample_time); 706 printed += fprintf(fp, "%12s: ", sample_time);
699 } 707 }
700 } 708 }
@@ -3413,6 +3421,7 @@ int cmd_script(int argc, const char **argv)
3413 "Set the maximum stack depth when parsing the callchain, " 3421 "Set the maximum stack depth when parsing the callchain, "
3414 "anything beyond the specified depth will be ignored. " 3422 "anything beyond the specified depth will be ignored. "
3415 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), 3423 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
3424 OPT_BOOLEAN(0, "reltime", &reltime, "Show time stamps relative to start"),
3416 OPT_BOOLEAN('I', "show-info", &show_full_info, 3425 OPT_BOOLEAN('I', "show-info", &show_full_info,
3417 "display extended information from perf.data file"), 3426 "display extended information from perf.data file"),
3418 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 3427 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -3487,6 +3496,11 @@ int cmd_script(int argc, const char **argv)
3487 } 3496 }
3488 } 3497 }
3489 3498
3499 if (script.time_str && reltime) {
3500 fprintf(stderr, "Don't combine --reltime with --time\n");
3501 return -1;
3502 }
3503
3490 if (itrace_synth_opts.callchain && 3504 if (itrace_synth_opts.callchain &&
3491 itrace_synth_opts.callchain_sz > scripting_max_stack) 3505 itrace_synth_opts.callchain_sz > scripting_max_stack)
3492 scripting_max_stack = itrace_synth_opts.callchain_sz; 3506 scripting_max_stack = itrace_synth_opts.callchain_sz;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7b8f09b0b8bf..49ee3c2033ec 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -718,7 +718,8 @@ static struct option stat_options[] = {
718 "system-wide collection from all CPUs"), 718 "system-wide collection from all CPUs"),
719 OPT_BOOLEAN('g', "group", &group, 719 OPT_BOOLEAN('g', "group", &group,
720 "put the counters into a counter group"), 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 OPT_INCR('v', "verbose", &verbose, 723 OPT_INCR('v', "verbose", &verbose,
723 "be more verbose (show counter open errors, etc)"), 724 "be more verbose (show counter open errors, etc)"),
724 OPT_INTEGER('r', "repeat", &stat_config.run_count, 725 OPT_INTEGER('r', "repeat", &stat_config.run_count,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 231a90daa958..1999d6533d12 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1189,30 +1189,26 @@ static int __cmd_top(struct perf_top *top)
1189 pthread_t thread, thread_process; 1189 pthread_t thread, thread_process;
1190 int ret; 1190 int ret;
1191 1191
1192 top->session = perf_session__new(NULL, false, NULL);
1193 if (top->session == NULL)
1194 return -1;
1195
1196 if (!top->annotation_opts.objdump_path) { 1192 if (!top->annotation_opts.objdump_path) {
1197 ret = perf_env__lookup_objdump(&top->session->header.env, 1193 ret = perf_env__lookup_objdump(&top->session->header.env,
1198 &top->annotation_opts.objdump_path); 1194 &top->annotation_opts.objdump_path);
1199 if (ret) 1195 if (ret)
1200 goto out_delete; 1196 return ret;
1201 } 1197 }
1202 1198
1203 ret = callchain_param__setup_sample_type(&callchain_param); 1199 ret = callchain_param__setup_sample_type(&callchain_param);
1204 if (ret) 1200 if (ret)
1205 goto out_delete; 1201 return ret;
1206 1202
1207 if (perf_session__register_idle_thread(top->session) < 0) 1203 if (perf_session__register_idle_thread(top->session) < 0)
1208 goto out_delete; 1204 return ret;
1209 1205
1210 if (top->nr_threads_synthesize > 1) 1206 if (top->nr_threads_synthesize > 1)
1211 perf_set_multithreaded(); 1207 perf_set_multithreaded();
1212 1208
1213 init_process_thread(top); 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 &top->session->machines.host, 1212 &top->session->machines.host,
1217 &top->record_opts); 1213 &top->record_opts);
1218 if (ret < 0) 1214 if (ret < 0)
@@ -1227,13 +1223,18 @@ static int __cmd_top(struct perf_top *top)
1227 1223
1228 if (perf_hpp_list.socket) { 1224 if (perf_hpp_list.socket) {
1229 ret = perf_env__read_cpu_topology_map(&perf_env); 1225 ret = perf_env__read_cpu_topology_map(&perf_env);
1230 if (ret < 0) 1226 if (ret < 0) {
1231 goto out_err_cpu_topo; 1227 char errbuf[BUFSIZ];
1228 const char *err = str_error_r(-ret, errbuf, sizeof(errbuf));
1229
1230 ui__error("Could not read the CPU topology map: %s\n", err);
1231 return ret;
1232 }
1232 } 1233 }
1233 1234
1234 ret = perf_top__start_counters(top); 1235 ret = perf_top__start_counters(top);
1235 if (ret) 1236 if (ret)
1236 goto out_delete; 1237 return ret;
1237 1238
1238 top->session->evlist = top->evlist; 1239 top->session->evlist = top->evlist;
1239 perf_session__set_id_hdr_size(top->session); 1240 perf_session__set_id_hdr_size(top->session);
@@ -1252,7 +1253,7 @@ static int __cmd_top(struct perf_top *top)
1252 ret = -1; 1253 ret = -1;
1253 if (pthread_create(&thread_process, NULL, process_thread, top)) { 1254 if (pthread_create(&thread_process, NULL, process_thread, top)) {
1254 ui__error("Could not create process thread.\n"); 1255 ui__error("Could not create process thread.\n");
1255 goto out_delete; 1256 return ret;
1256 } 1257 }
1257 1258
1258 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : 1259 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
@@ -1296,19 +1297,7 @@ out_join:
1296out_join_thread: 1297out_join_thread:
1297 pthread_cond_signal(&top->qe.cond); 1298 pthread_cond_signal(&top->qe.cond);
1298 pthread_join(thread_process, NULL); 1299 pthread_join(thread_process, NULL);
1299out_delete:
1300 perf_session__delete(top->session);
1301 top->session = NULL;
1302
1303 return ret; 1300 return ret;
1304
1305out_err_cpu_topo: {
1306 char errbuf[BUFSIZ];
1307 const char *err = str_error_r(-ret, errbuf, sizeof(errbuf));
1308
1309 ui__error("Could not read the CPU topology map: %s\n", err);
1310 goto out_delete;
1311}
1312} 1301}
1313 1302
1314static int 1303static int
@@ -1480,6 +1469,7 @@ int cmd_top(int argc, const char **argv)
1480 "Display raw encoding of assembly instructions (default)"), 1469 "Display raw encoding of assembly instructions (default)"),
1481 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 1470 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
1482 "Enable kernel symbol demangling"), 1471 "Enable kernel symbol demangling"),
1472 OPT_BOOLEAN(0, "no-bpf-event", &top.record_opts.no_bpf_event, "do not record bpf events"),
1483 OPT_STRING(0, "objdump", &top.annotation_opts.objdump_path, "path", 1473 OPT_STRING(0, "objdump", &top.annotation_opts.objdump_path, "path",
1484 "objdump binary to use for disassembly and annotations"), 1474 "objdump binary to use for disassembly and annotations"),
1485 OPT_STRING('M', "disassembler-style", &top.annotation_opts.disassembler_style, "disassembler style", 1475 OPT_STRING('M', "disassembler-style", &top.annotation_opts.disassembler_style, "disassembler style",
@@ -1511,6 +1501,7 @@ int cmd_top(int argc, const char **argv)
1511 "number of thread to run event synthesize"), 1501 "number of thread to run event synthesize"),
1512 OPT_END() 1502 OPT_END()
1513 }; 1503 };
1504 struct perf_evlist *sb_evlist = NULL;
1514 const char * const top_usage[] = { 1505 const char * const top_usage[] = {
1515 "perf top [<options>]", 1506 "perf top [<options>]",
1516 NULL 1507 NULL
@@ -1628,8 +1619,9 @@ int cmd_top(int argc, const char **argv)
1628 annotation_config__init(); 1619 annotation_config__init();
1629 1620
1630 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1621 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1631 if (symbol__init(NULL) < 0) 1622 status = symbol__init(NULL);
1632 return -1; 1623 if (status < 0)
1624 goto out_delete_evlist;
1633 1625
1634 sort__setup_elide(stdout); 1626 sort__setup_elide(stdout);
1635 1627
@@ -1639,10 +1631,28 @@ int cmd_top(int argc, const char **argv)
1639 signal(SIGWINCH, winch_sig); 1631 signal(SIGWINCH, winch_sig);
1640 } 1632 }
1641 1633
1634 top.session = perf_session__new(NULL, false, NULL);
1635 if (top.session == NULL) {
1636 status = -1;
1637 goto out_delete_evlist;
1638 }
1639
1640 if (!top.record_opts.no_bpf_event)
1641 bpf_event__add_sb_event(&sb_evlist, &perf_env);
1642
1643 if (perf_evlist__start_sb_thread(sb_evlist, target)) {
1644 pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
1645 opts->no_bpf_event = true;
1646 }
1647
1642 status = __cmd_top(&top); 1648 status = __cmd_top(&top);
1643 1649
1650 if (!opts->no_bpf_event)
1651 perf_evlist__stop_sb_thread(sb_evlist);
1652
1644out_delete_evlist: 1653out_delete_evlist:
1645 perf_evlist__delete(top.evlist); 1654 perf_evlist__delete(top.evlist);
1655 perf_session__delete(top.session);
1646 1656
1647 return status; 1657 return status;
1648} 1658}
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index a11cb006f968..72df4b6fa36f 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -298,6 +298,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
298 use_pager = 1; 298 use_pager = 1;
299 commit_pager_choice(); 299 commit_pager_choice();
300 300
301 perf_env__init(&perf_env);
301 perf_env__set_cmdline(&perf_env, argc, argv); 302 perf_env__set_cmdline(&perf_env, argc, argv);
302 status = p->fn(argc, argv); 303 status = p->fn(argc, argv);
303 perf_config__exit(); 304 perf_config__exit();
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index b120e547ddc7..c59743def8d3 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -66,7 +66,7 @@ struct record_opts {
66 bool ignore_missing_thread; 66 bool ignore_missing_thread;
67 bool strict_freq; 67 bool strict_freq;
68 bool sample_id; 68 bool sample_id;
69 bool bpf_event; 69 bool no_bpf_event;
70 unsigned int freq; 70 unsigned int freq;
71 unsigned int mmap_pages; 71 unsigned int mmap_pages;
72 unsigned int auxtrace_mmap_pages; 72 unsigned int auxtrace_mmap_pages;
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/other.json b/tools/perf/pmu-events/arch/powerpc/power8/other.json
index 704302c3e67d..9dc2f6b70354 100644
--- a/tools/perf/pmu-events/arch/powerpc/power8/other.json
+++ b/tools/perf/pmu-events/arch/powerpc/power8/other.json
@@ -348,18 +348,6 @@
348 "PublicDescription": "" 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 "EventCode": "0x3608a", 351 "EventCode": "0x3608a",
364 "EventName": "PM_CO_USAGE", 352 "EventName": "PM_CO_USAGE",
365 "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", 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",
@@ -1578,36 +1566,12 @@
1578 "PublicDescription": "" 1566 "PublicDescription": ""
1579 }, 1567 },
1580 {, 1568 {,
1581 "EventCode": "0x617082",
1582 "EventName": "PM_ISIDE_DISP",
1583 "BriefDescription": "All i-side dispatch attempts",
1584 "PublicDescription": ""
1585 },
1586 {,
1587 "EventCode": "0x627084",
1588 "EventName": "PM_ISIDE_DISP_FAIL",
1589 "BriefDescription": "All i-side dispatch attempts that failed due to a addr collision with another machine",
1590 "PublicDescription": ""
1591 },
1592 {,
1593 "EventCode": "0x627086",
1594 "EventName": "PM_ISIDE_DISP_FAIL_OTHER",
1595 "BriefDescription": "All i-side dispatch attempts that failed due to a reason other than addrs collision",
1596 "PublicDescription": ""
1597 },
1598 {,
1599 "EventCode": "0x4608e", 1569 "EventCode": "0x4608e",
1600 "EventName": "PM_ISIDE_L2MEMACC", 1570 "EventName": "PM_ISIDE_L2MEMACC",
1601 "BriefDescription": "valid when first beat of data comes in for an i-side fetch where data came from mem(or L4)", 1571 "BriefDescription": "valid when first beat of data comes in for an i-side fetch where data came from mem(or L4)",
1602 "PublicDescription": "" 1572 "PublicDescription": ""
1603 }, 1573 },
1604 {, 1574 {,
1605 "EventCode": "0x44608e",
1606 "EventName": "PM_ISIDE_MRU_TOUCH",
1607 "BriefDescription": "Iside L2 MRU touch",
1608 "PublicDescription": ""
1609 },
1610 {,
1611 "EventCode": "0x30ac", 1575 "EventCode": "0x30ac",
1612 "EventName": "PM_ISU_REF_FX0", 1576 "EventName": "PM_ISU_REF_FX0",
1613 "BriefDescription": "FX0 ISU reject", 1577 "BriefDescription": "FX0 ISU reject",
@@ -1734,222 +1698,36 @@
1734 "PublicDescription": "" 1698 "PublicDescription": ""
1735 }, 1699 },
1736 {, 1700 {,
1737 "EventCode": "0x417080",
1738 "EventName": "PM_L2_CASTOUT_MOD",
1739 "BriefDescription": "L2 Castouts - Modified (M, Mu, Me)",
1740 "PublicDescription": ""
1741 },
1742 {,
1743 "EventCode": "0x417082",
1744 "EventName": "PM_L2_CASTOUT_SHR",
1745 "BriefDescription": "L2 Castouts - Shared (T, Te, Si, S)",
1746 "PublicDescription": ""
1747 },
1748 {,
1749 "EventCode": "0x27084", 1701 "EventCode": "0x27084",
1750 "EventName": "PM_L2_CHIP_PUMP", 1702 "EventName": "PM_L2_CHIP_PUMP",
1751 "BriefDescription": "RC requests that were local on chip pump attempts", 1703 "BriefDescription": "RC requests that were local on chip pump attempts",
1752 "PublicDescription": "" 1704 "PublicDescription": ""
1753 }, 1705 },
1754 {, 1706 {,
1755 "EventCode": "0x427086",
1756 "EventName": "PM_L2_DC_INV",
1757 "BriefDescription": "Dcache invalidates from L2",
1758 "PublicDescription": ""
1759 },
1760 {,
1761 "EventCode": "0x44608c",
1762 "EventName": "PM_L2_DISP_ALL_L2MISS",
1763 "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2miss",
1764 "PublicDescription": ""
1765 },
1766 {,
1767 "EventCode": "0x27086", 1707 "EventCode": "0x27086",
1768 "EventName": "PM_L2_GROUP_PUMP", 1708 "EventName": "PM_L2_GROUP_PUMP",
1769 "BriefDescription": "RC requests that were on Node Pump attempts", 1709 "BriefDescription": "RC requests that were on Node Pump attempts",
1770 "PublicDescription": "" 1710 "PublicDescription": ""
1771 }, 1711 },
1772 {, 1712 {,
1773 "EventCode": "0x626084",
1774 "EventName": "PM_L2_GRP_GUESS_CORRECT",
1775 "BriefDescription": "L2 guess grp and guess was correct (data intra-6chip AND ^on-chip)",
1776 "PublicDescription": ""
1777 },
1778 {,
1779 "EventCode": "0x626086",
1780 "EventName": "PM_L2_GRP_GUESS_WRONG",
1781 "BriefDescription": "L2 guess grp and guess was not correct (ie data on-chip OR beyond-6chip)",
1782 "PublicDescription": ""
1783 },
1784 {,
1785 "EventCode": "0x427084",
1786 "EventName": "PM_L2_IC_INV",
1787 "BriefDescription": "Icache Invalidates from L2",
1788 "PublicDescription": ""
1789 },
1790 {,
1791 "EventCode": "0x436088",
1792 "EventName": "PM_L2_INST",
1793 "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)",
1794 "PublicDescription": ""
1795 },
1796 {,
1797 "EventCode": "0x43608a",
1798 "EventName": "PM_L2_INST_MISS",
1799 "BriefDescription": "All successful i-side dispatches that were an L2miss for this thread (excludes i_l2mru_tch reqs)",
1800 "PublicDescription": ""
1801 },
1802 {,
1803 "EventCode": "0x416080",
1804 "EventName": "PM_L2_LD",
1805 "BriefDescription": "All successful D-side Load dispatches for this thread",
1806 "PublicDescription": ""
1807 },
1808 {,
1809 "EventCode": "0x437088",
1810 "EventName": "PM_L2_LD_DISP",
1811 "BriefDescription": "All successful load dispatches",
1812 "PublicDescription": ""
1813 },
1814 {,
1815 "EventCode": "0x43708a",
1816 "EventName": "PM_L2_LD_HIT",
1817 "BriefDescription": "All successful load dispatches that were L2 hits",
1818 "PublicDescription": ""
1819 },
1820 {,
1821 "EventCode": "0x426084",
1822 "EventName": "PM_L2_LD_MISS",
1823 "BriefDescription": "All successful D-Side Load dispatches that were an L2miss for this thread",
1824 "PublicDescription": ""
1825 },
1826 {,
1827 "EventCode": "0x616080",
1828 "EventName": "PM_L2_LOC_GUESS_CORRECT",
1829 "BriefDescription": "L2 guess loc and guess was correct (ie data local)",
1830 "PublicDescription": ""
1831 },
1832 {,
1833 "EventCode": "0x616082",
1834 "EventName": "PM_L2_LOC_GUESS_WRONG",
1835 "BriefDescription": "L2 guess loc and guess was not correct (ie data not on chip)",
1836 "PublicDescription": ""
1837 },
1838 {,
1839 "EventCode": "0x516080",
1840 "EventName": "PM_L2_RCLD_DISP",
1841 "BriefDescription": "L2 RC load dispatch attempt",
1842 "PublicDescription": ""
1843 },
1844 {,
1845 "EventCode": "0x516082",
1846 "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR",
1847 "BriefDescription": "L2 RC load dispatch attempt failed due to address collision with RC/CO/SN/SQ",
1848 "PublicDescription": ""
1849 },
1850 {,
1851 "EventCode": "0x526084",
1852 "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER",
1853 "BriefDescription": "L2 RC load dispatch attempt failed due to other reasons",
1854 "PublicDescription": ""
1855 },
1856 {,
1857 "EventCode": "0x536088",
1858 "EventName": "PM_L2_RCST_DISP",
1859 "BriefDescription": "L2 RC store dispatch attempt",
1860 "PublicDescription": ""
1861 },
1862 {,
1863 "EventCode": "0x53608a",
1864 "EventName": "PM_L2_RCST_DISP_FAIL_ADDR",
1865 "BriefDescription": "L2 RC store dispatch attempt failed due to address collision with RC/CO/SN/SQ",
1866 "PublicDescription": ""
1867 },
1868 {,
1869 "EventCode": "0x54608c",
1870 "EventName": "PM_L2_RCST_DISP_FAIL_OTHER",
1871 "BriefDescription": "L2 RC store dispatch attempt failed due to other reasons",
1872 "PublicDescription": ""
1873 },
1874 {,
1875 "EventCode": "0x537088",
1876 "EventName": "PM_L2_RC_ST_DONE",
1877 "BriefDescription": "RC did st to line that was Tx or Sx",
1878 "PublicDescription": ""
1879 },
1880 {,
1881 "EventCode": "0x63708a",
1882 "EventName": "PM_L2_RTY_LD",
1883 "BriefDescription": "RC retries on PB for any load from core",
1884 "PublicDescription": ""
1885 },
1886 {,
1887 "EventCode": "0x3708a", 1713 "EventCode": "0x3708a",
1888 "EventName": "PM_L2_RTY_ST", 1714 "EventName": "PM_L2_RTY_ST",
1889 "BriefDescription": "RC retries on PB for any store from core", 1715 "BriefDescription": "RC retries on PB for any store from core",
1890 "PublicDescription": "" 1716 "PublicDescription": ""
1891 }, 1717 },
1892 {, 1718 {,
1893 "EventCode": "0x54708c",
1894 "EventName": "PM_L2_SN_M_RD_DONE",
1895 "BriefDescription": "SNP dispatched for a read and was M",
1896 "PublicDescription": ""
1897 },
1898 {,
1899 "EventCode": "0x54708e",
1900 "EventName": "PM_L2_SN_M_WR_DONE",
1901 "BriefDescription": "SNP dispatched for a write and was M",
1902 "PublicDescription": ""
1903 },
1904 {,
1905 "EventCode": "0x53708a",
1906 "EventName": "PM_L2_SN_SX_I_DONE",
1907 "BriefDescription": "SNP dispatched and went from Sx or Tx to Ix",
1908 "PublicDescription": ""
1909 },
1910 {,
1911 "EventCode": "0x17080", 1719 "EventCode": "0x17080",
1912 "EventName": "PM_L2_ST", 1720 "EventName": "PM_L2_ST",
1913 "BriefDescription": "All successful D-side store dispatches for this thread", 1721 "BriefDescription": "All successful D-side store dispatches for this thread",
1914 "PublicDescription": "" 1722 "PublicDescription": ""
1915 }, 1723 },
1916 {, 1724 {,
1917 "EventCode": "0x44708c",
1918 "EventName": "PM_L2_ST_DISP",
1919 "BriefDescription": "All successful store dispatches",
1920 "PublicDescription": ""
1921 },
1922 {,
1923 "EventCode": "0x44708e",
1924 "EventName": "PM_L2_ST_HIT",
1925 "BriefDescription": "All successful store dispatches that were L2Hits",
1926 "PublicDescription": ""
1927 },
1928 {,
1929 "EventCode": "0x17082", 1725 "EventCode": "0x17082",
1930 "EventName": "PM_L2_ST_MISS", 1726 "EventName": "PM_L2_ST_MISS",
1931 "BriefDescription": "All successful D-side store dispatches for this thread that were L2 Miss", 1727 "BriefDescription": "All successful D-side store dispatches for this thread that were L2 Miss",
1932 "PublicDescription": "" 1728 "PublicDescription": ""
1933 }, 1729 },
1934 {, 1730 {,
1935 "EventCode": "0x636088",
1936 "EventName": "PM_L2_SYS_GUESS_CORRECT",
1937 "BriefDescription": "L2 guess sys and guess was correct (ie data beyond-6chip)",
1938 "PublicDescription": ""
1939 },
1940 {,
1941 "EventCode": "0x63608a",
1942 "EventName": "PM_L2_SYS_GUESS_WRONG",
1943 "BriefDescription": "L2 guess sys and guess was not correct (ie data ^beyond-6chip)",
1944 "PublicDescription": ""
1945 },
1946 {,
1947 "EventCode": "0x617080",
1948 "EventName": "PM_L2_SYS_PUMP",
1949 "BriefDescription": "RC requests that were system pump attempts",
1950 "PublicDescription": ""
1951 },
1952 {,
1953 "EventCode": "0x1e05e", 1731 "EventCode": "0x1e05e",
1954 "EventName": "PM_L2_TM_REQ_ABORT", 1732 "EventName": "PM_L2_TM_REQ_ABORT",
1955 "BriefDescription": "TM abort", 1733 "BriefDescription": "TM abort",
@@ -1962,36 +1740,12 @@
1962 "PublicDescription": "" 1740 "PublicDescription": ""
1963 }, 1741 },
1964 {, 1742 {,
1965 "EventCode": "0x23808a",
1966 "EventName": "PM_L3_CINJ",
1967 "BriefDescription": "l3 ci of cache inject",
1968 "PublicDescription": ""
1969 },
1970 {,
1971 "EventCode": "0x128084",
1972 "EventName": "PM_L3_CI_HIT",
1973 "BriefDescription": "L3 Castins Hit (total count",
1974 "PublicDescription": ""
1975 },
1976 {,
1977 "EventCode": "0x128086",
1978 "EventName": "PM_L3_CI_MISS",
1979 "BriefDescription": "L3 castins miss (total count",
1980 "PublicDescription": ""
1981 },
1982 {,
1983 "EventCode": "0x819082", 1743 "EventCode": "0x819082",
1984 "EventName": "PM_L3_CI_USAGE", 1744 "EventName": "PM_L3_CI_USAGE",
1985 "BriefDescription": "rotating sample of 16 CI or CO actives", 1745 "BriefDescription": "rotating sample of 16 CI or CO actives",
1986 "PublicDescription": "" 1746 "PublicDescription": ""
1987 }, 1747 },
1988 {, 1748 {,
1989 "EventCode": "0x438088",
1990 "EventName": "PM_L3_CO",
1991 "BriefDescription": "l3 castout occurring ( does not include casthrough or log writes (cinj/dmaw)",
1992 "PublicDescription": ""
1993 },
1994 {,
1995 "EventCode": "0x83908b", 1749 "EventCode": "0x83908b",
1996 "EventName": "PM_L3_CO0_ALLOC", 1750 "EventName": "PM_L3_CO0_ALLOC",
1997 "BriefDescription": "lifetime, sample of CO machine 0 valid", 1751 "BriefDescription": "lifetime, sample of CO machine 0 valid",
@@ -2010,120 +1764,18 @@
2010 "PublicDescription": "" 1764 "PublicDescription": ""
2011 }, 1765 },
2012 {, 1766 {,
2013 "EventCode": "0x238088",
2014 "EventName": "PM_L3_CO_LCO",
2015 "BriefDescription": "Total L3 castouts occurred on LCO",
2016 "PublicDescription": ""
2017 },
2018 {,
2019 "EventCode": "0x28084", 1767 "EventCode": "0x28084",
2020 "EventName": "PM_L3_CO_MEM", 1768 "EventName": "PM_L3_CO_MEM",
2021 "BriefDescription": "L3 CO to memory OR of port 0 and 1 ( lossy)", 1769 "BriefDescription": "L3 CO to memory OR of port 0 and 1 ( lossy)",
2022 "PublicDescription": "" 1770 "PublicDescription": ""
2023 }, 1771 },
2024 {, 1772 {,
2025 "EventCode": "0xb19082",
2026 "EventName": "PM_L3_GRP_GUESS_CORRECT",
2027 "BriefDescription": "Initial scope=group and data from same group (near) (pred successful)",
2028 "PublicDescription": ""
2029 },
2030 {,
2031 "EventCode": "0xb3908a",
2032 "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH",
2033 "BriefDescription": "Initial scope=group but data from local node. Predition too high",
2034 "PublicDescription": ""
2035 },
2036 {,
2037 "EventCode": "0xb39088",
2038 "EventName": "PM_L3_GRP_GUESS_WRONG_LOW",
2039 "BriefDescription": "Initial scope=group but data from outside group (far or rem). Prediction too Low",
2040 "PublicDescription": ""
2041 },
2042 {,
2043 "EventCode": "0x218080",
2044 "EventName": "PM_L3_HIT",
2045 "BriefDescription": "L3 Hits",
2046 "PublicDescription": ""
2047 },
2048 {,
2049 "EventCode": "0x138088",
2050 "EventName": "PM_L3_L2_CO_HIT",
2051 "BriefDescription": "L2 castout hits",
2052 "PublicDescription": ""
2053 },
2054 {,
2055 "EventCode": "0x13808a",
2056 "EventName": "PM_L3_L2_CO_MISS",
2057 "BriefDescription": "L2 castout miss",
2058 "PublicDescription": ""
2059 },
2060 {,
2061 "EventCode": "0x14808c",
2062 "EventName": "PM_L3_LAT_CI_HIT",
2063 "BriefDescription": "L3 Lateral Castins Hit",
2064 "PublicDescription": ""
2065 },
2066 {,
2067 "EventCode": "0x14808e",
2068 "EventName": "PM_L3_LAT_CI_MISS",
2069 "BriefDescription": "L3 Lateral Castins Miss",
2070 "PublicDescription": ""
2071 },
2072 {,
2073 "EventCode": "0x228084",
2074 "EventName": "PM_L3_LD_HIT",
2075 "BriefDescription": "L3 demand LD Hits",
2076 "PublicDescription": ""
2077 },
2078 {,
2079 "EventCode": "0x228086",
2080 "EventName": "PM_L3_LD_MISS",
2081 "BriefDescription": "L3 demand LD Miss",
2082 "PublicDescription": ""
2083 },
2084 {,
2085 "EventCode": "0x1e052", 1773 "EventCode": "0x1e052",
2086 "EventName": "PM_L3_LD_PREF", 1774 "EventName": "PM_L3_LD_PREF",
2087 "BriefDescription": "L3 Load Prefetches", 1775 "BriefDescription": "L3 Load Prefetches",
2088 "PublicDescription": "" 1776 "PublicDescription": ""
2089 }, 1777 },
2090 {, 1778 {,
2091 "EventCode": "0xb19080",
2092 "EventName": "PM_L3_LOC_GUESS_CORRECT",
2093 "BriefDescription": "initial scope=node/chip and data from local node (local) (pred successful)",
2094 "PublicDescription": ""
2095 },
2096 {,
2097 "EventCode": "0xb29086",
2098 "EventName": "PM_L3_LOC_GUESS_WRONG",
2099 "BriefDescription": "Initial scope=node but data from out side local node (near or far or rem). Prediction too Low",
2100 "PublicDescription": ""
2101 },
2102 {,
2103 "EventCode": "0x218082",
2104 "EventName": "PM_L3_MISS",
2105 "BriefDescription": "L3 Misses",
2106 "PublicDescription": ""
2107 },
2108 {,
2109 "EventCode": "0x54808c",
2110 "EventName": "PM_L3_P0_CO_L31",
2111 "BriefDescription": "l3 CO to L3.1 (lco) port 0",
2112 "PublicDescription": ""
2113 },
2114 {,
2115 "EventCode": "0x538088",
2116 "EventName": "PM_L3_P0_CO_MEM",
2117 "BriefDescription": "l3 CO to memory port 0",
2118 "PublicDescription": ""
2119 },
2120 {,
2121 "EventCode": "0x929084",
2122 "EventName": "PM_L3_P0_CO_RTY",
2123 "BriefDescription": "L3 CO received retry port 0",
2124 "PublicDescription": ""
2125 },
2126 {,
2127 "EventCode": "0xa29084", 1779 "EventCode": "0xa29084",
2128 "EventName": "PM_L3_P0_GRP_PUMP", 1780 "EventName": "PM_L3_P0_GRP_PUMP",
2129 "BriefDescription": "L3 pf sent with grp scope port 0", 1781 "BriefDescription": "L3 pf sent with grp scope port 0",
@@ -2148,120 +1800,6 @@
2148 "PublicDescription": "" 1800 "PublicDescription": ""
2149 }, 1801 },
2150 {, 1802 {,
2151 "EventCode": "0xa19080",
2152 "EventName": "PM_L3_P0_NODE_PUMP",
2153 "BriefDescription": "L3 pf sent with nodal scope port 0",
2154 "PublicDescription": ""
2155 },
2156 {,
2157 "EventCode": "0x919080",
2158 "EventName": "PM_L3_P0_PF_RTY",
2159 "BriefDescription": "L3 PF received retry port 0",
2160 "PublicDescription": ""
2161 },
2162 {,
2163 "EventCode": "0x939088",
2164 "EventName": "PM_L3_P0_SN_HIT",
2165 "BriefDescription": "L3 snoop hit port 0",
2166 "PublicDescription": ""
2167 },
2168 {,
2169 "EventCode": "0x118080",
2170 "EventName": "PM_L3_P0_SN_INV",
2171 "BriefDescription": "Port0 snooper detects someone doing a store to a line thats Sx",
2172 "PublicDescription": ""
2173 },
2174 {,
2175 "EventCode": "0x94908c",
2176 "EventName": "PM_L3_P0_SN_MISS",
2177 "BriefDescription": "L3 snoop miss port 0",
2178 "PublicDescription": ""
2179 },
2180 {,
2181 "EventCode": "0xa39088",
2182 "EventName": "PM_L3_P0_SYS_PUMP",
2183 "BriefDescription": "L3 pf sent with sys scope port 0",
2184 "PublicDescription": ""
2185 },
2186 {,
2187 "EventCode": "0x54808e",
2188 "EventName": "PM_L3_P1_CO_L31",
2189 "BriefDescription": "l3 CO to L3.1 (lco) port 1",
2190 "PublicDescription": ""
2191 },
2192 {,
2193 "EventCode": "0x53808a",
2194 "EventName": "PM_L3_P1_CO_MEM",
2195 "BriefDescription": "l3 CO to memory port 1",
2196 "PublicDescription": ""
2197 },
2198 {,
2199 "EventCode": "0x929086",
2200 "EventName": "PM_L3_P1_CO_RTY",
2201 "BriefDescription": "L3 CO received retry port 1",
2202 "PublicDescription": ""
2203 },
2204 {,
2205 "EventCode": "0xa29086",
2206 "EventName": "PM_L3_P1_GRP_PUMP",
2207 "BriefDescription": "L3 pf sent with grp scope port 1",
2208 "PublicDescription": ""
2209 },
2210 {,
2211 "EventCode": "0x528086",
2212 "EventName": "PM_L3_P1_LCO_DATA",
2213 "BriefDescription": "lco sent with data port 1",
2214 "PublicDescription": ""
2215 },
2216 {,
2217 "EventCode": "0x518082",
2218 "EventName": "PM_L3_P1_LCO_NO_DATA",
2219 "BriefDescription": "dataless l3 lco sent port 1",
2220 "PublicDescription": ""
2221 },
2222 {,
2223 "EventCode": "0xa4908e",
2224 "EventName": "PM_L3_P1_LCO_RTY",
2225 "BriefDescription": "L3 LCO received retry port 1",
2226 "PublicDescription": ""
2227 },
2228 {,
2229 "EventCode": "0xa19082",
2230 "EventName": "PM_L3_P1_NODE_PUMP",
2231 "BriefDescription": "L3 pf sent with nodal scope port 1",
2232 "PublicDescription": ""
2233 },
2234 {,
2235 "EventCode": "0x919082",
2236 "EventName": "PM_L3_P1_PF_RTY",
2237 "BriefDescription": "L3 PF received retry port 1",
2238 "PublicDescription": ""
2239 },
2240 {,
2241 "EventCode": "0x93908a",
2242 "EventName": "PM_L3_P1_SN_HIT",
2243 "BriefDescription": "L3 snoop hit port 1",
2244 "PublicDescription": ""
2245 },
2246 {,
2247 "EventCode": "0x118082",
2248 "EventName": "PM_L3_P1_SN_INV",
2249 "BriefDescription": "Port1 snooper detects someone doing a store to a line thats Sx",
2250 "PublicDescription": ""
2251 },
2252 {,
2253 "EventCode": "0x94908e",
2254 "EventName": "PM_L3_P1_SN_MISS",
2255 "BriefDescription": "L3 snoop miss port 1",
2256 "PublicDescription": ""
2257 },
2258 {,
2259 "EventCode": "0xa3908a",
2260 "EventName": "PM_L3_P1_SYS_PUMP",
2261 "BriefDescription": "L3 pf sent with sys scope port 1",
2262 "PublicDescription": ""
2263 },
2264 {,
2265 "EventCode": "0x84908d", 1803 "EventCode": "0x84908d",
2266 "EventName": "PM_L3_PF0_ALLOC", 1804 "EventName": "PM_L3_PF0_ALLOC",
2267 "BriefDescription": "lifetime, sample of PF machine 0 valid", 1805 "BriefDescription": "lifetime, sample of PF machine 0 valid",
@@ -2274,12 +1812,6 @@
2274 "PublicDescription": "" 1812 "PublicDescription": ""
2275 }, 1813 },
2276 {, 1814 {,
2277 "EventCode": "0x428084",
2278 "EventName": "PM_L3_PF_HIT_L3",
2279 "BriefDescription": "l3 pf hit in l3",
2280 "PublicDescription": ""
2281 },
2282 {,
2283 "EventCode": "0x18080", 1815 "EventCode": "0x18080",
2284 "EventName": "PM_L3_PF_MISS_L3", 1816 "EventName": "PM_L3_PF_MISS_L3",
2285 "BriefDescription": "L3 Prefetch missed in L3", 1817 "BriefDescription": "L3 Prefetch missed in L3",
@@ -2370,42 +1902,12 @@
2370 "PublicDescription": "" 1902 "PublicDescription": ""
2371 }, 1903 },
2372 {, 1904 {,
2373 "EventCode": "0xb29084",
2374 "EventName": "PM_L3_SYS_GUESS_CORRECT",
2375 "BriefDescription": "Initial scope=system and data from outside group (far or rem)(pred successful)",
2376 "PublicDescription": ""
2377 },
2378 {,
2379 "EventCode": "0xb4908c",
2380 "EventName": "PM_L3_SYS_GUESS_WRONG",
2381 "BriefDescription": "Initial scope=system but data from local or near. Predction too high",
2382 "PublicDescription": ""
2383 },
2384 {,
2385 "EventCode": "0x24808e",
2386 "EventName": "PM_L3_TRANS_PF",
2387 "BriefDescription": "L3 Transient prefetch",
2388 "PublicDescription": ""
2389 },
2390 {,
2391 "EventCode": "0x18081", 1905 "EventCode": "0x18081",
2392 "EventName": "PM_L3_WI0_ALLOC", 1906 "EventName": "PM_L3_WI0_ALLOC",
2393 "BriefDescription": "lifetime, sample of Write Inject machine 0 valid", 1907 "BriefDescription": "lifetime, sample of Write Inject machine 0 valid",
2394 "PublicDescription": "0.0" 1908 "PublicDescription": "0.0"
2395 }, 1909 },
2396 {, 1910 {,
2397 "EventCode": "0x418080",
2398 "EventName": "PM_L3_WI0_BUSY",
2399 "BriefDescription": "lifetime, sample of Write Inject machine 0 valid",
2400 "PublicDescription": ""
2401 },
2402 {,
2403 "EventCode": "0x418082",
2404 "EventName": "PM_L3_WI_USAGE",
2405 "BriefDescription": "rotating sample of 8 WI actives",
2406 "PublicDescription": ""
2407 },
2408 {,
2409 "EventCode": "0xc080", 1911 "EventCode": "0xc080",
2410 "EventName": "PM_LD_REF_L1_LSU0", 1912 "EventName": "PM_LD_REF_L1_LSU0",
2411 "BriefDescription": "LS0 L1 D cache load references counted at finish, gated by reject", 1913 "BriefDescription": "LS0 L1 D cache load references counted at finish, gated by reject",
@@ -3312,12 +2814,6 @@
3312 "PublicDescription": "" 2814 "PublicDescription": ""
3313 }, 2815 },
3314 {, 2816 {,
3315 "EventCode": "0x328084",
3316 "EventName": "PM_NON_TM_RST_SC",
3317 "BriefDescription": "non tm snp rst tm sc",
3318 "PublicDescription": ""
3319 },
3320 {,
3321 "EventCode": "0x2001a", 2817 "EventCode": "0x2001a",
3322 "EventName": "PM_NTCG_ALL_FIN", 2818 "EventName": "PM_NTCG_ALL_FIN",
3323 "BriefDescription": "Cycles after all instructions have finished to group completed", 2819 "BriefDescription": "Cycles after all instructions have finished to group completed",
@@ -3420,24 +2916,6 @@
3420 "PublicDescription": "" 2916 "PublicDescription": ""
3421 }, 2917 },
3422 {, 2918 {,
3423 "EventCode": "0x34808e",
3424 "EventName": "PM_RD_CLEARING_SC",
3425 "BriefDescription": "rd clearing sc",
3426 "PublicDescription": ""
3427 },
3428 {,
3429 "EventCode": "0x34808c",
3430 "EventName": "PM_RD_FORMING_SC",
3431 "BriefDescription": "rd forming sc",
3432 "PublicDescription": ""
3433 },
3434 {,
3435 "EventCode": "0x428086",
3436 "EventName": "PM_RD_HIT_PF",
3437 "BriefDescription": "rd machine hit l3 pf machine",
3438 "PublicDescription": ""
3439 },
3440 {,
3441 "EventCode": "0x20004", 2919 "EventCode": "0x20004",
3442 "EventName": "PM_REAL_SRQ_FULL", 2920 "EventName": "PM_REAL_SRQ_FULL",
3443 "BriefDescription": "Out of real srq entries", 2921 "BriefDescription": "Out of real srq entries",
@@ -3504,18 +2982,6 @@
3504 "PublicDescription": "TLBIE snoopSnoop TLBIE" 2982 "PublicDescription": "TLBIE snoopSnoop TLBIE"
3505 }, 2983 },
3506 {, 2984 {,
3507 "EventCode": "0x338088",
3508 "EventName": "PM_SNP_TM_HIT_M",
3509 "BriefDescription": "snp tm st hit m mu",
3510 "PublicDescription": ""
3511 },
3512 {,
3513 "EventCode": "0x33808a",
3514 "EventName": "PM_SNP_TM_HIT_T",
3515 "BriefDescription": "snp tm_st_hit t tn te",
3516 "PublicDescription": ""
3517 },
3518 {,
3519 "EventCode": "0x4608c", 2985 "EventCode": "0x4608c",
3520 "EventName": "PM_SN_USAGE", 2986 "EventName": "PM_SN_USAGE",
3521 "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", 2987 "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",
@@ -3534,12 +3000,6 @@
3534 "PublicDescription": "STCX executed reported at sent to nest42" 3000 "PublicDescription": "STCX executed reported at sent to nest42"
3535 }, 3001 },
3536 {, 3002 {,
3537 "EventCode": "0x717080",
3538 "EventName": "PM_ST_CAUSED_FAIL",
3539 "BriefDescription": "Non TM St caused any thread to fail",
3540 "PublicDescription": ""
3541 },
3542 {,
3543 "EventCode": "0x3090", 3003 "EventCode": "0x3090",
3544 "EventName": "PM_SWAP_CANCEL", 3004 "EventName": "PM_SWAP_CANCEL",
3545 "BriefDescription": "SWAP cancel , rtag not available", 3005 "BriefDescription": "SWAP cancel , rtag not available",
@@ -3624,18 +3084,6 @@
3624 "PublicDescription": "" 3084 "PublicDescription": ""
3625 }, 3085 },
3626 {, 3086 {,
3627 "EventCode": "0x318082",
3628 "EventName": "PM_TM_CAM_OVERFLOW",
3629 "BriefDescription": "l3 tm cam overflow during L2 co of SC",
3630 "PublicDescription": ""
3631 },
3632 {,
3633 "EventCode": "0x74708c",
3634 "EventName": "PM_TM_CAP_OVERFLOW",
3635 "BriefDescription": "TM Footprint Capactiy Overflow",
3636 "PublicDescription": ""
3637 },
3638 {,
3639 "EventCode": "0x20ba", 3087 "EventCode": "0x20ba",
3640 "EventName": "PM_TM_END_ALL", 3088 "EventName": "PM_TM_END_ALL",
3641 "BriefDescription": "Tm any tend", 3089 "BriefDescription": "Tm any tend",
@@ -3690,48 +3138,6 @@
3690 "PublicDescription": "Transactional conflict from LSU, whatever gets reported to texas 42" 3138 "PublicDescription": "Transactional conflict from LSU, whatever gets reported to texas 42"
3691 }, 3139 },
3692 {, 3140 {,
3693 "EventCode": "0x727086",
3694 "EventName": "PM_TM_FAV_CAUSED_FAIL",
3695 "BriefDescription": "TM Load (fav) caused another thread to fail",
3696 "PublicDescription": ""
3697 },
3698 {,
3699 "EventCode": "0x717082",
3700 "EventName": "PM_TM_LD_CAUSED_FAIL",
3701 "BriefDescription": "Non TM Ld caused any thread to fail",
3702 "PublicDescription": ""
3703 },
3704 {,
3705 "EventCode": "0x727084",
3706 "EventName": "PM_TM_LD_CONF",
3707 "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)",
3708 "PublicDescription": ""
3709 },
3710 {,
3711 "EventCode": "0x328086",
3712 "EventName": "PM_TM_RST_SC",
3713 "BriefDescription": "tm snp rst tm sc",
3714 "PublicDescription": ""
3715 },
3716 {,
3717 "EventCode": "0x318080",
3718 "EventName": "PM_TM_SC_CO",
3719 "BriefDescription": "l3 castout tm Sc line",
3720 "PublicDescription": ""
3721 },
3722 {,
3723 "EventCode": "0x73708a",
3724 "EventName": "PM_TM_ST_CAUSED_FAIL",
3725 "BriefDescription": "TM Store (fav or non-fav) caused another thread to fail",
3726 "PublicDescription": ""
3727 },
3728 {,
3729 "EventCode": "0x737088",
3730 "EventName": "PM_TM_ST_CONF",
3731 "BriefDescription": "TM Store (fav or non-fav) ran into conflict (failed)",
3732 "PublicDescription": ""
3733 },
3734 {,
3735 "EventCode": "0x20bc", 3141 "EventCode": "0x20bc",
3736 "EventName": "PM_TM_TBEGIN", 3142 "EventName": "PM_TM_TBEGIN",
3737 "BriefDescription": "Tm nested tbegin", 3143 "BriefDescription": "Tm nested tbegin",
diff --git a/tools/perf/tests/attr/test-record-C0 b/tools/perf/tests/attr/test-record-C0
index cb0a3138fa54..93818054ae20 100644
--- a/tools/perf/tests/attr/test-record-C0
+++ b/tools/perf/tests/attr/test-record-C0
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -C 0 kill >/dev/null 2>&1 3args = --no-bpf-event -C 0 kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-basic b/tools/perf/tests/attr/test-record-basic
index 85a23cf35ba1..b0ca42a5ecc9 100644
--- a/tools/perf/tests/attr/test-record-basic
+++ b/tools/perf/tests/attr/test-record-basic
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = kill >/dev/null 2>&1 3args = --no-bpf-event kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-any b/tools/perf/tests/attr/test-record-branch-any
index 81f839e2fad0..1a99b3ce6b89 100644
--- a/tools/perf/tests/attr/test-record-branch-any
+++ b/tools/perf/tests/attr/test-record-branch-any
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -b kill >/dev/null 2>&1 3args = --no-bpf-event -b kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any b/tools/perf/tests/attr/test-record-branch-filter-any
index 357421f4dfce..709768b508c6 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-any
+++ b/tools/perf/tests/attr/test-record-branch-filter-any
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -j any kill >/dev/null 2>&1 3args = --no-bpf-event -j any kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_call b/tools/perf/tests/attr/test-record-branch-filter-any_call
index dbc55f2ab845..f943221f7825 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-any_call
+++ b/tools/perf/tests/attr/test-record-branch-filter-any_call
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -j any_call kill >/dev/null 2>&1 3args = --no-bpf-event -j any_call kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_ret b/tools/perf/tests/attr/test-record-branch-filter-any_ret
index a0824ff8e131..fd4f5b4154a9 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-any_ret
+++ b/tools/perf/tests/attr/test-record-branch-filter-any_ret
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -j any_ret kill >/dev/null 2>&1 3args = --no-bpf-event -j any_ret kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-filter-hv b/tools/perf/tests/attr/test-record-branch-filter-hv
index f34d6f120181..4e52d685ebe1 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-hv
+++ b/tools/perf/tests/attr/test-record-branch-filter-hv
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -j hv kill >/dev/null 2>&1 3args = --no-bpf-event -j hv kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-filter-ind_call b/tools/perf/tests/attr/test-record-branch-filter-ind_call
index b86a35232248..e08c6ab3796e 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-ind_call
+++ b/tools/perf/tests/attr/test-record-branch-filter-ind_call
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -j ind_call kill >/dev/null 2>&1 3args = --no-bpf-event -j ind_call kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-filter-k b/tools/perf/tests/attr/test-record-branch-filter-k
index d3fbc5e1858a..b4b98f84fc2f 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-k
+++ b/tools/perf/tests/attr/test-record-branch-filter-k
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -j k kill >/dev/null 2>&1 3args = --no-bpf-event -j k kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-filter-u b/tools/perf/tests/attr/test-record-branch-filter-u
index a318f0dda173..fb9610edbb0d 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-u
+++ b/tools/perf/tests/attr/test-record-branch-filter-u
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -j u kill >/dev/null 2>&1 3args = --no-bpf-event -j u kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-count b/tools/perf/tests/attr/test-record-count
index 34f6cc577263..5e9b9019d786 100644
--- a/tools/perf/tests/attr/test-record-count
+++ b/tools/perf/tests/attr/test-record-count
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -c 123 kill >/dev/null 2>&1 3args = --no-bpf-event -c 123 kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-data b/tools/perf/tests/attr/test-record-data
index a9cf2233b0ce..a99bb13149c2 100644
--- a/tools/perf/tests/attr/test-record-data
+++ b/tools/perf/tests/attr/test-record-data
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -d kill >/dev/null 2>&1 3args = --no-bpf-event -d kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-freq b/tools/perf/tests/attr/test-record-freq
index bf4cb459f0d5..89e29f6b2ae0 100644
--- a/tools/perf/tests/attr/test-record-freq
+++ b/tools/perf/tests/attr/test-record-freq
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -F 100 kill >/dev/null 2>&1 3args = --no-bpf-event -F 100 kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-graph-default b/tools/perf/tests/attr/test-record-graph-default
index 0b216e69760c..5d8234d50845 100644
--- a/tools/perf/tests/attr/test-record-graph-default
+++ b/tools/perf/tests/attr/test-record-graph-default
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -g kill >/dev/null 2>&1 3args = --no-bpf-event -g kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf
index da2fa73bd0a2..ae92061d611d 100644
--- a/tools/perf/tests/attr/test-record-graph-dwarf
+++ b/tools/perf/tests/attr/test-record-graph-dwarf
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = --call-graph dwarf -- kill >/dev/null 2>&1 3args = --no-bpf-event --call-graph dwarf -- kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-graph-fp b/tools/perf/tests/attr/test-record-graph-fp
index 625d190bb798..5630521c0b0f 100644
--- a/tools/perf/tests/attr/test-record-graph-fp
+++ b/tools/perf/tests/attr/test-record-graph-fp
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = --call-graph fp kill >/dev/null 2>&1 3args = --no-bpf-event --call-graph fp kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group
index 618ba1c17474..14ee60fd3f41 100644
--- a/tools/perf/tests/attr/test-record-group
+++ b/tools/perf/tests/attr/test-record-group
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = --group -e cycles,instructions kill >/dev/null 2>&1 3args = --no-bpf-event --group -e cycles,instructions kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event-1:base-record] 6[event-1:base-record]
diff --git a/tools/perf/tests/attr/test-record-group-sampling b/tools/perf/tests/attr/test-record-group-sampling
index f0729c454f16..300b9f7e6d69 100644
--- a/tools/perf/tests/attr/test-record-group-sampling
+++ b/tools/perf/tests/attr/test-record-group-sampling
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 3args = --no-bpf-event -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event-1:base-record] 6[event-1:base-record]
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
index 48e8bd12fe46..3ffe246e0228 100644
--- a/tools/perf/tests/attr/test-record-group1
+++ b/tools/perf/tests/attr/test-record-group1
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -e '{cycles,instructions}' kill >/dev/null 2>&1 3args = --no-bpf-event -e '{cycles,instructions}' kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event-1:base-record] 6[event-1:base-record]
diff --git a/tools/perf/tests/attr/test-record-no-buffering b/tools/perf/tests/attr/test-record-no-buffering
index aa3956d8fe20..583dcbb078ba 100644
--- a/tools/perf/tests/attr/test-record-no-buffering
+++ b/tools/perf/tests/attr/test-record-no-buffering
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = --no-buffering kill >/dev/null 2>&1 3args = --no-bpf-event --no-buffering kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-no-inherit b/tools/perf/tests/attr/test-record-no-inherit
index 560943decb87..15d1dc162e1c 100644
--- a/tools/perf/tests/attr/test-record-no-inherit
+++ b/tools/perf/tests/attr/test-record-no-inherit
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -i kill >/dev/null 2>&1 3args = --no-bpf-event -i kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-no-samples b/tools/perf/tests/attr/test-record-no-samples
index 8eb73ab639e0..596fbd6d5a2c 100644
--- a/tools/perf/tests/attr/test-record-no-samples
+++ b/tools/perf/tests/attr/test-record-no-samples
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -n kill >/dev/null 2>&1 3args = --no-bpf-event -n kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-period b/tools/perf/tests/attr/test-record-period
index 69bc748f0f27..119101154c5e 100644
--- a/tools/perf/tests/attr/test-record-period
+++ b/tools/perf/tests/attr/test-record-period
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -c 100 -P kill >/dev/null 2>&1 3args = --no-bpf-event -c 100 -P kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-raw b/tools/perf/tests/attr/test-record-raw
index a188a614a44c..13a5f7860c78 100644
--- a/tools/perf/tests/attr/test-record-raw
+++ b/tools/perf/tests/attr/test-record-raw
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -R kill >/dev/null 2>&1 3args = --no-bpf-event -R kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index 6d598cc071ae..1a9c3becf5ff 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -18,7 +18,7 @@ static void testcase(void)
18 int i; 18 int i;
19 19
20 for (i = 0; i < NR_ITERS; i++) { 20 for (i = 0; i < NR_ITERS; i++) {
21 char proc_name[10]; 21 char proc_name[15];
22 22
23 snprintf(proc_name, sizeof(proc_name), "p:%d\n", i); 23 snprintf(proc_name, sizeof(proc_name), "p:%d\n", i);
24 prctl(PR_SET_NAME, proc_name); 24 prctl(PR_SET_NAME, proc_name);
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index ea7acf403727..71f60c0f9faa 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -85,5 +85,6 @@ int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtes
85 if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) 85 if (perf_evsel__test_field(evsel, "target_cpu", 4, true))
86 ret = -1; 86 ret = -1;
87 87
88 perf_evsel__delete(evsel);
88 return ret; 89 return ret;
89} 90}
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
index 01f0706995a9..9acc1e80b936 100644
--- a/tools/perf/tests/expr.c
+++ b/tools/perf/tests/expr.c
@@ -19,7 +19,7 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
19 const char *p; 19 const char *p;
20 const char **other; 20 const char **other;
21 double val; 21 double val;
22 int ret; 22 int i, ret;
23 struct parse_ctx ctx; 23 struct parse_ctx ctx;
24 int num_other; 24 int num_other;
25 25
@@ -56,6 +56,9 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
56 TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ")); 56 TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ"));
57 TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO")); 57 TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO"));
58 TEST_ASSERT_VAL("find other", other[3] == NULL); 58 TEST_ASSERT_VAL("find other", other[3] == NULL);
59
60 for (i = 0; i < num_other; i++)
61 free((void *)other[i]);
59 free((void *)other); 62 free((void *)other);
60 63
61 return 0; 64 return 0;
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index c531e6deb104..493ecb611540 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -45,7 +45,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int
45 if (IS_ERR(evsel)) { 45 if (IS_ERR(evsel)) {
46 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat"); 46 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
47 pr_debug("%s\n", errbuf); 47 pr_debug("%s\n", errbuf);
48 goto out_thread_map_delete; 48 goto out_cpu_map_delete;
49 } 49 }
50 50
51 if (perf_evsel__open(evsel, cpus, threads) < 0) { 51 if (perf_evsel__open(evsel, cpus, threads) < 0) {
@@ -119,6 +119,8 @@ out_close_fd:
119 perf_evsel__close_fd(evsel); 119 perf_evsel__close_fd(evsel);
120out_evsel_delete: 120out_evsel_delete:
121 perf_evsel__delete(evsel); 121 perf_evsel__delete(evsel);
122out_cpu_map_delete:
123 cpu_map__put(cpus);
122out_thread_map_delete: 124out_thread_map_delete:
123 thread_map__put(threads); 125 thread_map__put(threads);
124 return err; 126 return err;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 5f6dbbf5d749..c8b01176c9e1 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -10,6 +10,10 @@
10#include <errno.h> 10#include <errno.h>
11#include <inttypes.h> 11#include <inttypes.h>
12#include <libgen.h> 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#include "util.h" 17#include "util.h"
14#include "ui/ui.h" 18#include "ui/ui.h"
15#include "sort.h" 19#include "sort.h"
@@ -24,6 +28,7 @@
24#include "annotate.h" 28#include "annotate.h"
25#include "evsel.h" 29#include "evsel.h"
26#include "evlist.h" 30#include "evlist.h"
31#include "bpf-event.h"
27#include "block-range.h" 32#include "block-range.h"
28#include "string2.h" 33#include "string2.h"
29#include "arch/common.h" 34#include "arch/common.h"
@@ -31,6 +36,7 @@
31#include <pthread.h> 36#include <pthread.h>
32#include <linux/bitops.h> 37#include <linux/bitops.h>
33#include <linux/kernel.h> 38#include <linux/kernel.h>
39#include <bpf/libbpf.h>
34 40
35/* FIXME: For the HE_COLORSET */ 41/* FIXME: For the HE_COLORSET */
36#include "ui/browser.h" 42#include "ui/browser.h"
@@ -1615,6 +1621,9 @@ int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *
1615 " --vmlinux vmlinux\n", build_id_msg ?: ""); 1621 " --vmlinux vmlinux\n", build_id_msg ?: "");
1616 } 1622 }
1617 break; 1623 break;
1624 case SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF:
1625 scnprintf(buf, buflen, "Please link with binutils's libopcode to enable BPF annotation");
1626 break;
1618 default: 1627 default:
1619 scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum); 1628 scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
1620 break; 1629 break;
@@ -1674,6 +1683,156 @@ fallback:
1674 return 0; 1683 return 0;
1675} 1684}
1676 1685
1686#if defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1687#define PACKAGE "perf"
1688#include <bfd.h>
1689#include <dis-asm.h>
1690
1691static int symbol__disassemble_bpf(struct symbol *sym,
1692 struct annotate_args *args)
1693{
1694 struct annotation *notes = symbol__annotation(sym);
1695 struct annotation_options *opts = args->options;
1696 struct bpf_prog_info_linear *info_linear;
1697 struct bpf_prog_linfo *prog_linfo = NULL;
1698 struct bpf_prog_info_node *info_node;
1699 int len = sym->end - sym->start;
1700 disassembler_ftype disassemble;
1701 struct map *map = args->ms.map;
1702 struct disassemble_info info;
1703 struct dso *dso = map->dso;
1704 int pc = 0, count, sub_id;
1705 struct btf *btf = NULL;
1706 char tpath[PATH_MAX];
1707 size_t buf_size;
1708 int nr_skip = 0;
1709 int ret = -1;
1710 char *buf;
1711 bfd *bfdf;
1712 FILE *s;
1713
1714 if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
1715 return -1;
1716
1717 pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__,
1718 sym->name, sym->start, sym->end - sym->start);
1719
1720 memset(tpath, 0, sizeof(tpath));
1721 perf_exe(tpath, sizeof(tpath));
1722
1723 bfdf = bfd_openr(tpath, NULL);
1724 assert(bfdf);
1725 assert(bfd_check_format(bfdf, bfd_object));
1726
1727 s = open_memstream(&buf, &buf_size);
1728 if (!s)
1729 goto out;
1730 init_disassemble_info(&info, s,
1731 (fprintf_ftype) fprintf);
1732
1733 info.arch = bfd_get_arch(bfdf);
1734 info.mach = bfd_get_mach(bfdf);
1735
1736 info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
1737 dso->bpf_prog.id);
1738 if (!info_node)
1739 goto out;
1740 info_linear = info_node->info_linear;
1741 sub_id = dso->bpf_prog.sub_id;
1742
1743 info.buffer = (void *)(info_linear->info.jited_prog_insns);
1744 info.buffer_length = info_linear->info.jited_prog_len;
1745
1746 if (info_linear->info.nr_line_info)
1747 prog_linfo = bpf_prog_linfo__new(&info_linear->info);
1748
1749 if (info_linear->info.btf_id) {
1750 struct btf_node *node;
1751
1752 node = perf_env__find_btf(dso->bpf_prog.env,
1753 info_linear->info.btf_id);
1754 if (node)
1755 btf = btf__new((__u8 *)(node->data),
1756 node->data_size);
1757 }
1758
1759 disassemble_init_for_target(&info);
1760
1761#ifdef DISASM_FOUR_ARGS_SIGNATURE
1762 disassemble = disassembler(info.arch,
1763 bfd_big_endian(bfdf),
1764 info.mach,
1765 bfdf);
1766#else
1767 disassemble = disassembler(bfdf);
1768#endif
1769 assert(disassemble);
1770
1771 fflush(s);
1772 do {
1773 const struct bpf_line_info *linfo = NULL;
1774 struct disasm_line *dl;
1775 size_t prev_buf_size;
1776 const char *srcline;
1777 u64 addr;
1778
1779 addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id];
1780 count = disassemble(pc, &info);
1781
1782 if (prog_linfo)
1783 linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
1784 addr, sub_id,
1785 nr_skip);
1786
1787 if (linfo && btf) {
1788 srcline = btf__name_by_offset(btf, linfo->line_off);
1789 nr_skip++;
1790 } else
1791 srcline = NULL;
1792
1793 fprintf(s, "\n");
1794 prev_buf_size = buf_size;
1795 fflush(s);
1796
1797 if (!opts->hide_src_code && srcline) {
1798 args->offset = -1;
1799 args->line = strdup(srcline);
1800 args->line_nr = 0;
1801 args->ms.sym = sym;
1802 dl = disasm_line__new(args);
1803 if (dl) {
1804 annotation_line__add(&dl->al,
1805 &notes->src->source);
1806 }
1807 }
1808
1809 args->offset = pc;
1810 args->line = buf + prev_buf_size;
1811 args->line_nr = 0;
1812 args->ms.sym = sym;
1813 dl = disasm_line__new(args);
1814 if (dl)
1815 annotation_line__add(&dl->al, &notes->src->source);
1816
1817 pc += count;
1818 } while (count > 0 && pc < len);
1819
1820 ret = 0;
1821out:
1822 free(prog_linfo);
1823 free(btf);
1824 fclose(s);
1825 bfd_close(bfdf);
1826 return ret;
1827}
1828#else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1829static int symbol__disassemble_bpf(struct symbol *sym __maybe_unused,
1830 struct annotate_args *args __maybe_unused)
1831{
1832 return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF;
1833}
1834#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1835
1677static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) 1836static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1678{ 1837{
1679 struct annotation_options *opts = args->options; 1838 struct annotation_options *opts = args->options;
@@ -1701,7 +1860,9 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1701 pr_debug("annotating [%p] %30s : [%p] %30s\n", 1860 pr_debug("annotating [%p] %30s : [%p] %30s\n",
1702 dso, dso->long_name, sym, sym->name); 1861 dso, dso->long_name, sym, sym->name);
1703 1862
1704 if (dso__is_kcore(dso)) { 1863 if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
1864 return symbol__disassemble_bpf(sym, args);
1865 } else if (dso__is_kcore(dso)) {
1705 kce.kcore_filename = symfs_filename; 1866 kce.kcore_filename = symfs_filename;
1706 kce.addr = map__rip_2objdump(map, sym->start); 1867 kce.addr = map__rip_2objdump(map, sym->start);
1707 kce.offs = sym->start; 1868 kce.offs = sym->start;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index df34fe483164..5bc0cf655d37 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -369,6 +369,7 @@ enum symbol_disassemble_errno {
369 __SYMBOL_ANNOTATE_ERRNO__START = -10000, 369 __SYMBOL_ANNOTATE_ERRNO__START = -10000,
370 370
371 SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START, 371 SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START,
372 SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF,
372 373
373 __SYMBOL_ANNOTATE_ERRNO__END, 374 __SYMBOL_ANNOTATE_ERRNO__END,
374}; 375};
diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
index 028c8ec1f62a..2a4a0da35632 100644
--- a/tools/perf/util/bpf-event.c
+++ b/tools/perf/util/bpf-event.c
@@ -3,11 +3,17 @@
3#include <stdlib.h> 3#include <stdlib.h>
4#include <bpf/bpf.h> 4#include <bpf/bpf.h>
5#include <bpf/btf.h> 5#include <bpf/btf.h>
6#include <bpf/libbpf.h>
6#include <linux/btf.h> 7#include <linux/btf.h>
8#include <linux/err.h>
7#include "bpf-event.h" 9#include "bpf-event.h"
8#include "debug.h" 10#include "debug.h"
9#include "symbol.h" 11#include "symbol.h"
10#include "machine.h" 12#include "machine.h"
13#include "env.h"
14#include "session.h"
15#include "map.h"
16#include "evlist.h"
11 17
12#define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr)) 18#define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr))
13 19
@@ -21,15 +27,122 @@ static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len)
21 return ret; 27 return ret;
22} 28}
23 29
30static int machine__process_bpf_event_load(struct machine *machine,
31 union perf_event *event,
32 struct perf_sample *sample __maybe_unused)
33{
34 struct bpf_prog_info_linear *info_linear;
35 struct bpf_prog_info_node *info_node;
36 struct perf_env *env = machine->env;
37 int id = event->bpf_event.id;
38 unsigned int i;
39
40 /* perf-record, no need to handle bpf-event */
41 if (env == NULL)
42 return 0;
43
44 info_node = perf_env__find_bpf_prog_info(env, id);
45 if (!info_node)
46 return 0;
47 info_linear = info_node->info_linear;
48
49 for (i = 0; i < info_linear->info.nr_jited_ksyms; i++) {
50 u64 *addrs = (u64 *)(uintptr_t)(info_linear->info.jited_ksyms);
51 u64 addr = addrs[i];
52 struct map *map;
53
54 map = map_groups__find(&machine->kmaps, addr);
55
56 if (map) {
57 map->dso->binary_type = DSO_BINARY_TYPE__BPF_PROG_INFO;
58 map->dso->bpf_prog.id = id;
59 map->dso->bpf_prog.sub_id = i;
60 map->dso->bpf_prog.env = env;
61 }
62 }
63 return 0;
64}
65
24int machine__process_bpf_event(struct machine *machine __maybe_unused, 66int machine__process_bpf_event(struct machine *machine __maybe_unused,
25 union perf_event *event, 67 union perf_event *event,
26 struct perf_sample *sample __maybe_unused) 68 struct perf_sample *sample __maybe_unused)
27{ 69{
28 if (dump_trace) 70 if (dump_trace)
29 perf_event__fprintf_bpf_event(event, stdout); 71 perf_event__fprintf_bpf_event(event, stdout);
72
73 switch (event->bpf_event.type) {
74 case PERF_BPF_EVENT_PROG_LOAD:
75 return machine__process_bpf_event_load(machine, event, sample);
76
77 case PERF_BPF_EVENT_PROG_UNLOAD:
78 /*
79 * Do not free bpf_prog_info and btf of the program here,
80 * as annotation still need them. They will be freed at
81 * the end of the session.
82 */
83 break;
84 default:
85 pr_debug("unexpected bpf_event type of %d\n",
86 event->bpf_event.type);
87 break;
88 }
30 return 0; 89 return 0;
31} 90}
32 91
92static int perf_env__fetch_btf(struct perf_env *env,
93 u32 btf_id,
94 struct btf *btf)
95{
96 struct btf_node *node;
97 u32 data_size;
98 const void *data;
99
100 data = btf__get_raw_data(btf, &data_size);
101
102 node = malloc(data_size + sizeof(struct btf_node));
103 if (!node)
104 return -1;
105
106 node->id = btf_id;
107 node->data_size = data_size;
108 memcpy(node->data, data, data_size);
109
110 perf_env__insert_btf(env, node);
111 return 0;
112}
113
114static int synthesize_bpf_prog_name(char *buf, int size,
115 struct bpf_prog_info *info,
116 struct btf *btf,
117 u32 sub_id)
118{
119 u8 (*prog_tags)[BPF_TAG_SIZE] = (void *)(uintptr_t)(info->prog_tags);
120 void *func_infos = (void *)(uintptr_t)(info->func_info);
121 u32 sub_prog_cnt = info->nr_jited_ksyms;
122 const struct bpf_func_info *finfo;
123 const char *short_name = NULL;
124 const struct btf_type *t;
125 int name_len;
126
127 name_len = snprintf(buf, size, "bpf_prog_");
128 name_len += snprintf_hex(buf + name_len, size - name_len,
129 prog_tags[sub_id], BPF_TAG_SIZE);
130 if (btf) {
131 finfo = func_infos + sub_id * info->func_info_rec_size;
132 t = btf__type_by_id(btf, finfo->type_id);
133 short_name = btf__name_by_offset(btf, t->name_off);
134 } else if (sub_id == 0 && sub_prog_cnt == 1) {
135 /* no subprog */
136 if (info->name[0])
137 short_name = info->name;
138 } else
139 short_name = "F";
140 if (short_name)
141 name_len += snprintf(buf + name_len, size - name_len,
142 "_%s", short_name);
143 return name_len;
144}
145
33/* 146/*
34 * Synthesize PERF_RECORD_KSYMBOL and PERF_RECORD_BPF_EVENT for one bpf 147 * Synthesize PERF_RECORD_KSYMBOL and PERF_RECORD_BPF_EVENT for one bpf
35 * program. One PERF_RECORD_BPF_EVENT is generated for the program. And 148 * program. One PERF_RECORD_BPF_EVENT is generated for the program. And
@@ -40,7 +153,7 @@ int machine__process_bpf_event(struct machine *machine __maybe_unused,
40 * -1 for failures; 153 * -1 for failures;
41 * -2 for lack of kernel support. 154 * -2 for lack of kernel support.
42 */ 155 */
43static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, 156static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
44 perf_event__handler_t process, 157 perf_event__handler_t process,
45 struct machine *machine, 158 struct machine *machine,
46 int fd, 159 int fd,
@@ -49,102 +162,71 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,
49{ 162{
50 struct ksymbol_event *ksymbol_event = &event->ksymbol_event; 163 struct ksymbol_event *ksymbol_event = &event->ksymbol_event;
51 struct bpf_event *bpf_event = &event->bpf_event; 164 struct bpf_event *bpf_event = &event->bpf_event;
52 u32 sub_prog_cnt, i, func_info_rec_size = 0; 165 struct bpf_prog_info_linear *info_linear;
53 u8 (*prog_tags)[BPF_TAG_SIZE] = NULL; 166 struct perf_tool *tool = session->tool;
54 struct bpf_prog_info info = { .type = 0, }; 167 struct bpf_prog_info_node *info_node;
55 u32 info_len = sizeof(info); 168 struct bpf_prog_info *info;
56 void *func_infos = NULL;
57 u64 *prog_addrs = NULL;
58 struct btf *btf = NULL; 169 struct btf *btf = NULL;
59 u32 *prog_lens = NULL; 170 struct perf_env *env;
60 bool has_btf = false; 171 u32 sub_prog_cnt, i;
61 char errbuf[512];
62 int err = 0; 172 int err = 0;
173 u64 arrays;
174
175 /*
176 * for perf-record and perf-report use header.env;
177 * otherwise, use global perf_env.
178 */
179 env = session->data ? &session->header.env : &perf_env;
63 180
64 /* Call bpf_obj_get_info_by_fd() to get sizes of arrays */ 181 arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS;
65 err = bpf_obj_get_info_by_fd(fd, &info, &info_len); 182 arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS;
183 arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO;
184 arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS;
185 arrays |= 1UL << BPF_PROG_INFO_JITED_INSNS;
186 arrays |= 1UL << BPF_PROG_INFO_LINE_INFO;
187 arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO;
66 188
67 if (err) { 189 info_linear = bpf_program__get_prog_info_linear(fd, arrays);
68 pr_debug("%s: failed to get BPF program info: %s, aborting\n", 190 if (IS_ERR_OR_NULL(info_linear)) {
69 __func__, str_error_r(errno, errbuf, sizeof(errbuf))); 191 info_linear = NULL;
192 pr_debug("%s: failed to get BPF program info. aborting\n", __func__);
70 return -1; 193 return -1;
71 } 194 }
72 if (info_len < offsetof(struct bpf_prog_info, prog_tags)) { 195
196 if (info_linear->info_len < offsetof(struct bpf_prog_info, prog_tags)) {
73 pr_debug("%s: the kernel is too old, aborting\n", __func__); 197 pr_debug("%s: the kernel is too old, aborting\n", __func__);
74 return -2; 198 return -2;
75 } 199 }
76 200
201 info = &info_linear->info;
202
77 /* number of ksyms, func_lengths, and tags should match */ 203 /* number of ksyms, func_lengths, and tags should match */
78 sub_prog_cnt = info.nr_jited_ksyms; 204 sub_prog_cnt = info->nr_jited_ksyms;
79 if (sub_prog_cnt != info.nr_prog_tags || 205 if (sub_prog_cnt != info->nr_prog_tags ||
80 sub_prog_cnt != info.nr_jited_func_lens) 206 sub_prog_cnt != info->nr_jited_func_lens)
81 return -1; 207 return -1;
82 208
83 /* check BTF func info support */ 209 /* check BTF func info support */
84 if (info.btf_id && info.nr_func_info && info.func_info_rec_size) { 210 if (info->btf_id && info->nr_func_info && info->func_info_rec_size) {
85 /* btf func info number should be same as sub_prog_cnt */ 211 /* btf func info number should be same as sub_prog_cnt */
86 if (sub_prog_cnt != info.nr_func_info) { 212 if (sub_prog_cnt != info->nr_func_info) {
87 pr_debug("%s: mismatch in BPF sub program count and BTF function info count, aborting\n", __func__); 213 pr_debug("%s: mismatch in BPF sub program count and BTF function info count, aborting\n", __func__);
88 return -1; 214 err = -1;
89 } 215 goto out;
90 if (btf__get_from_id(info.btf_id, &btf)) {
91 pr_debug("%s: failed to get BTF of id %u, aborting\n", __func__, info.btf_id);
92 return -1;
93 } 216 }
94 func_info_rec_size = info.func_info_rec_size; 217 if (btf__get_from_id(info->btf_id, &btf)) {
95 func_infos = calloc(sub_prog_cnt, func_info_rec_size); 218 pr_debug("%s: failed to get BTF of id %u, aborting\n", __func__, info->btf_id);
96 if (!func_infos) { 219 err = -1;
97 pr_debug("%s: failed to allocate memory for func_infos, aborting\n", __func__); 220 btf = NULL;
98 return -1; 221 goto out;
99 } 222 }
100 has_btf = true; 223 perf_env__fetch_btf(env, info->btf_id, btf);
101 }
102
103 /*
104 * We need address, length, and tag for each sub program.
105 * Allocate memory and call bpf_obj_get_info_by_fd() again
106 */
107 prog_addrs = calloc(sub_prog_cnt, sizeof(u64));
108 if (!prog_addrs) {
109 pr_debug("%s: failed to allocate memory for prog_addrs, aborting\n", __func__);
110 goto out;
111 }
112 prog_lens = calloc(sub_prog_cnt, sizeof(u32));
113 if (!prog_lens) {
114 pr_debug("%s: failed to allocate memory for prog_lens, aborting\n", __func__);
115 goto out;
116 }
117 prog_tags = calloc(sub_prog_cnt, BPF_TAG_SIZE);
118 if (!prog_tags) {
119 pr_debug("%s: failed to allocate memory for prog_tags, aborting\n", __func__);
120 goto out;
121 }
122
123 memset(&info, 0, sizeof(info));
124 info.nr_jited_ksyms = sub_prog_cnt;
125 info.nr_jited_func_lens = sub_prog_cnt;
126 info.nr_prog_tags = sub_prog_cnt;
127 info.jited_ksyms = ptr_to_u64(prog_addrs);
128 info.jited_func_lens = ptr_to_u64(prog_lens);
129 info.prog_tags = ptr_to_u64(prog_tags);
130 info_len = sizeof(info);
131 if (has_btf) {
132 info.nr_func_info = sub_prog_cnt;
133 info.func_info_rec_size = func_info_rec_size;
134 info.func_info = ptr_to_u64(func_infos);
135 }
136
137 err = bpf_obj_get_info_by_fd(fd, &info, &info_len);
138 if (err) {
139 pr_debug("%s: failed to get BPF program info, aborting\n", __func__);
140 goto out;
141 } 224 }
142 225
143 /* Synthesize PERF_RECORD_KSYMBOL */ 226 /* Synthesize PERF_RECORD_KSYMBOL */
144 for (i = 0; i < sub_prog_cnt; i++) { 227 for (i = 0; i < sub_prog_cnt; i++) {
145 const struct bpf_func_info *finfo; 228 __u32 *prog_lens = (__u32 *)(uintptr_t)(info->jited_func_lens);
146 const char *short_name = NULL; 229 __u64 *prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms);
147 const struct btf_type *t;
148 int name_len; 230 int name_len;
149 231
150 *ksymbol_event = (struct ksymbol_event){ 232 *ksymbol_event = (struct ksymbol_event){
@@ -157,26 +239,9 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,
157 .ksym_type = PERF_RECORD_KSYMBOL_TYPE_BPF, 239 .ksym_type = PERF_RECORD_KSYMBOL_TYPE_BPF,
158 .flags = 0, 240 .flags = 0,
159 }; 241 };
160 name_len = snprintf(ksymbol_event->name, KSYM_NAME_LEN,
161 "bpf_prog_");
162 name_len += snprintf_hex(ksymbol_event->name + name_len,
163 KSYM_NAME_LEN - name_len,
164 prog_tags[i], BPF_TAG_SIZE);
165 if (has_btf) {
166 finfo = func_infos + i * info.func_info_rec_size;
167 t = btf__type_by_id(btf, finfo->type_id);
168 short_name = btf__name_by_offset(btf, t->name_off);
169 } else if (i == 0 && sub_prog_cnt == 1) {
170 /* no subprog */
171 if (info.name[0])
172 short_name = info.name;
173 } else
174 short_name = "F";
175 if (short_name)
176 name_len += snprintf(ksymbol_event->name + name_len,
177 KSYM_NAME_LEN - name_len,
178 "_%s", short_name);
179 242
243 name_len = synthesize_bpf_prog_name(ksymbol_event->name,
244 KSYM_NAME_LEN, info, btf, i);
180 ksymbol_event->header.size += PERF_ALIGN(name_len + 1, 245 ksymbol_event->header.size += PERF_ALIGN(name_len + 1,
181 sizeof(u64)); 246 sizeof(u64));
182 247
@@ -186,8 +251,8 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,
186 machine, process); 251 machine, process);
187 } 252 }
188 253
189 /* Synthesize PERF_RECORD_BPF_EVENT */ 254 if (!opts->no_bpf_event) {
190 if (opts->bpf_event) { 255 /* Synthesize PERF_RECORD_BPF_EVENT */
191 *bpf_event = (struct bpf_event){ 256 *bpf_event = (struct bpf_event){
192 .header = { 257 .header = {
193 .type = PERF_RECORD_BPF_EVENT, 258 .type = PERF_RECORD_BPF_EVENT,
@@ -195,25 +260,38 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,
195 }, 260 },
196 .type = PERF_BPF_EVENT_PROG_LOAD, 261 .type = PERF_BPF_EVENT_PROG_LOAD,
197 .flags = 0, 262 .flags = 0,
198 .id = info.id, 263 .id = info->id,
199 }; 264 };
200 memcpy(bpf_event->tag, prog_tags[i], BPF_TAG_SIZE); 265 memcpy(bpf_event->tag, info->tag, BPF_TAG_SIZE);
201 memset((void *)event + event->header.size, 0, machine->id_hdr_size); 266 memset((void *)event + event->header.size, 0, machine->id_hdr_size);
202 event->header.size += machine->id_hdr_size; 267 event->header.size += machine->id_hdr_size;
268
269 /* save bpf_prog_info to env */
270 info_node = malloc(sizeof(struct bpf_prog_info_node));
271 if (!info_node) {
272 err = -1;
273 goto out;
274 }
275
276 info_node->info_linear = info_linear;
277 perf_env__insert_bpf_prog_info(env, info_node);
278 info_linear = NULL;
279
280 /*
281 * process after saving bpf_prog_info to env, so that
282 * required information is ready for look up
283 */
203 err = perf_tool__process_synth_event(tool, event, 284 err = perf_tool__process_synth_event(tool, event,
204 machine, process); 285 machine, process);
205 } 286 }
206 287
207out: 288out:
208 free(prog_tags); 289 free(info_linear);
209 free(prog_lens);
210 free(prog_addrs);
211 free(func_infos);
212 free(btf); 290 free(btf);
213 return err ? -1 : 0; 291 return err ? -1 : 0;
214} 292}
215 293
216int perf_event__synthesize_bpf_events(struct perf_tool *tool, 294int perf_event__synthesize_bpf_events(struct perf_session *session,
217 perf_event__handler_t process, 295 perf_event__handler_t process,
218 struct machine *machine, 296 struct machine *machine,
219 struct record_opts *opts) 297 struct record_opts *opts)
@@ -247,7 +325,7 @@ int perf_event__synthesize_bpf_events(struct perf_tool *tool,
247 continue; 325 continue;
248 } 326 }
249 327
250 err = perf_event__synthesize_one_bpf_prog(tool, process, 328 err = perf_event__synthesize_one_bpf_prog(session, process,
251 machine, fd, 329 machine, fd,
252 event, opts); 330 event, opts);
253 close(fd); 331 close(fd);
@@ -261,3 +339,142 @@ int perf_event__synthesize_bpf_events(struct perf_tool *tool,
261 free(event); 339 free(event);
262 return err; 340 return err;
263} 341}
342
343static void perf_env__add_bpf_info(struct perf_env *env, u32 id)
344{
345 struct bpf_prog_info_linear *info_linear;
346 struct bpf_prog_info_node *info_node;
347 struct btf *btf = NULL;
348 u64 arrays;
349 u32 btf_id;
350 int fd;
351
352 fd = bpf_prog_get_fd_by_id(id);
353 if (fd < 0)
354 return;
355
356 arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS;
357 arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS;
358 arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO;
359 arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS;
360 arrays |= 1UL << BPF_PROG_INFO_JITED_INSNS;
361 arrays |= 1UL << BPF_PROG_INFO_LINE_INFO;
362 arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO;
363
364 info_linear = bpf_program__get_prog_info_linear(fd, arrays);
365 if (IS_ERR_OR_NULL(info_linear)) {
366 pr_debug("%s: failed to get BPF program info. aborting\n", __func__);
367 goto out;
368 }
369
370 btf_id = info_linear->info.btf_id;
371
372 info_node = malloc(sizeof(struct bpf_prog_info_node));
373 if (info_node) {
374 info_node->info_linear = info_linear;
375 perf_env__insert_bpf_prog_info(env, info_node);
376 } else
377 free(info_linear);
378
379 if (btf_id == 0)
380 goto out;
381
382 if (btf__get_from_id(btf_id, &btf)) {
383 pr_debug("%s: failed to get BTF of id %u, aborting\n",
384 __func__, btf_id);
385 goto out;
386 }
387 perf_env__fetch_btf(env, btf_id, btf);
388
389out:
390 free(btf);
391 close(fd);
392}
393
394static int bpf_event__sb_cb(union perf_event *event, void *data)
395{
396 struct perf_env *env = data;
397
398 if (event->header.type != PERF_RECORD_BPF_EVENT)
399 return -1;
400
401 switch (event->bpf_event.type) {
402 case PERF_BPF_EVENT_PROG_LOAD:
403 perf_env__add_bpf_info(env, event->bpf_event.id);
404
405 case PERF_BPF_EVENT_PROG_UNLOAD:
406 /*
407 * Do not free bpf_prog_info and btf of the program here,
408 * as annotation still need them. They will be freed at
409 * the end of the session.
410 */
411 break;
412 default:
413 pr_debug("unexpected bpf_event type of %d\n",
414 event->bpf_event.type);
415 break;
416 }
417
418 return 0;
419}
420
421int bpf_event__add_sb_event(struct perf_evlist **evlist,
422 struct perf_env *env)
423{
424 struct perf_event_attr attr = {
425 .type = PERF_TYPE_SOFTWARE,
426 .config = PERF_COUNT_SW_DUMMY,
427 .sample_id_all = 1,
428 .watermark = 1,
429 .bpf_event = 1,
430 .size = sizeof(attr), /* to capture ABI version */
431 };
432
433 /*
434 * Older gcc versions don't support designated initializers, like above,
435 * for unnamed union members, such as the following:
436 */
437 attr.wakeup_watermark = 1;
438
439 return perf_evlist__add_sb_event(evlist, &attr, bpf_event__sb_cb, env);
440}
441
442void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
443 struct perf_env *env,
444 FILE *fp)
445{
446 __u32 *prog_lens = (__u32 *)(uintptr_t)(info->jited_func_lens);
447 __u64 *prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms);
448 char name[KSYM_NAME_LEN];
449 struct btf *btf = NULL;
450 u32 sub_prog_cnt, i;
451
452 sub_prog_cnt = info->nr_jited_ksyms;
453 if (sub_prog_cnt != info->nr_prog_tags ||
454 sub_prog_cnt != info->nr_jited_func_lens)
455 return;
456
457 if (info->btf_id) {
458 struct btf_node *node;
459
460 node = perf_env__find_btf(env, info->btf_id);
461 if (node)
462 btf = btf__new((__u8 *)(node->data),
463 node->data_size);
464 }
465
466 if (sub_prog_cnt == 1) {
467 synthesize_bpf_prog_name(name, KSYM_NAME_LEN, info, btf, 0);
468 fprintf(fp, "# bpf_prog_info %u: %s addr 0x%llx size %u\n",
469 info->id, name, prog_addrs[0], prog_lens[0]);
470 return;
471 }
472
473 fprintf(fp, "# bpf_prog_info %u:\n", info->id);
474 for (i = 0; i < sub_prog_cnt; i++) {
475 synthesize_bpf_prog_name(name, KSYM_NAME_LEN, info, btf, i);
476
477 fprintf(fp, "# \tsub_prog %u: %s addr 0x%llx size %u\n",
478 i, name, prog_addrs[i], prog_lens[i]);
479 }
480}
diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h
index 7890067e1a37..04c33b3bfe28 100644
--- a/tools/perf/util/bpf-event.h
+++ b/tools/perf/util/bpf-event.h
@@ -3,22 +3,45 @@
3#define __PERF_BPF_EVENT_H 3#define __PERF_BPF_EVENT_H
4 4
5#include <linux/compiler.h> 5#include <linux/compiler.h>
6#include <linux/rbtree.h>
7#include <pthread.h>
8#include <api/fd/array.h>
6#include "event.h" 9#include "event.h"
10#include <stdio.h>
7 11
8struct machine; 12struct machine;
9union perf_event; 13union perf_event;
14struct perf_env;
10struct perf_sample; 15struct perf_sample;
11struct perf_tool;
12struct record_opts; 16struct record_opts;
17struct evlist;
18struct target;
19
20struct bpf_prog_info_node {
21 struct bpf_prog_info_linear *info_linear;
22 struct rb_node rb_node;
23};
24
25struct btf_node {
26 struct rb_node rb_node;
27 u32 id;
28 u32 data_size;
29 char data[];
30};
13 31
14#ifdef HAVE_LIBBPF_SUPPORT 32#ifdef HAVE_LIBBPF_SUPPORT
15int machine__process_bpf_event(struct machine *machine, union perf_event *event, 33int machine__process_bpf_event(struct machine *machine, union perf_event *event,
16 struct perf_sample *sample); 34 struct perf_sample *sample);
17 35
18int perf_event__synthesize_bpf_events(struct perf_tool *tool, 36int perf_event__synthesize_bpf_events(struct perf_session *session,
19 perf_event__handler_t process, 37 perf_event__handler_t process,
20 struct machine *machine, 38 struct machine *machine,
21 struct record_opts *opts); 39 struct record_opts *opts);
40int bpf_event__add_sb_event(struct perf_evlist **evlist,
41 struct perf_env *env);
42void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
43 struct perf_env *env,
44 FILE *fp);
22#else 45#else
23static inline int machine__process_bpf_event(struct machine *machine __maybe_unused, 46static inline int machine__process_bpf_event(struct machine *machine __maybe_unused,
24 union perf_event *event __maybe_unused, 47 union perf_event *event __maybe_unused,
@@ -27,12 +50,25 @@ static inline int machine__process_bpf_event(struct machine *machine __maybe_unu
27 return 0; 50 return 0;
28} 51}
29 52
30static inline int perf_event__synthesize_bpf_events(struct perf_tool *tool __maybe_unused, 53static inline int perf_event__synthesize_bpf_events(struct perf_session *session __maybe_unused,
31 perf_event__handler_t process __maybe_unused, 54 perf_event__handler_t process __maybe_unused,
32 struct machine *machine __maybe_unused, 55 struct machine *machine __maybe_unused,
33 struct record_opts *opts __maybe_unused) 56 struct record_opts *opts __maybe_unused)
34{ 57{
35 return 0; 58 return 0;
36} 59}
60
61static inline int bpf_event__add_sb_event(struct perf_evlist **evlist __maybe_unused,
62 struct perf_env *env __maybe_unused)
63{
64 return 0;
65}
66
67static inline void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info __maybe_unused,
68 struct perf_env *env __maybe_unused,
69 FILE *fp __maybe_unused)
70{
71
72}
37#endif // HAVE_LIBBPF_SUPPORT 73#endif // HAVE_LIBBPF_SUPPORT
38#endif 74#endif
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index bff0d17920ed..0c5517a8d0b7 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -185,6 +185,7 @@ char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size)
185 return bf; 185 return bf;
186} 186}
187 187
188/* The caller is responsible to free the returned buffer. */
188char *build_id_cache__origname(const char *sbuild_id) 189char *build_id_cache__origname(const char *sbuild_id)
189{ 190{
190 char *linkname; 191 char *linkname;
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index fa092511c52b..7e3c1b60120c 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -633,11 +633,10 @@ static int collect_config(const char *var, const char *value,
633 } 633 }
634 634
635 ret = set_value(item, value); 635 ret = set_value(item, value);
636 return ret;
637 636
638out_free: 637out_free:
639 free(key); 638 free(key);
640 return -1; 639 return ret;
641} 640}
642 641
643int perf_config_set__collect(struct perf_config_set *set, const char *file_name, 642int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index c6b67efea11a..6a64f713710d 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -361,9 +361,9 @@ ssize_t perf_data__write(struct perf_data *data,
361 361
362int perf_data__switch(struct perf_data *data, 362int perf_data__switch(struct perf_data *data,
363 const char *postfix, 363 const char *postfix,
364 size_t pos, bool at_exit) 364 size_t pos, bool at_exit,
365 char **new_filepath)
365{ 366{
366 char *new_filepath;
367 int ret; 367 int ret;
368 368
369 if (check_pipe(data)) 369 if (check_pipe(data))
@@ -371,15 +371,15 @@ int perf_data__switch(struct perf_data *data,
371 if (perf_data__is_read(data)) 371 if (perf_data__is_read(data))
372 return -EINVAL; 372 return -EINVAL;
373 373
374 if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0) 374 if (asprintf(new_filepath, "%s.%s", data->path, postfix) < 0)
375 return -ENOMEM; 375 return -ENOMEM;
376 376
377 /* 377 /*
378 * Only fire a warning, don't return error, continue fill 378 * Only fire a warning, don't return error, continue fill
379 * original file. 379 * original file.
380 */ 380 */
381 if (rename(data->path, new_filepath)) 381 if (rename(data->path, *new_filepath))
382 pr_warning("Failed to rename %s to %s\n", data->path, new_filepath); 382 pr_warning("Failed to rename %s to %s\n", data->path, *new_filepath);
383 383
384 if (!at_exit) { 384 if (!at_exit) {
385 close(data->file.fd); 385 close(data->file.fd);
@@ -396,7 +396,6 @@ int perf_data__switch(struct perf_data *data,
396 } 396 }
397 ret = data->file.fd; 397 ret = data->file.fd;
398out: 398out:
399 free(new_filepath);
400 return ret; 399 return ret;
401} 400}
402 401
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 6aef8746469f..259868a39019 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -70,7 +70,7 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
70 */ 70 */
71int perf_data__switch(struct perf_data *data, 71int perf_data__switch(struct perf_data *data,
72 const char *postfix, 72 const char *postfix,
73 size_t pos, bool at_exit); 73 size_t pos, bool at_exit, char **new_filepath);
74 74
75int perf_data__create_dir(struct perf_data *data, int nr); 75int perf_data__create_dir(struct perf_data *data, int nr);
76int perf_data__open_dir(struct perf_data *data); 76int perf_data__open_dir(struct perf_data *data);
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index ba58ba603b69..e059976d9d93 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -184,6 +184,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
184 case DSO_BINARY_TYPE__KALLSYMS: 184 case DSO_BINARY_TYPE__KALLSYMS:
185 case DSO_BINARY_TYPE__GUEST_KALLSYMS: 185 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
186 case DSO_BINARY_TYPE__JAVA_JIT: 186 case DSO_BINARY_TYPE__JAVA_JIT:
187 case DSO_BINARY_TYPE__BPF_PROG_INFO:
187 case DSO_BINARY_TYPE__NOT_FOUND: 188 case DSO_BINARY_TYPE__NOT_FOUND:
188 ret = -1; 189 ret = -1;
189 break; 190 break;
@@ -1141,28 +1142,34 @@ void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
1141 1142
1142static void dso__set_basename(struct dso *dso) 1143static void dso__set_basename(struct dso *dso)
1143{ 1144{
1144 /* 1145 char *base, *lname;
1145 * basename() may modify path buffer, so we must pass 1146 int tid;
1146 * a copy.
1147 */
1148 char *base, *lname = strdup(dso->long_name);
1149 1147
1150 if (!lname) 1148 if (sscanf(dso->long_name, "/tmp/perf-%d.map", &tid) == 1) {
1151 return; 1149 if (asprintf(&base, "[JIT] tid %d", tid) < 0)
1152 1150 return;
1153 /* 1151 } else {
1154 * basename() may return a pointer to internal 1152 /*
1155 * storage which is reused in subsequent calls 1153 * basename() may modify path buffer, so we must pass
1156 * so copy the result. 1154 * a copy.
1157 */ 1155 */
1158 base = strdup(basename(lname)); 1156 lname = strdup(dso->long_name);
1157 if (!lname)
1158 return;
1159 1159
1160 free(lname); 1160 /*
1161 * basename() may return a pointer to internal
1162 * storage which is reused in subsequent calls
1163 * so copy the result.
1164 */
1165 base = strdup(basename(lname));
1161 1166
1162 if (!base) 1167 free(lname);
1163 return;
1164 1168
1165 dso__set_short_name(dso, base, true); 1169 if (!base)
1170 return;
1171 }
1172 dso__set_short_name(dso, base, true);
1166} 1173}
1167 1174
1168int dso__name_len(const struct dso *dso) 1175int dso__name_len(const struct dso *dso)
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index bb417c54c25a..6e3f63781e51 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -14,6 +14,7 @@
14 14
15struct machine; 15struct machine;
16struct map; 16struct map;
17struct perf_env;
17 18
18enum dso_binary_type { 19enum dso_binary_type {
19 DSO_BINARY_TYPE__KALLSYMS = 0, 20 DSO_BINARY_TYPE__KALLSYMS = 0,
@@ -35,6 +36,7 @@ enum dso_binary_type {
35 DSO_BINARY_TYPE__KCORE, 36 DSO_BINARY_TYPE__KCORE,
36 DSO_BINARY_TYPE__GUEST_KCORE, 37 DSO_BINARY_TYPE__GUEST_KCORE,
37 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 38 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
39 DSO_BINARY_TYPE__BPF_PROG_INFO,
38 DSO_BINARY_TYPE__NOT_FOUND, 40 DSO_BINARY_TYPE__NOT_FOUND,
39}; 41};
40 42
@@ -189,6 +191,12 @@ struct dso {
189 u64 debug_frame_offset; 191 u64 debug_frame_offset;
190 u64 eh_frame_hdr_offset; 192 u64 eh_frame_hdr_offset;
191 } data; 193 } data;
194 /* bpf prog information */
195 struct {
196 u32 id;
197 u32 sub_id;
198 struct perf_env *env;
199 } bpf_prog;
192 200
193 union { /* Tool specific area */ 201 union { /* Tool specific area */
194 void *priv; 202 void *priv;
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 4c23779e271a..c6351b557bb0 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -3,15 +3,163 @@
3#include "env.h" 3#include "env.h"
4#include "sane_ctype.h" 4#include "sane_ctype.h"
5#include "util.h" 5#include "util.h"
6#include "bpf-event.h"
6#include <errno.h> 7#include <errno.h>
7#include <sys/utsname.h> 8#include <sys/utsname.h>
9#include <bpf/libbpf.h>
8 10
9struct perf_env perf_env; 11struct perf_env perf_env;
10 12
13void 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++;
40out:
41 up_write(&env->bpf_progs.lock);
42}
43
44struct 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
67void 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++;
93out:
94 up_write(&env->bpf_progs.lock);
95}
96
97struct 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 */
120static 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}
157
11void perf_env__exit(struct perf_env *env) 158void perf_env__exit(struct perf_env *env)
12{ 159{
13 int i; 160 int i;
14 161
162 perf_env__purge_bpf(env);
15 zfree(&env->hostname); 163 zfree(&env->hostname);
16 zfree(&env->os_release); 164 zfree(&env->os_release);
17 zfree(&env->version); 165 zfree(&env->version);
@@ -38,6 +186,13 @@ void perf_env__exit(struct perf_env *env)
38 zfree(&env->memory_nodes); 186 zfree(&env->memory_nodes);
39} 187}
40 188
189void perf_env__init(struct perf_env *env)
190{
191 env->bpf_progs.infos = RB_ROOT;
192 env->bpf_progs.btfs = RB_ROOT;
193 init_rwsem(&env->bpf_progs.lock);
194}
195
41int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) 196int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
42{ 197{
43 int i; 198 int i;
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index d01b8355f4ca..4f8e2b485c01 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -3,7 +3,9 @@
3#define __PERF_ENV_H 3#define __PERF_ENV_H
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/rbtree.h>
6#include "cpumap.h" 7#include "cpumap.h"
8#include "rwsem.h"
7 9
8struct cpu_topology_map { 10struct cpu_topology_map {
9 int socket_id; 11 int socket_id;
@@ -64,8 +66,23 @@ struct perf_env {
64 struct memory_node *memory_nodes; 66 struct memory_node *memory_nodes;
65 unsigned long long memory_bsize; 67 unsigned long long memory_bsize;
66 u64 clockid_res_ns; 68 u64 clockid_res_ns;
69
70 /*
71 * bpf_info_lock protects bpf rbtrees. This is needed because the
72 * trees are accessed by different threads in perf-top
73 */
74 struct {
75 struct rw_semaphore lock;
76 struct rb_root infos;
77 u32 infos_cnt;
78 struct rb_root btfs;
79 u32 btfs_cnt;
80 } bpf_progs;
67}; 81};
68 82
83struct bpf_prog_info_node;
84struct btf_node;
85
69extern struct perf_env perf_env; 86extern struct perf_env perf_env;
70 87
71void perf_env__exit(struct perf_env *env); 88void perf_env__exit(struct perf_env *env);
@@ -80,4 +97,11 @@ const char *perf_env__arch(struct perf_env *env);
80const char *perf_env__raw_arch(struct perf_env *env); 97const char *perf_env__raw_arch(struct perf_env *env);
81int perf_env__nr_cpus_avail(struct perf_env *env); 98int perf_env__nr_cpus_avail(struct perf_env *env);
82 99
100void perf_env__init(struct perf_env *env);
101void perf_env__insert_bpf_prog_info(struct perf_env *env,
102 struct bpf_prog_info_node *info_node);
103struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
104 __u32 prog_id);
105void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node);
106struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id);
83#endif /* __PERF_ENV_H */ 107#endif /* __PERF_ENV_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index ed20f4379956..ec78e93085de 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -19,6 +19,7 @@
19#include "debug.h" 19#include "debug.h"
20#include "units.h" 20#include "units.h"
21#include "asm/bug.h" 21#include "asm/bug.h"
22#include "bpf-event.h"
22#include <signal.h> 23#include <signal.h>
23#include <unistd.h> 24#include <unistd.h>
24 25
@@ -1856,3 +1857,121 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list,
1856 } 1857 }
1857 return leader; 1858 return leader;
1858} 1859}
1860
1861int perf_evlist__add_sb_event(struct perf_evlist **evlist,
1862 struct perf_event_attr *attr,
1863 perf_evsel__sb_cb_t cb,
1864 void *data)
1865{
1866 struct perf_evsel *evsel;
1867 bool new_evlist = (*evlist) == NULL;
1868
1869 if (*evlist == NULL)
1870 *evlist = perf_evlist__new();
1871 if (*evlist == NULL)
1872 return -1;
1873
1874 if (!attr->sample_id_all) {
1875 pr_warning("enabling sample_id_all for all side band events\n");
1876 attr->sample_id_all = 1;
1877 }
1878
1879 evsel = perf_evsel__new_idx(attr, (*evlist)->nr_entries);
1880 if (!evsel)
1881 goto out_err;
1882
1883 evsel->side_band.cb = cb;
1884 evsel->side_band.data = data;
1885 perf_evlist__add(*evlist, evsel);
1886 return 0;
1887
1888out_err:
1889 if (new_evlist) {
1890 perf_evlist__delete(*evlist);
1891 *evlist = NULL;
1892 }
1893 return -1;
1894}
1895
1896static void *perf_evlist__poll_thread(void *arg)
1897{
1898 struct perf_evlist *evlist = arg;
1899 bool draining = false;
1900 int i;
1901
1902 while (draining || !(evlist->thread.done)) {
1903 if (draining)
1904 draining = false;
1905 else if (evlist->thread.done)
1906 draining = true;
1907
1908 if (!draining)
1909 perf_evlist__poll(evlist, 1000);
1910
1911 for (i = 0; i < evlist->nr_mmaps; i++) {
1912 struct perf_mmap *map = &evlist->mmap[i];
1913 union perf_event *event;
1914
1915 if (perf_mmap__read_init(map))
1916 continue;
1917 while ((event = perf_mmap__read_event(map)) != NULL) {
1918 struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);
1919
1920 if (evsel && evsel->side_band.cb)
1921 evsel->side_band.cb(event, evsel->side_band.data);
1922 else
1923 pr_warning("cannot locate proper evsel for the side band event\n");
1924
1925 perf_mmap__consume(map);
1926 }
1927 perf_mmap__read_done(map);
1928 }
1929 }
1930 return NULL;
1931}
1932
1933int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
1934 struct target *target)
1935{
1936 struct perf_evsel *counter;
1937
1938 if (!evlist)
1939 return 0;
1940
1941 if (perf_evlist__create_maps(evlist, target))
1942 goto out_delete_evlist;
1943
1944 evlist__for_each_entry(evlist, counter) {
1945 if (perf_evsel__open(counter, evlist->cpus,
1946 evlist->threads) < 0)
1947 goto out_delete_evlist;
1948 }
1949
1950 if (perf_evlist__mmap(evlist, UINT_MAX))
1951 goto out_delete_evlist;
1952
1953 evlist__for_each_entry(evlist, counter) {
1954 if (perf_evsel__enable(counter))
1955 goto out_delete_evlist;
1956 }
1957
1958 evlist->thread.done = 0;
1959 if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist))
1960 goto out_delete_evlist;
1961
1962 return 0;
1963
1964out_delete_evlist:
1965 perf_evlist__delete(evlist);
1966 evlist = NULL;
1967 return -1;
1968}
1969
1970void perf_evlist__stop_sb_thread(struct perf_evlist *evlist)
1971{
1972 if (!evlist)
1973 return;
1974 evlist->thread.done = 1;
1975 pthread_join(evlist->thread.th, NULL);
1976 perf_evlist__delete(evlist);
1977}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 744906dd4887..dcb68f34d2cd 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -54,6 +54,10 @@ struct perf_evlist {
54 struct perf_sample *sample); 54 struct perf_sample *sample);
55 u64 first_sample_time; 55 u64 first_sample_time;
56 u64 last_sample_time; 56 u64 last_sample_time;
57 struct {
58 pthread_t th;
59 volatile int done;
60 } thread;
57}; 61};
58 62
59struct perf_evsel_str_handler { 63struct perf_evsel_str_handler {
@@ -87,6 +91,14 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
87 91
88int perf_evlist__add_dummy(struct perf_evlist *evlist); 92int perf_evlist__add_dummy(struct perf_evlist *evlist);
89 93
94int perf_evlist__add_sb_event(struct perf_evlist **evlist,
95 struct perf_event_attr *attr,
96 perf_evsel__sb_cb_t cb,
97 void *data);
98int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
99 struct target *target);
100void perf_evlist__stop_sb_thread(struct perf_evlist *evlist);
101
90int perf_evlist__add_newtp(struct perf_evlist *evlist, 102int perf_evlist__add_newtp(struct perf_evlist *evlist,
91 const char *sys, const char *name, void *handler); 103 const char *sys, const char *name, void *handler);
92 104
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3bbf73e979c0..7835e05f0c0a 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1036,7 +1036,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
1036 attr->mmap2 = track && !perf_missing_features.mmap2; 1036 attr->mmap2 = track && !perf_missing_features.mmap2;
1037 attr->comm = track; 1037 attr->comm = track;
1038 attr->ksymbol = track && !perf_missing_features.ksymbol; 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 !perf_missing_features.bpf_event; 1040 !perf_missing_features.bpf_event;
1041 1041
1042 if (opts->record_namespaces) 1042 if (opts->record_namespaces)
@@ -1292,6 +1292,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
1292{ 1292{
1293 assert(list_empty(&evsel->node)); 1293 assert(list_empty(&evsel->node));
1294 assert(evsel->evlist == NULL); 1294 assert(evsel->evlist == NULL);
1295 perf_evsel__free_counts(evsel);
1295 perf_evsel__free_fd(evsel); 1296 perf_evsel__free_fd(evsel);
1296 perf_evsel__free_id(evsel); 1297 perf_evsel__free_id(evsel);
1297 perf_evsel__free_config_terms(evsel); 1298 perf_evsel__free_config_terms(evsel);
@@ -1342,10 +1343,9 @@ void perf_counts_values__scale(struct perf_counts_values *count,
1342 count->val = 0; 1343 count->val = 0;
1343 } else if (count->run < count->ena) { 1344 } else if (count->run < count->ena) {
1344 scaled = 1; 1345 scaled = 1;
1345 count->val = (u64)((double) count->val * count->ena / count->run + 0.5); 1346 count->val = (u64)((double) count->val * count->ena / count->run);
1346 } 1347 }
1347 } else 1348 }
1348 count->ena = count->run = 0;
1349 1349
1350 if (pscaled) 1350 if (pscaled)
1351 *pscaled = scaled; 1351 *pscaled = scaled;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index cc578e02e08f..0f2c6c93d721 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -73,6 +73,8 @@ struct perf_evsel_config_term {
73 73
74struct perf_stat_evsel; 74struct perf_stat_evsel;
75 75
76typedef int (perf_evsel__sb_cb_t)(union perf_event *event, void *data);
77
76/** struct perf_evsel - event selector 78/** struct perf_evsel - event selector
77 * 79 *
78 * @evlist - evlist this evsel is in, if it is in one. 80 * @evlist - evlist this evsel is in, if it is in one.
@@ -151,6 +153,10 @@ struct perf_evsel {
151 bool collect_stat; 153 bool collect_stat;
152 bool weak_group; 154 bool weak_group;
153 const char *pmu_name; 155 const char *pmu_name;
156 struct {
157 perf_evsel__sb_cb_t *cb;
158 void *data;
159 } side_band;
154}; 160};
155 161
156union u64_swap { 162union u64_swap {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index b0683bf4d9f3..b9e693825873 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -18,6 +18,7 @@
18#include <sys/utsname.h> 18#include <sys/utsname.h>
19#include <linux/time64.h> 19#include <linux/time64.h>
20#include <dirent.h> 20#include <dirent.h>
21#include <bpf/libbpf.h>
21 22
22#include "evlist.h" 23#include "evlist.h"
23#include "evsel.h" 24#include "evsel.h"
@@ -40,6 +41,7 @@
40#include "time-utils.h" 41#include "time-utils.h"
41#include "units.h" 42#include "units.h"
42#include "cputopo.h" 43#include "cputopo.h"
44#include "bpf-event.h"
43 45
44#include "sane_ctype.h" 46#include "sane_ctype.h"
45 47
@@ -876,6 +878,89 @@ static int write_dir_format(struct feat_fd *ff,
876 return do_write(ff, &data->dir.version, sizeof(data->dir.version)); 878 return do_write(ff, &data->dir.version, sizeof(data->dir.version));
877} 879}
878 880
881#ifdef HAVE_LIBBPF_SUPPORT
882static int write_bpf_prog_info(struct feat_fd *ff,
883 struct perf_evlist *evlist __maybe_unused)
884{
885 struct perf_env *env = &ff->ph->env;
886 struct rb_root *root;
887 struct rb_node *next;
888 int ret;
889
890 down_read(&env->bpf_progs.lock);
891
892 ret = do_write(ff, &env->bpf_progs.infos_cnt,
893 sizeof(env->bpf_progs.infos_cnt));
894 if (ret < 0)
895 goto out;
896
897 root = &env->bpf_progs.infos;
898 next = rb_first(root);
899 while (next) {
900 struct bpf_prog_info_node *node;
901 size_t len;
902
903 node = rb_entry(next, struct bpf_prog_info_node, rb_node);
904 next = rb_next(&node->rb_node);
905 len = sizeof(struct bpf_prog_info_linear) +
906 node->info_linear->data_len;
907
908 /* before writing to file, translate address to offset */
909 bpf_program__bpil_addr_to_offs(node->info_linear);
910 ret = do_write(ff, node->info_linear, len);
911 /*
912 * translate back to address even when do_write() fails,
913 * so that this function never changes the data.
914 */
915 bpf_program__bpil_offs_to_addr(node->info_linear);
916 if (ret < 0)
917 goto out;
918 }
919out:
920 up_read(&env->bpf_progs.lock);
921 return ret;
922}
923#else // HAVE_LIBBPF_SUPPORT
924static int write_bpf_prog_info(struct feat_fd *ff __maybe_unused,
925 struct perf_evlist *evlist __maybe_unused)
926{
927 return 0;
928}
929#endif // HAVE_LIBBPF_SUPPORT
930
931static int write_bpf_btf(struct feat_fd *ff,
932 struct perf_evlist *evlist __maybe_unused)
933{
934 struct perf_env *env = &ff->ph->env;
935 struct rb_root *root;
936 struct rb_node *next;
937 int ret;
938
939 down_read(&env->bpf_progs.lock);
940
941 ret = do_write(ff, &env->bpf_progs.btfs_cnt,
942 sizeof(env->bpf_progs.btfs_cnt));
943
944 if (ret < 0)
945 goto out;
946
947 root = &env->bpf_progs.btfs;
948 next = rb_first(root);
949 while (next) {
950 struct btf_node *node;
951
952 node = rb_entry(next, struct btf_node, rb_node);
953 next = rb_next(&node->rb_node);
954 ret = do_write(ff, &node->id,
955 sizeof(u32) * 2 + node->data_size);
956 if (ret < 0)
957 goto out;
958 }
959out:
960 up_read(&env->bpf_progs.lock);
961 return ret;
962}
963
879static int cpu_cache_level__sort(const void *a, const void *b) 964static int cpu_cache_level__sort(const void *a, const void *b)
880{ 965{
881 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a; 966 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1367,6 +1452,52 @@ static void print_dir_format(struct feat_fd *ff, FILE *fp)
1367 fprintf(fp, "# directory data version : %"PRIu64"\n", data->dir.version); 1452 fprintf(fp, "# directory data version : %"PRIu64"\n", data->dir.version);
1368} 1453}
1369 1454
1455static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp)
1456{
1457 struct perf_env *env = &ff->ph->env;
1458 struct rb_root *root;
1459 struct rb_node *next;
1460
1461 down_read(&env->bpf_progs.lock);
1462
1463 root = &env->bpf_progs.infos;
1464 next = rb_first(root);
1465
1466 while (next) {
1467 struct bpf_prog_info_node *node;
1468
1469 node = rb_entry(next, struct bpf_prog_info_node, rb_node);
1470 next = rb_next(&node->rb_node);
1471
1472 bpf_event__print_bpf_prog_info(&node->info_linear->info,
1473 env, fp);
1474 }
1475
1476 up_read(&env->bpf_progs.lock);
1477}
1478
1479static void print_bpf_btf(struct feat_fd *ff, FILE *fp)
1480{
1481 struct perf_env *env = &ff->ph->env;
1482 struct rb_root *root;
1483 struct rb_node *next;
1484
1485 down_read(&env->bpf_progs.lock);
1486
1487 root = &env->bpf_progs.btfs;
1488 next = rb_first(root);
1489
1490 while (next) {
1491 struct btf_node *node;
1492
1493 node = rb_entry(next, struct btf_node, rb_node);
1494 next = rb_next(&node->rb_node);
1495 fprintf(fp, "# btf info of id %u\n", node->id);
1496 }
1497
1498 up_read(&env->bpf_progs.lock);
1499}
1500
1370static void free_event_desc(struct perf_evsel *events) 1501static void free_event_desc(struct perf_evsel *events)
1371{ 1502{
1372 struct perf_evsel *evsel; 1503 struct perf_evsel *evsel;
@@ -2414,6 +2545,124 @@ static int process_dir_format(struct feat_fd *ff,
2414 return do_read_u64(ff, &data->dir.version); 2545 return do_read_u64(ff, &data->dir.version);
2415} 2546}
2416 2547
2548#ifdef HAVE_LIBBPF_SUPPORT
2549static int process_bpf_prog_info(struct feat_fd *ff, void *data __maybe_unused)
2550{
2551 struct bpf_prog_info_linear *info_linear;
2552 struct bpf_prog_info_node *info_node;
2553 struct perf_env *env = &ff->ph->env;
2554 u32 count, i;
2555 int err = -1;
2556
2557 if (ff->ph->needs_swap) {
2558 pr_warning("interpreting bpf_prog_info from systems with endianity is not yet supported\n");
2559 return 0;
2560 }
2561
2562 if (do_read_u32(ff, &count))
2563 return -1;
2564
2565 down_write(&env->bpf_progs.lock);
2566
2567 for (i = 0; i < count; ++i) {
2568 u32 info_len, data_len;
2569
2570 info_linear = NULL;
2571 info_node = NULL;
2572 if (do_read_u32(ff, &info_len))
2573 goto out;
2574 if (do_read_u32(ff, &data_len))
2575 goto out;
2576
2577 if (info_len > sizeof(struct bpf_prog_info)) {
2578 pr_warning("detected invalid bpf_prog_info\n");
2579 goto out;
2580 }
2581
2582 info_linear = malloc(sizeof(struct bpf_prog_info_linear) +
2583 data_len);
2584 if (!info_linear)
2585 goto out;
2586 info_linear->info_len = sizeof(struct bpf_prog_info);
2587 info_linear->data_len = data_len;
2588 if (do_read_u64(ff, (u64 *)(&info_linear->arrays)))
2589 goto out;
2590 if (__do_read(ff, &info_linear->info, info_len))
2591 goto out;
2592 if (info_len < sizeof(struct bpf_prog_info))
2593 memset(((void *)(&info_linear->info)) + info_len, 0,
2594 sizeof(struct bpf_prog_info) - info_len);
2595
2596 if (__do_read(ff, info_linear->data, data_len))
2597 goto out;
2598
2599 info_node = malloc(sizeof(struct bpf_prog_info_node));
2600 if (!info_node)
2601 goto out;
2602
2603 /* after reading from file, translate offset to address */
2604 bpf_program__bpil_offs_to_addr(info_linear);
2605 info_node->info_linear = info_linear;
2606 perf_env__insert_bpf_prog_info(env, info_node);
2607 }
2608
2609 return 0;
2610out:
2611 free(info_linear);
2612 free(info_node);
2613 up_write(&env->bpf_progs.lock);
2614 return err;
2615}
2616#else // HAVE_LIBBPF_SUPPORT
2617static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data __maybe_unused)
2618{
2619 return 0;
2620}
2621#endif // HAVE_LIBBPF_SUPPORT
2622
2623static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused)
2624{
2625 struct perf_env *env = &ff->ph->env;
2626 u32 count, i;
2627
2628 if (ff->ph->needs_swap) {
2629 pr_warning("interpreting btf from systems with endianity is not yet supported\n");
2630 return 0;
2631 }
2632
2633 if (do_read_u32(ff, &count))
2634 return -1;
2635
2636 down_write(&env->bpf_progs.lock);
2637
2638 for (i = 0; i < count; ++i) {
2639 struct btf_node *node;
2640 u32 id, data_size;
2641
2642 if (do_read_u32(ff, &id))
2643 return -1;
2644 if (do_read_u32(ff, &data_size))
2645 return -1;
2646
2647 node = malloc(sizeof(struct btf_node) + data_size);
2648 if (!node)
2649 return -1;
2650
2651 node->id = id;
2652 node->data_size = data_size;
2653
2654 if (__do_read(ff, node->data, data_size)) {
2655 free(node);
2656 return -1;
2657 }
2658
2659 perf_env__insert_btf(env, node);
2660 }
2661
2662 up_write(&env->bpf_progs.lock);
2663 return 0;
2664}
2665
2417struct feature_ops { 2666struct feature_ops {
2418 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); 2667 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2419 void (*print)(struct feat_fd *ff, FILE *fp); 2668 void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2474,7 +2723,9 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2474 FEAT_OPR(SAMPLE_TIME, sample_time, false), 2723 FEAT_OPR(SAMPLE_TIME, sample_time, false),
2475 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true), 2724 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
2476 FEAT_OPR(CLOCKID, clockid, false), 2725 FEAT_OPR(CLOCKID, clockid, false),
2477 FEAT_OPN(DIR_FORMAT, dir_format, false) 2726 FEAT_OPN(DIR_FORMAT, dir_format, false),
2727 FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false),
2728 FEAT_OPR(BPF_BTF, bpf_btf, false),
2478}; 2729};
2479 2730
2480struct header_print_data { 2731struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 6a231340238d..386da49e1bfa 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -40,6 +40,8 @@ enum {
40 HEADER_MEM_TOPOLOGY, 40 HEADER_MEM_TOPOLOGY,
41 HEADER_CLOCKID, 41 HEADER_CLOCKID,
42 HEADER_DIR_FORMAT, 42 HEADER_DIR_FORMAT,
43 HEADER_BPF_PROG_INFO,
44 HEADER_BPF_BTF,
43 HEADER_LAST_FEATURE, 45 HEADER_LAST_FEATURE,
44 HEADER_FEAT_BITS = 256, 46 HEADER_FEAT_BITS = 256,
45}; 47};
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 1f230285d78a..7ace7a10054d 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1111,8 +1111,10 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
1111 1111
1112 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, 1112 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
1113 iter->evsel, al, max_stack_depth); 1113 iter->evsel, al, max_stack_depth);
1114 if (err) 1114 if (err) {
1115 map__put(alm);
1115 return err; 1116 return err;
1117 }
1116 1118
1117 err = iter->ops->prepare_entry(iter, al); 1119 err = iter->ops->prepare_entry(iter, al);
1118 if (err) 1120 if (err)
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index fbeb0c6efaa6..e32628cd20a7 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -577,10 +577,25 @@ static void __maps__purge(struct maps *maps)
577 } 577 }
578} 578}
579 579
580static 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
580static void maps__exit(struct maps *maps) 594static void maps__exit(struct maps *maps)
581{ 595{
582 down_write(&maps->lock); 596 down_write(&maps->lock);
583 __maps__purge(maps); 597 __maps__purge(maps);
598 __maps__purge_names(maps);
584 up_write(&maps->lock); 599 up_write(&maps->lock);
585} 600}
586 601
@@ -917,6 +932,9 @@ static void __maps__remove(struct maps *maps, struct map *map)
917{ 932{
918 rb_erase_init(&map->rb_node, &maps->entries); 933 rb_erase_init(&map->rb_node, &maps->entries);
919 map__put(map); 934 map__put(map);
935
936 rb_erase_init(&map->rb_node_name, &maps->names);
937 map__put(map);
920} 938}
921 939
922void maps__remove(struct maps *maps, struct map *map) 940void maps__remove(struct maps *maps, struct map *map)
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index ea523d3b248f..989fed6f43b5 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -270,6 +270,8 @@ static int __ordered_events__flush(struct ordered_events *oe, enum oe_flush how,
270 "FINAL", 270 "FINAL",
271 "ROUND", 271 "ROUND",
272 "HALF ", 272 "HALF ",
273 "TOP ",
274 "TIME ",
273 }; 275 };
274 int err; 276 int err;
275 bool show_progress = false; 277 bool show_progress = false;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4dcc01b2532c..5ef4939408f2 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -2271,6 +2271,7 @@ static bool is_event_supported(u8 type, unsigned config)
2271 perf_evsel__delete(evsel); 2271 perf_evsel__delete(evsel);
2272 } 2272 }
2273 2273
2274 thread_map__put(tmap);
2274 return ret; 2275 return ret;
2275} 2276}
2276 2277
@@ -2341,6 +2342,7 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
2341 printf(" %-50s [%s]\n", buf, "SDT event"); 2342 printf(" %-50s [%s]\n", buf, "SDT event");
2342 free(buf); 2343 free(buf);
2343 } 2344 }
2345 free(path);
2344 } else 2346 } else
2345 printf(" %-50s [%s]\n", nd->s, "SDT event"); 2347 printf(" %-50s [%s]\n", nd->s, "SDT event");
2346 if (nd2) { 2348 if (nd2) {
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0ec34227bd60..b17f1c9bc965 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -132,6 +132,7 @@ struct perf_session *perf_session__new(struct perf_data *data,
132 ordered_events__init(&session->ordered_events, 132 ordered_events__init(&session->ordered_events,
133 ordered_events__deliver_event, NULL); 133 ordered_events__deliver_event, NULL);
134 134
135 perf_env__init(&session->header.env);
135 if (data) { 136 if (data) {
136 if (perf_data__open(data)) 137 if (perf_data__open(data))
137 goto out_delete; 138 goto out_delete;
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index bdd30cab51cb..5d2518e89fc4 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -13,6 +13,7 @@
13#include "evsel.h" 13#include "evsel.h"
14#include "evlist.h" 14#include "evlist.h"
15#include "strlist.h" 15#include "strlist.h"
16#include "strbuf.h"
16#include <traceevent/event-parse.h> 17#include <traceevent/event-parse.h>
17#include "mem-events.h" 18#include "mem-events.h"
18#include "annotate.h" 19#include "annotate.h"
@@ -3107,3 +3108,54 @@ void reset_output_field(void)
3107 reset_dimensions(); 3108 reset_dimensions();
3108 perf_hpp__reset_output_field(&perf_hpp_list); 3109 perf_hpp__reset_output_field(&perf_hpp_list);
3109} 3110}
3111
3112#define INDENT (3*8 + 1)
3113
3114static void add_key(struct strbuf *sb, const char *str, int *llen)
3115{
3116 if (*llen >= 75) {
3117 strbuf_addstr(sb, "\n\t\t\t ");
3118 *llen = INDENT;
3119 }
3120 strbuf_addf(sb, " %s", str);
3121 *llen += strlen(str) + 1;
3122}
3123
3124static void add_sort_string(struct strbuf *sb, struct sort_dimension *s, int n,
3125 int *llen)
3126{
3127 int i;
3128
3129 for (i = 0; i < n; i++)
3130 add_key(sb, s[i].name, llen);
3131}
3132
3133static void add_hpp_sort_string(struct strbuf *sb, struct hpp_dimension *s, int n,
3134 int *llen)
3135{
3136 int i;
3137
3138 for (i = 0; i < n; i++)
3139 add_key(sb, s[i].name, llen);
3140}
3141
3142const char *sort_help(const char *prefix)
3143{
3144 struct strbuf sb;
3145 char *s;
3146 int len = strlen(prefix) + INDENT;
3147
3148 strbuf_init(&sb, 300);
3149 strbuf_addstr(&sb, prefix);
3150 add_hpp_sort_string(&sb, hpp_sort_dimensions,
3151 ARRAY_SIZE(hpp_sort_dimensions), &len);
3152 add_sort_string(&sb, common_sort_dimensions,
3153 ARRAY_SIZE(common_sort_dimensions), &len);
3154 add_sort_string(&sb, bstack_sort_dimensions,
3155 ARRAY_SIZE(bstack_sort_dimensions), &len);
3156 add_sort_string(&sb, memory_sort_dimensions,
3157 ARRAY_SIZE(memory_sort_dimensions), &len);
3158 s = strbuf_detach(&sb, NULL);
3159 strbuf_release(&sb);
3160 return s;
3161}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index bb9442ab7a0c..ce376a73f964 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -296,6 +296,8 @@ void reset_output_field(void);
296void sort__setup_elide(FILE *fp); 296void sort__setup_elide(FILE *fp);
297void perf_hpp__set_elide(int idx, bool elide); 297void perf_hpp__set_elide(int idx, bool elide);
298 298
299const char *sort_help(const char *prefix);
300
299int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); 301int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);
300 302
301bool is_strict_order(const char *order); 303bool is_strict_order(const char *order);
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 4d40515307b8..2856cc9d5a31 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -291,10 +291,8 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
291 break; 291 break;
292 case AGGR_GLOBAL: 292 case AGGR_GLOBAL:
293 aggr->val += count->val; 293 aggr->val += count->val;
294 if (config->scale) { 294 aggr->ena += count->ena;
295 aggr->ena += count->ena; 295 aggr->run += count->run;
296 aggr->run += count->run;
297 }
298 case AGGR_UNSET: 296 case AGGR_UNSET:
299 default: 297 default:
300 break; 298 break;
@@ -442,10 +440,8 @@ int create_perf_stat_counter(struct perf_evsel *evsel,
442 struct perf_event_attr *attr = &evsel->attr; 440 struct perf_event_attr *attr = &evsel->attr;
443 struct perf_evsel *leader = evsel->leader; 441 struct perf_evsel *leader = evsel->leader;
444 442
445 if (config->scale) { 443 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
446 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 444 PERF_FORMAT_TOTAL_TIME_RUNNING;
447 PERF_FORMAT_TOTAL_TIME_RUNNING;
448 }
449 445
450 /* 446 /*
451 * The event is part of non trivial group, let's enable 447 * The event is part of non trivial group, let's enable
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 58442ca5e3c4..5cbad55cd99d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1455,6 +1455,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1455 case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: 1455 case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
1456 return true; 1456 return true;
1457 1457
1458 case DSO_BINARY_TYPE__BPF_PROG_INFO:
1458 case DSO_BINARY_TYPE__NOT_FOUND: 1459 case DSO_BINARY_TYPE__NOT_FOUND:
1459 default: 1460 default:
1460 return false; 1461 return false;