summaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-01 01:42:04 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-01 01:42:04 -0400
commit8cdfd068c1ea54cca7d7ad6ad31335cc5d0d9905 (patch)
tree26a36ec23067a9e26baf3d46c65f70619ca4d808 /tools/perf
parent4d537f37e0d39f64687be71087dca607ee507f5a (diff)
parent79a3aaa7b82e3106be97842dedfd8429248896e6 (diff)
Merge 5.1-rc3 into usb-next
We want the USB fixes in here as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/Build.txt24
-rw-r--r--tools/perf/Documentation/perf-config.txt16
-rw-r--r--tools/perf/Documentation/perf-record.txt4
-rw-r--r--tools/perf/Documentation/perf-report.txt13
-rw-r--r--tools/perf/Documentation/perf-script.txt3
-rw-r--r--tools/perf/Documentation/perf-stat.txt5
-rw-r--r--tools/perf/Documentation/tips.txt7
-rw-r--r--tools/perf/Makefile.config15
-rw-r--r--tools/perf/Makefile.perf4
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl10
-rw-r--r--tools/perf/arch/x86/util/Build1
-rw-r--r--tools/perf/arch/x86/util/archinsn.c26
-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.c54
-rw-r--r--tools/perf/builtin-report.c50
-rw-r--r--tools/perf/builtin-script.c129
-rw-r--r--tools/perf/builtin-stat.c3
-rw-r--r--tools/perf/builtin-top.c62
-rw-r--r--tools/perf/builtin.h3
-rwxr-xr-xtools/perf/check-headers.sh2
-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/pmu-events/arch/x86/amdfam17h/branch.json12
-rw-r--r--tools/perf/pmu-events/arch/x86/amdfam17h/cache.json287
-rw-r--r--tools/perf/pmu-events/arch/x86/amdfam17h/core.json134
-rw-r--r--tools/perf/pmu-events/arch/x86/amdfam17h/floating-point.json168
-rw-r--r--tools/perf/pmu-events/arch/x86/amdfam17h/memory.json162
-rw-r--r--tools/perf/pmu-events/arch/x86/amdfam17h/other.json65
-rw-r--r--tools/perf/pmu-events/arch/x86/mapfile.csv1
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py61
-rw-r--r--tools/perf/scripts/python/export-to-sqlite.py26
-rwxr-xr-xtools/perf/scripts/python/exported-sql-viewer.py119
-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
-rwxr-xr-xtools/perf/trace/beauty/mmap_flags.sh14
-rw-r--r--tools/perf/ui/browser.c10
-rw-r--r--tools/perf/ui/browsers/Build1
-rw-r--r--tools/perf/ui/browsers/annotate.c2
-rw-r--r--tools/perf/ui/browsers/hists.c141
-rw-r--r--tools/perf/ui/browsers/res_sample.c91
-rw-r--r--tools/perf/ui/browsers/scripts.c274
-rw-r--r--tools/perf/util/annotate.c163
-rw-r--r--tools/perf/util/annotate.h1
-rw-r--r--tools/perf/util/archinsn.h12
-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/cs-etm-decoder/cs-etm-decoder.c1
-rw-r--r--tools/perf/util/data.c107
-rw-r--r--tools/perf/util/data.h14
-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.c148
-rw-r--r--tools/perf/util/evlist.h14
-rw-r--r--tools/perf/util/evsel.c80
-rw-r--r--tools/perf/util/evsel.h6
-rw-r--r--tools/perf/util/header.c295
-rw-r--r--tools/perf/util/header.h7
-rw-r--r--tools/perf/util/hist.c54
-rw-r--r--tools/perf/util/hist.h31
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c20
-rw-r--r--tools/perf/util/machine.c32
-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/pmu.c10
-rw-r--r--tools/perf/util/probe-event.c6
-rw-r--r--tools/perf/util/session.c28
-rw-r--r--tools/perf/util/sort.c91
-rw-r--r--tools/perf/util/sort.h12
-rw-r--r--tools/perf/util/stat.c12
-rw-r--r--tools/perf/util/symbol.c5
-rw-r--r--tools/perf/util/symbol_conf.h3
-rw-r--r--tools/perf/util/time-utils.c8
-rw-r--r--tools/perf/util/time-utils.h1
107 files changed, 3391 insertions, 1155 deletions
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 86f3dcc15f83..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
@@ -584,6 +584,20 @@ llvm.*::
584 llvm.opts:: 584 llvm.opts::
585 Options passed to llc. 585 Options passed to llc.
586 586
587samples.*::
588
589 samples.context::
590 Define how many ns worth of time to show
591 around samples in perf report sample context browser.
592
593scripts.*::
594
595 Any option defines a script that is added to the scripts menu
596 in the interactive perf browser and whose output is displayed.
597 The name of the option is the name, the value is a script command line.
598 The script gets the same options passed as a full perf script,
599 in particular -i perfdata file, --cpu, --tid
600
587SEE ALSO 601SEE ALSO
588-------- 602--------
589linkperf:perf[1] 603linkperf:perf[1]
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-report.txt b/tools/perf/Documentation/perf-report.txt
index 1a27bfe05039..f441baa794ce 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -105,6 +105,8 @@ OPTIONS
105 guest machine 105 guest machine
106 - sample: Number of sample 106 - sample: Number of sample
107 - period: Raw number of event count of sample 107 - period: Raw number of event count of sample
108 - time: Separate the samples by time stamp with the resolution specified by
109 --time-quantum (default 100ms). Specify with overhead and before it.
108 110
109 By default, comm, dso and symbol keys are used. 111 By default, comm, dso and symbol keys are used.
110 (i.e. --sort comm,dso,symbol) 112 (i.e. --sort comm,dso,symbol)
@@ -459,6 +461,10 @@ include::itrace.txt[]
459--socket-filter:: 461--socket-filter::
460 Only report the samples on the processor socket that match with this filter 462 Only report the samples on the processor socket that match with this filter
461 463
464--samples=N::
465 Save N individual samples for each histogram entry to show context in perf
466 report tui browser.
467
462--raw-trace:: 468--raw-trace::
463 When displaying traceevent output, do not use print fmt or plugins. 469 When displaying traceevent output, do not use print fmt or plugins.
464 470
@@ -477,6 +483,9 @@ include::itrace.txt[]
477 Please note that not all mmaps are stored, options affecting which ones 483 Please note that not all mmaps are stored, options affecting which ones
478 are include 'perf record --data', for instance. 484 are include 'perf record --data', for instance.
479 485
486--ns::
487 Show time stamps in nanoseconds.
488
480--stats:: 489--stats::
481 Display overall events statistics without any further processing. 490 Display overall events statistics without any further processing.
482 (like the one at the end of the perf report -D command) 491 (like the one at the end of the perf report -D command)
@@ -494,6 +503,10 @@ include::itrace.txt[]
494 The period/hits keywords set the base the percentage is computed 503 The period/hits keywords set the base the percentage is computed
495 on - the samples period or the number of samples (hits). 504 on - the samples period or the number of samples (hits).
496 505
506--time-quantum::
507 Configure time quantum for time sort key. Default 100ms.
508 Accepts s, us, ms, ns units.
509
497include::callchain-overhead-calculation.txt[] 510include::callchain-overhead-calculation.txt[]
498 511
499SEE ALSO 512SEE ALSO
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/Documentation/tips.txt b/tools/perf/Documentation/tips.txt
index 849599f39c5e..869965d629ce 100644
--- a/tools/perf/Documentation/tips.txt
+++ b/tools/perf/Documentation/tips.txt
@@ -15,6 +15,7 @@ To see callchains in a more compact form: perf report -g folded
15Show individual samples with: perf script 15Show individual samples with: perf script
16Limit to show entries above 5% only: perf report --percent-limit 5 16Limit to show entries above 5% only: perf report --percent-limit 5
17Profiling branch (mis)predictions with: perf record -b / perf report 17Profiling branch (mis)predictions with: perf record -b / perf report
18To show assembler sample contexts use perf record -b / perf script -F +brstackinsn --xed
18Treat branches as callchains: perf report --branch-history 19Treat branches as callchains: perf report --branch-history
19To count events in every 1000 msec: perf stat -I 1000 20To count events in every 1000 msec: perf stat -I 1000
20Print event counts in CSV format with: perf stat -x, 21Print event counts in CSV format with: perf stat -x,
@@ -34,3 +35,9 @@ Show current config key-value pairs: perf config --list
34Show user configuration overrides: perf config --user --list 35Show user configuration overrides: perf config --user --list
35To add Node.js USDT(User-Level Statically Defined Tracing): perf buildid-cache --add `which node` 36To add Node.js USDT(User-Level Statically Defined Tracing): perf buildid-cache --add `which node`
36To report cacheline events from previous recording: perf c2c report 37To report cacheline events from previous recording: perf c2c report
38To browse sample contexts use perf report --sample 10 and select in context menu
39To separate samples by time use perf report --sort time,overhead,sym
40To set sample time separation other than 100ms with --sort time use --time-quantum
41Add -I to perf report to sample register values visible in perf report context.
42To show IPC for sampling periods use perf record -e '{cycles,instructions}:S' and then browse context
43To show context switches in perf report sample context add --switch-events to perf record.
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/Makefile.perf b/tools/perf/Makefile.perf
index 01f7555fd933..e8c9f77e9010 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -481,8 +481,8 @@ $(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_t
481mmap_flags_array := $(beauty_outdir)/mmap_flags_array.c 481mmap_flags_array := $(beauty_outdir)/mmap_flags_array.c
482mmap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mmap_flags.sh 482mmap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mmap_flags.sh
483 483
484$(mmap_flags_array): $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(mmap_flags_tbl) 484$(mmap_flags_array): $(linux_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(mmap_flags_tbl)
485 $(Q)$(SHELL) '$(mmap_flags_tbl)' $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@ 485 $(Q)$(SHELL) '$(mmap_flags_tbl)' $(linux_uapi_dir) $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@
486 486
487mount_flags_array := $(beauty_outdir)/mount_flags_array.c 487mount_flags_array := $(beauty_outdir)/mount_flags_array.c
488mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/mount_flags.sh 488mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/mount_flags.sh
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index f0b1709a5ffb..92ee0b4378d4 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -343,6 +343,12 @@
343332 common statx __x64_sys_statx 343332 common statx __x64_sys_statx
344333 common io_pgetevents __x64_sys_io_pgetevents 344333 common io_pgetevents __x64_sys_io_pgetevents
345334 common rseq __x64_sys_rseq 345334 common rseq __x64_sys_rseq
346# don't use numbers 387 through 423, add new calls after the last
347# 'common' entry
348424 common pidfd_send_signal __x64_sys_pidfd_send_signal
349425 common io_uring_setup __x64_sys_io_uring_setup
350426 common io_uring_enter __x64_sys_io_uring_enter
351427 common io_uring_register __x64_sys_io_uring_register
346 352
347# 353#
348# x32-specific system call numbers start at 512 to avoid cache impact 354# x32-specific system call numbers start at 512 to avoid cache impact
@@ -361,7 +367,7 @@
361520 x32 execve __x32_compat_sys_execve/ptregs 367520 x32 execve __x32_compat_sys_execve/ptregs
362521 x32 ptrace __x32_compat_sys_ptrace 368521 x32 ptrace __x32_compat_sys_ptrace
363522 x32 rt_sigpending __x32_compat_sys_rt_sigpending 369522 x32 rt_sigpending __x32_compat_sys_rt_sigpending
364523 x32 rt_sigtimedwait __x32_compat_sys_rt_sigtimedwait 370523 x32 rt_sigtimedwait __x32_compat_sys_rt_sigtimedwait_time64
365524 x32 rt_sigqueueinfo __x32_compat_sys_rt_sigqueueinfo 371524 x32 rt_sigqueueinfo __x32_compat_sys_rt_sigqueueinfo
366525 x32 sigaltstack __x32_compat_sys_sigaltstack 372525 x32 sigaltstack __x32_compat_sys_sigaltstack
367526 x32 timer_create __x32_compat_sys_timer_create 373526 x32 timer_create __x32_compat_sys_timer_create
@@ -375,7 +381,7 @@
375534 x32 preadv __x32_compat_sys_preadv64 381534 x32 preadv __x32_compat_sys_preadv64
376535 x32 pwritev __x32_compat_sys_pwritev64 382535 x32 pwritev __x32_compat_sys_pwritev64
377536 x32 rt_tgsigqueueinfo __x32_compat_sys_rt_tgsigqueueinfo 383536 x32 rt_tgsigqueueinfo __x32_compat_sys_rt_tgsigqueueinfo
378537 x32 recvmmsg __x32_compat_sys_recvmmsg 384537 x32 recvmmsg __x32_compat_sys_recvmmsg_time64
379538 x32 sendmmsg __x32_compat_sys_sendmmsg 385538 x32 sendmmsg __x32_compat_sys_sendmmsg
380539 x32 process_vm_readv __x32_compat_sys_process_vm_readv 386539 x32 process_vm_readv __x32_compat_sys_process_vm_readv
381540 x32 process_vm_writev __x32_compat_sys_process_vm_writev 387540 x32 process_vm_writev __x32_compat_sys_process_vm_writev
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
index 7aab0be5fc5f..47f9c56e744f 100644
--- a/tools/perf/arch/x86/util/Build
+++ b/tools/perf/arch/x86/util/Build
@@ -14,5 +14,6 @@ perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
14perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 14perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
15 15
16perf-$(CONFIG_AUXTRACE) += auxtrace.o 16perf-$(CONFIG_AUXTRACE) += auxtrace.o
17perf-$(CONFIG_AUXTRACE) += archinsn.o
17perf-$(CONFIG_AUXTRACE) += intel-pt.o 18perf-$(CONFIG_AUXTRACE) += intel-pt.o
18perf-$(CONFIG_AUXTRACE) += intel-bts.o 19perf-$(CONFIG_AUXTRACE) += intel-bts.o
diff --git a/tools/perf/arch/x86/util/archinsn.c b/tools/perf/arch/x86/util/archinsn.c
new file mode 100644
index 000000000000..4237bb2e7fa2
--- /dev/null
+++ b/tools/perf/arch/x86/util/archinsn.c
@@ -0,0 +1,26 @@
1// SPDX-License-Identifier: GPL-2.0
2#include "perf.h"
3#include "archinsn.h"
4#include "util/intel-pt-decoder/insn.h"
5#include "machine.h"
6#include "thread.h"
7#include "symbol.h"
8
9void arch_fetch_insn(struct perf_sample *sample,
10 struct thread *thread,
11 struct machine *machine)
12{
13 struct insn insn;
14 int len;
15 bool is64bit = false;
16
17 if (!sample->ip)
18 return;
19 len = thread__memcpy(thread, machine, sample->insn, sample->ip, sizeof(sample->insn), &is64bit);
20 if (len <= 0)
21 return;
22 insn_init(&insn, sample->insn, len, is64bit);
23 insn_get_length(&insn);
24 if (insn_complete(&insn) && insn.length <= len)
25 sample->insn_len = insn.length;
26}
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 f3f7f3100336..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 {
@@ -392,7 +395,7 @@ static int record__process_auxtrace(struct perf_tool *tool,
392 size_t padding; 395 size_t padding;
393 u8 pad[8] = {0}; 396 u8 pad[8] = {0};
394 397
395 if (!perf_data__is_pipe(data)) { 398 if (!perf_data__is_pipe(data) && !perf_data__is_dir(data)) {
396 off_t file_offset; 399 off_t file_offset;
397 int fd = perf_data__fd(data); 400 int fd = perf_data__fd(data);
398 int err; 401 int err;
@@ -837,6 +840,8 @@ static void record__init_features(struct record *rec)
837 if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns)) 840 if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
838 perf_header__clear_feat(&session->header, HEADER_CLOCKID); 841 perf_header__clear_feat(&session->header, HEADER_CLOCKID);
839 842
843 perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
844
840 perf_header__clear_feat(&session->header, HEADER_STAT); 845 perf_header__clear_feat(&session->header, HEADER_STAT);
841} 846}
842 847
@@ -890,6 +895,7 @@ record__switch_output(struct record *rec, bool at_exit)
890{ 895{
891 struct perf_data *data = &rec->data; 896 struct perf_data *data = &rec->data;
892 int fd, err; 897 int fd, err;
898 char *new_filename;
893 899
894 /* Same Size: "2015122520103046"*/ 900 /* Same Size: "2015122520103046"*/
895 char timestamp[] = "InvalidTimestamp"; 901 char timestamp[] = "InvalidTimestamp";
@@ -910,7 +916,7 @@ record__switch_output(struct record *rec, bool at_exit)
910 916
911 fd = perf_data__switch(data, timestamp, 917 fd = perf_data__switch(data, timestamp,
912 rec->session->header.data_offset, 918 rec->session->header.data_offset,
913 at_exit); 919 at_exit, &new_filename);
914 if (fd >= 0 && !at_exit) { 920 if (fd >= 0 && !at_exit) {
915 rec->bytes_written = 0; 921 rec->bytes_written = 0;
916 rec->session->header.data_size = 0; 922 rec->session->header.data_size = 0;
@@ -920,6 +926,21 @@ record__switch_output(struct record *rec, bool at_exit)
920 fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 926 fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
921 data->path, timestamp); 927 data->path, timestamp);
922 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
923 /* Output tracking events */ 944 /* Output tracking events */
924 if (!at_exit) { 945 if (!at_exit) {
925 record__synthesize(rec, false); 946 record__synthesize(rec, false);
@@ -1093,7 +1114,7 @@ static int record__synthesize(struct record *rec, bool tail)
1093 return err; 1114 return err;
1094 } 1115 }
1095 1116
1096 err = perf_event__synthesize_bpf_events(tool, process_synthesized_event, 1117 err = perf_event__synthesize_bpf_events(session, process_synthesized_event,
1097 machine, opts); 1118 machine, opts);
1098 if (err < 0) 1119 if (err < 0)
1099 pr_warning("Couldn't synthesize bpf events.\n"); 1120 pr_warning("Couldn't synthesize bpf events.\n");
@@ -1116,6 +1137,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
1116 struct perf_data *data = &rec->data; 1137 struct perf_data *data = &rec->data;
1117 struct perf_session *session; 1138 struct perf_session *session;
1118 bool disabled = false, draining = false; 1139 bool disabled = false, draining = false;
1140 struct perf_evlist *sb_evlist = NULL;
1119 int fd; 1141 int fd;
1120 1142
1121 atexit(record__sig_exit); 1143 atexit(record__sig_exit);
@@ -1216,6 +1238,14 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
1216 goto out_child; 1238 goto out_child;
1217 } 1239 }
1218 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
1219 err = record__synthesize(rec, false); 1249 err = record__synthesize(rec, false);
1220 if (err < 0) 1250 if (err < 0)
1221 goto out_child; 1251 goto out_child;
@@ -1466,6 +1496,9 @@ out_child:
1466 1496
1467out_delete_session: 1497out_delete_session:
1468 perf_session__delete(session); 1498 perf_session__delete(session);
1499
1500 if (!opts->no_bpf_event)
1501 perf_evlist__stop_sb_thread(sb_evlist);
1469 return status; 1502 return status;
1470} 1503}
1471 1504
@@ -1870,7 +1903,7 @@ static struct option __record_options[] = {
1870 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 1903 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
1871 "synthesize non-sample events at the end of output"), 1904 "synthesize non-sample events at the end of output"),
1872 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 1905 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1873 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"),
1874 OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq, 1907 OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
1875 "Fail if the specified frequency can't be used"), 1908 "Fail if the specified frequency can't be used"),
1876 OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'", 1909 OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
@@ -1968,9 +2001,11 @@ static struct option __record_options[] = {
1968 OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, 2001 OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
1969 "Record timestamp boundary (time of first/last samples)"), 2002 "Record timestamp boundary (time of first/last samples)"),
1970 OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 2003 OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
1971 &record.switch_output.set, "signal,size,time", 2004 &record.switch_output.set, "signal or size[BKMG] or time[smhd]",
1972 "Switch output when receive SIGUSR2 or cross size,time threshold", 2005 "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold",
1973 "signal"), 2006 "signal"),
2007 OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files,
2008 "Limit number of switch output generated files"),
1974 OPT_BOOLEAN(0, "dry-run", &dry_run, 2009 OPT_BOOLEAN(0, "dry-run", &dry_run,
1975 "Parse options then exit"), 2010 "Parse options then exit"),
1976#ifdef HAVE_AIO_SUPPORT 2011#ifdef HAVE_AIO_SUPPORT
@@ -2057,6 +2092,13 @@ int cmd_record(int argc, const char **argv)
2057 alarm(rec->switch_output.time); 2092 alarm(rec->switch_output.time);
2058 } 2093 }
2059 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
2060 /* 2102 /*
2061 * Allow aliases to facilitate the lookup of symbols for address 2103 * Allow aliases to facilitate the lookup of symbols for address
2062 * 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 ee93c18a6685..4054eb1f98ac 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -47,9 +47,11 @@
47#include <errno.h> 47#include <errno.h>
48#include <inttypes.h> 48#include <inttypes.h>
49#include <regex.h> 49#include <regex.h>
50#include "sane_ctype.h"
50#include <signal.h> 51#include <signal.h>
51#include <linux/bitmap.h> 52#include <linux/bitmap.h>
52#include <linux/stringify.h> 53#include <linux/stringify.h>
54#include <linux/time64.h>
53#include <sys/types.h> 55#include <sys/types.h>
54#include <sys/stat.h> 56#include <sys/stat.h>
55#include <unistd.h> 57#include <unistd.h>
@@ -926,6 +928,43 @@ report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
926 return parse_callchain_report_opt(arg); 928 return parse_callchain_report_opt(arg);
927} 929}
928 930
931static int
932parse_time_quantum(const struct option *opt, const char *arg,
933 int unset __maybe_unused)
934{
935 unsigned long *time_q = opt->value;
936 char *end;
937
938 *time_q = strtoul(arg, &end, 0);
939 if (end == arg)
940 goto parse_err;
941 if (*time_q == 0) {
942 pr_err("time quantum cannot be 0");
943 return -1;
944 }
945 while (isspace(*end))
946 end++;
947 if (*end == 0)
948 return 0;
949 if (!strcmp(end, "s")) {
950 *time_q *= NSEC_PER_SEC;
951 return 0;
952 }
953 if (!strcmp(end, "ms")) {
954 *time_q *= NSEC_PER_MSEC;
955 return 0;
956 }
957 if (!strcmp(end, "us")) {
958 *time_q *= NSEC_PER_USEC;
959 return 0;
960 }
961 if (!strcmp(end, "ns"))
962 return 0;
963parse_err:
964 pr_err("Cannot parse time quantum `%s'\n", arg);
965 return -1;
966}
967
929int 968int
930report_parse_ignore_callees_opt(const struct option *opt __maybe_unused, 969report_parse_ignore_callees_opt(const struct option *opt __maybe_unused,
931 const char *arg, int unset __maybe_unused) 970 const char *arg, int unset __maybe_unused)
@@ -1044,10 +1083,9 @@ int cmd_report(int argc, const char **argv)
1044 OPT_BOOLEAN(0, "header-only", &report.header_only, 1083 OPT_BOOLEAN(0, "header-only", &report.header_only,
1045 "Show only data header."), 1084 "Show only data header."),
1046 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1085 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1047 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." 1086 sort_help("sort by key(s):")),
1048 " Please refer the man page for the complete list."),
1049 OPT_STRING('F', "fields", &field_order, "key[,keys...]", 1087 OPT_STRING('F', "fields", &field_order, "key[,keys...]",
1050 "output field(s): overhead, period, sample plus all of sort keys"), 1088 sort_help("output field(s): overhead period sample ")),
1051 OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization, 1089 OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization,
1052 "Show sample percentage for different cpu modes"), 1090 "Show sample percentage for different cpu modes"),
1053 OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 1091 OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
@@ -1120,6 +1158,8 @@ int cmd_report(int argc, const char **argv)
1120 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 1158 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
1121 "Enable kernel symbol demangling"), 1159 "Enable kernel symbol demangling"),
1122 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), 1160 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
1161 OPT_INTEGER(0, "samples", &symbol_conf.res_sample,
1162 "Number of samples to save per histogram entry for individual browsing"),
1123 OPT_CALLBACK(0, "percent-limit", &report, "percent", 1163 OPT_CALLBACK(0, "percent-limit", &report, "percent",
1124 "Don't show entries under that percent", parse_percent_limit), 1164 "Don't show entries under that percent", parse_percent_limit),
1125 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 1165 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
@@ -1147,6 +1187,10 @@ int cmd_report(int argc, const char **argv)
1147 OPT_CALLBACK(0, "percent-type", &report.annotation_opts, "local-period", 1187 OPT_CALLBACK(0, "percent-type", &report.annotation_opts, "local-period",
1148 "Set percent type local/global-period/hits", 1188 "Set percent type local/global-period/hits",
1149 annotate_parse_percent_type), 1189 annotate_parse_percent_type),
1190 OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs, "Show times in nanosecs"),
1191 OPT_CALLBACK(0, "time-quantum", &symbol_conf.time_quantum, "time (ms|us|ns|s)",
1192 "Set time quantum for time sort key (default 100ms)",
1193 parse_time_quantum),
1150 OPT_END() 1194 OPT_END()
1151 }; 1195 };
1152 struct perf_data data = { 1196 struct perf_data data = {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 53f78cf3113f..61cfd8f70989 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -29,10 +29,12 @@
29#include "util/time-utils.h" 29#include "util/time-utils.h"
30#include "util/path.h" 30#include "util/path.h"
31#include "print_binary.h" 31#include "print_binary.h"
32#include "archinsn.h"
32#include <linux/bitmap.h> 33#include <linux/bitmap.h>
33#include <linux/kernel.h> 34#include <linux/kernel.h>
34#include <linux/stringify.h> 35#include <linux/stringify.h>
35#include <linux/time64.h> 36#include <linux/time64.h>
37#include <sys/utsname.h>
36#include "asm/bug.h" 38#include "asm/bug.h"
37#include "util/mem-events.h" 39#include "util/mem-events.h"
38#include "util/dump-insn.h" 40#include "util/dump-insn.h"
@@ -51,6 +53,8 @@
51 53
52static char const *script_name; 54static char const *script_name;
53static char const *generate_script_lang; 55static char const *generate_script_lang;
56static bool reltime;
57static u64 initial_time;
54static bool debug_mode; 58static bool debug_mode;
55static u64 last_timestamp; 59static u64 last_timestamp;
56static u64 nr_unordered; 60static u64 nr_unordered;
@@ -58,11 +62,11 @@ static bool no_callchain;
58static bool latency_format; 62static bool latency_format;
59static bool system_wide; 63static bool system_wide;
60static bool print_flags; 64static bool print_flags;
61static bool nanosecs;
62static const char *cpu_list; 65static const char *cpu_list;
63static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 66static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
64static struct perf_stat_config stat_config; 67static struct perf_stat_config stat_config;
65static int max_blocks; 68static int max_blocks;
69static bool native_arch;
66 70
67unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; 71unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
68 72
@@ -684,15 +688,21 @@ static int perf_sample__fprintf_start(struct perf_sample *sample,
684 } 688 }
685 689
686 if (PRINT_FIELD(TIME)) { 690 if (PRINT_FIELD(TIME)) {
687 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;
688 secs = nsecs / NSEC_PER_SEC; 698 secs = nsecs / NSEC_PER_SEC;
689 nsecs -= secs * NSEC_PER_SEC; 699 nsecs -= secs * NSEC_PER_SEC;
690 700
691 if (nanosecs) 701 if (symbol_conf.nanosecs)
692 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs); 702 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs);
693 else { 703 else {
694 char sample_time[32]; 704 char sample_time[32];
695 timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time)); 705 timestamp__scnprintf_usec(t, sample_time, sizeof(sample_time));
696 printed += fprintf(fp, "%12s: ", sample_time); 706 printed += fprintf(fp, "%12s: ", sample_time);
697 } 707 }
698 } 708 }
@@ -1227,6 +1237,12 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1227 return len + dlen; 1237 return len + dlen;
1228} 1238}
1229 1239
1240__weak void arch_fetch_insn(struct perf_sample *sample __maybe_unused,
1241 struct thread *thread __maybe_unused,
1242 struct machine *machine __maybe_unused)
1243{
1244}
1245
1230static int perf_sample__fprintf_insn(struct perf_sample *sample, 1246static int perf_sample__fprintf_insn(struct perf_sample *sample,
1231 struct perf_event_attr *attr, 1247 struct perf_event_attr *attr,
1232 struct thread *thread, 1248 struct thread *thread,
@@ -1234,9 +1250,12 @@ static int perf_sample__fprintf_insn(struct perf_sample *sample,
1234{ 1250{
1235 int printed = 0; 1251 int printed = 0;
1236 1252
1253 if (sample->insn_len == 0 && native_arch)
1254 arch_fetch_insn(sample, thread, machine);
1255
1237 if (PRINT_FIELD(INSNLEN)) 1256 if (PRINT_FIELD(INSNLEN))
1238 printed += fprintf(fp, " ilen: %d", sample->insn_len); 1257 printed += fprintf(fp, " ilen: %d", sample->insn_len);
1239 if (PRINT_FIELD(INSN)) { 1258 if (PRINT_FIELD(INSN) && sample->insn_len) {
1240 int i; 1259 int i;
1241 1260
1242 printed += fprintf(fp, " insn:"); 1261 printed += fprintf(fp, " insn:");
@@ -1922,6 +1941,13 @@ static int cleanup_scripting(void)
1922 return scripting_ops ? scripting_ops->stop_script() : 0; 1941 return scripting_ops ? scripting_ops->stop_script() : 0;
1923} 1942}
1924 1943
1944static bool filter_cpu(struct perf_sample *sample)
1945{
1946 if (cpu_list)
1947 return !test_bit(sample->cpu, cpu_bitmap);
1948 return false;
1949}
1950
1925static int process_sample_event(struct perf_tool *tool, 1951static int process_sample_event(struct perf_tool *tool,
1926 union perf_event *event, 1952 union perf_event *event,
1927 struct perf_sample *sample, 1953 struct perf_sample *sample,
@@ -1956,7 +1982,7 @@ static int process_sample_event(struct perf_tool *tool,
1956 if (al.filtered) 1982 if (al.filtered)
1957 goto out_put; 1983 goto out_put;
1958 1984
1959 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 1985 if (filter_cpu(sample))
1960 goto out_put; 1986 goto out_put;
1961 1987
1962 if (scripting_ops) 1988 if (scripting_ops)
@@ -2041,9 +2067,11 @@ static int process_comm_event(struct perf_tool *tool,
2041 sample->tid = event->comm.tid; 2067 sample->tid = event->comm.tid;
2042 sample->pid = event->comm.pid; 2068 sample->pid = event->comm.pid;
2043 } 2069 }
2044 perf_sample__fprintf_start(sample, thread, evsel, 2070 if (!filter_cpu(sample)) {
2071 perf_sample__fprintf_start(sample, thread, evsel,
2045 PERF_RECORD_COMM, stdout); 2072 PERF_RECORD_COMM, stdout);
2046 perf_event__fprintf(event, stdout); 2073 perf_event__fprintf(event, stdout);
2074 }
2047 ret = 0; 2075 ret = 0;
2048out: 2076out:
2049 thread__put(thread); 2077 thread__put(thread);
@@ -2077,9 +2105,11 @@ static int process_namespaces_event(struct perf_tool *tool,
2077 sample->tid = event->namespaces.tid; 2105 sample->tid = event->namespaces.tid;
2078 sample->pid = event->namespaces.pid; 2106 sample->pid = event->namespaces.pid;
2079 } 2107 }
2080 perf_sample__fprintf_start(sample, thread, evsel, 2108 if (!filter_cpu(sample)) {
2081 PERF_RECORD_NAMESPACES, stdout); 2109 perf_sample__fprintf_start(sample, thread, evsel,
2082 perf_event__fprintf(event, stdout); 2110 PERF_RECORD_NAMESPACES, stdout);
2111 perf_event__fprintf(event, stdout);
2112 }
2083 ret = 0; 2113 ret = 0;
2084out: 2114out:
2085 thread__put(thread); 2115 thread__put(thread);
@@ -2111,9 +2141,11 @@ static int process_fork_event(struct perf_tool *tool,
2111 sample->tid = event->fork.tid; 2141 sample->tid = event->fork.tid;
2112 sample->pid = event->fork.pid; 2142 sample->pid = event->fork.pid;
2113 } 2143 }
2114 perf_sample__fprintf_start(sample, thread, evsel, 2144 if (!filter_cpu(sample)) {
2115 PERF_RECORD_FORK, stdout); 2145 perf_sample__fprintf_start(sample, thread, evsel,
2116 perf_event__fprintf(event, stdout); 2146 PERF_RECORD_FORK, stdout);
2147 perf_event__fprintf(event, stdout);
2148 }
2117 thread__put(thread); 2149 thread__put(thread);
2118 2150
2119 return 0; 2151 return 0;
@@ -2141,9 +2173,11 @@ static int process_exit_event(struct perf_tool *tool,
2141 sample->tid = event->fork.tid; 2173 sample->tid = event->fork.tid;
2142 sample->pid = event->fork.pid; 2174 sample->pid = event->fork.pid;
2143 } 2175 }
2144 perf_sample__fprintf_start(sample, thread, evsel, 2176 if (!filter_cpu(sample)) {
2145 PERF_RECORD_EXIT, stdout); 2177 perf_sample__fprintf_start(sample, thread, evsel,
2146 perf_event__fprintf(event, stdout); 2178 PERF_RECORD_EXIT, stdout);
2179 perf_event__fprintf(event, stdout);
2180 }
2147 2181
2148 if (perf_event__process_exit(tool, event, sample, machine) < 0) 2182 if (perf_event__process_exit(tool, event, sample, machine) < 0)
2149 err = -1; 2183 err = -1;
@@ -2177,9 +2211,11 @@ static int process_mmap_event(struct perf_tool *tool,
2177 sample->tid = event->mmap.tid; 2211 sample->tid = event->mmap.tid;
2178 sample->pid = event->mmap.pid; 2212 sample->pid = event->mmap.pid;
2179 } 2213 }
2180 perf_sample__fprintf_start(sample, thread, evsel, 2214 if (!filter_cpu(sample)) {
2181 PERF_RECORD_MMAP, stdout); 2215 perf_sample__fprintf_start(sample, thread, evsel,
2182 perf_event__fprintf(event, stdout); 2216 PERF_RECORD_MMAP, stdout);
2217 perf_event__fprintf(event, stdout);
2218 }
2183 thread__put(thread); 2219 thread__put(thread);
2184 return 0; 2220 return 0;
2185} 2221}
@@ -2209,9 +2245,11 @@ static int process_mmap2_event(struct perf_tool *tool,
2209 sample->tid = event->mmap2.tid; 2245 sample->tid = event->mmap2.tid;
2210 sample->pid = event->mmap2.pid; 2246 sample->pid = event->mmap2.pid;
2211 } 2247 }
2212 perf_sample__fprintf_start(sample, thread, evsel, 2248 if (!filter_cpu(sample)) {
2213 PERF_RECORD_MMAP2, stdout); 2249 perf_sample__fprintf_start(sample, thread, evsel,
2214 perf_event__fprintf(event, stdout); 2250 PERF_RECORD_MMAP2, stdout);
2251 perf_event__fprintf(event, stdout);
2252 }
2215 thread__put(thread); 2253 thread__put(thread);
2216 return 0; 2254 return 0;
2217} 2255}
@@ -2236,9 +2274,11 @@ static int process_switch_event(struct perf_tool *tool,
2236 return -1; 2274 return -1;
2237 } 2275 }
2238 2276
2239 perf_sample__fprintf_start(sample, thread, evsel, 2277 if (!filter_cpu(sample)) {
2240 PERF_RECORD_SWITCH, stdout); 2278 perf_sample__fprintf_start(sample, thread, evsel,
2241 perf_event__fprintf(event, stdout); 2279 PERF_RECORD_SWITCH, stdout);
2280 perf_event__fprintf(event, stdout);
2281 }
2242 thread__put(thread); 2282 thread__put(thread);
2243 return 0; 2283 return 0;
2244} 2284}
@@ -2259,9 +2299,11 @@ process_lost_event(struct perf_tool *tool,
2259 if (thread == NULL) 2299 if (thread == NULL)
2260 return -1; 2300 return -1;
2261 2301
2262 perf_sample__fprintf_start(sample, thread, evsel, 2302 if (!filter_cpu(sample)) {
2263 PERF_RECORD_LOST, stdout); 2303 perf_sample__fprintf_start(sample, thread, evsel,
2264 perf_event__fprintf(event, stdout); 2304 PERF_RECORD_LOST, stdout);
2305 perf_event__fprintf(event, stdout);
2306 }
2265 thread__put(thread); 2307 thread__put(thread);
2266 return 0; 2308 return 0;
2267} 2309}
@@ -2948,7 +2990,8 @@ static int check_ev_match(char *dir_name, char *scriptname,
2948 * will list all statically runnable scripts, select one, execute it and 2990 * will list all statically runnable scripts, select one, execute it and
2949 * show the output in a perf browser. 2991 * show the output in a perf browser.
2950 */ 2992 */
2951int find_scripts(char **scripts_array, char **scripts_path_array) 2993int find_scripts(char **scripts_array, char **scripts_path_array, int num,
2994 int pathlen)
2952{ 2995{
2953 struct dirent *script_dirent, *lang_dirent; 2996 struct dirent *script_dirent, *lang_dirent;
2954 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; 2997 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
@@ -2993,7 +3036,10 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
2993 /* Skip those real time scripts: xxxtop.p[yl] */ 3036 /* Skip those real time scripts: xxxtop.p[yl] */
2994 if (strstr(script_dirent->d_name, "top.")) 3037 if (strstr(script_dirent->d_name, "top."))
2995 continue; 3038 continue;
2996 sprintf(scripts_path_array[i], "%s/%s", lang_path, 3039 if (i >= num)
3040 break;
3041 snprintf(scripts_path_array[i], pathlen, "%s/%s",
3042 lang_path,
2997 script_dirent->d_name); 3043 script_dirent->d_name);
2998 temp = strchr(script_dirent->d_name, '.'); 3044 temp = strchr(script_dirent->d_name, '.');
2999 snprintf(scripts_array[i], 3045 snprintf(scripts_array[i],
@@ -3232,7 +3278,7 @@ static int parse_insn_trace(const struct option *opt __maybe_unused,
3232{ 3278{
3233 parse_output_fields(NULL, "+insn,-event,-period", 0); 3279 parse_output_fields(NULL, "+insn,-event,-period", 0);
3234 itrace_parse_synth_opts(opt, "i0ns", 0); 3280 itrace_parse_synth_opts(opt, "i0ns", 0);
3235 nanosecs = true; 3281 symbol_conf.nanosecs = true;
3236 return 0; 3282 return 0;
3237} 3283}
3238 3284
@@ -3250,7 +3296,7 @@ static int parse_call_trace(const struct option *opt __maybe_unused,
3250{ 3296{
3251 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0); 3297 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
3252 itrace_parse_synth_opts(opt, "cewp", 0); 3298 itrace_parse_synth_opts(opt, "cewp", 0);
3253 nanosecs = true; 3299 symbol_conf.nanosecs = true;
3254 return 0; 3300 return 0;
3255} 3301}
3256 3302
@@ -3260,7 +3306,7 @@ static int parse_callret_trace(const struct option *opt __maybe_unused,
3260{ 3306{
3261 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0); 3307 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0);
3262 itrace_parse_synth_opts(opt, "crewp", 0); 3308 itrace_parse_synth_opts(opt, "crewp", 0);
3263 nanosecs = true; 3309 symbol_conf.nanosecs = true;
3264 return 0; 3310 return 0;
3265} 3311}
3266 3312
@@ -3277,6 +3323,7 @@ int cmd_script(int argc, const char **argv)
3277 .set = false, 3323 .set = false,
3278 .default_no_sample = true, 3324 .default_no_sample = true,
3279 }; 3325 };
3326 struct utsname uts;
3280 char *script_path = NULL; 3327 char *script_path = NULL;
3281 const char **__argv; 3328 const char **__argv;
3282 int i, j, err = 0; 3329 int i, j, err = 0;
@@ -3374,6 +3421,7 @@ int cmd_script(int argc, const char **argv)
3374 "Set the maximum stack depth when parsing the callchain, " 3421 "Set the maximum stack depth when parsing the callchain, "
3375 "anything beyond the specified depth will be ignored. " 3422 "anything beyond the specified depth will be ignored. "
3376 "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"),
3377 OPT_BOOLEAN('I', "show-info", &show_full_info, 3425 OPT_BOOLEAN('I', "show-info", &show_full_info,
3378 "display extended information from perf.data file"), 3426 "display extended information from perf.data file"),
3379 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 3427 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -3395,7 +3443,7 @@ int cmd_script(int argc, const char **argv)
3395 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 3443 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
3396 OPT_INTEGER(0, "max-blocks", &max_blocks, 3444 OPT_INTEGER(0, "max-blocks", &max_blocks,
3397 "Maximum number of code blocks to dump with brstackinsn"), 3445 "Maximum number of code blocks to dump with brstackinsn"),
3398 OPT_BOOLEAN(0, "ns", &nanosecs, 3446 OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs,
3399 "Use 9 decimal places when displaying time"), 3447 "Use 9 decimal places when displaying time"),
3400 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 3448 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
3401 "Instruction Tracing options\n" ITRACE_HELP, 3449 "Instruction Tracing options\n" ITRACE_HELP,
@@ -3448,6 +3496,11 @@ int cmd_script(int argc, const char **argv)
3448 } 3496 }
3449 } 3497 }
3450 3498
3499 if (script.time_str && reltime) {
3500 fprintf(stderr, "Don't combine --reltime with --time\n");
3501 return -1;
3502 }
3503
3451 if (itrace_synth_opts.callchain && 3504 if (itrace_synth_opts.callchain &&
3452 itrace_synth_opts.callchain_sz > scripting_max_stack) 3505 itrace_synth_opts.callchain_sz > scripting_max_stack)
3453 scripting_max_stack = itrace_synth_opts.callchain_sz; 3506 scripting_max_stack = itrace_synth_opts.callchain_sz;
@@ -3615,6 +3668,12 @@ int cmd_script(int argc, const char **argv)
3615 if (symbol__init(&session->header.env) < 0) 3668 if (symbol__init(&session->header.env) < 0)
3616 goto out_delete; 3669 goto out_delete;
3617 3670
3671 uname(&uts);
3672 if (!strcmp(uts.machine, session->header.env.arch) ||
3673 (!strcmp(uts.machine, "x86_64") &&
3674 !strcmp(session->header.env.arch, "i386")))
3675 native_arch = true;
3676
3618 script.session = session; 3677 script.session = session;
3619 script__setup_sample_type(&script); 3678 script__setup_sample_type(&script);
3620 3679
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/builtin.h b/tools/perf/builtin.h
index 05745f3ce912..999fe9170122 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -40,5 +40,6 @@ int cmd_mem(int argc, const char **argv);
40int cmd_data(int argc, const char **argv); 40int cmd_data(int argc, const char **argv);
41int cmd_ftrace(int argc, const char **argv); 41int cmd_ftrace(int argc, const char **argv);
42 42
43int find_scripts(char **scripts_array, char **scripts_path_array); 43int find_scripts(char **scripts_array, char **scripts_path_array, int num,
44 int pathlen);
44#endif 45#endif
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 7b55613924de..c68ee06cae63 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -103,7 +103,7 @@ done
103# diff with extra ignore lines 103# diff with extra ignore lines
104check arch/x86/lib/memcpy_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"' 104check arch/x86/lib/memcpy_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
105check arch/x86/lib/memset_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"' 105check arch/x86/lib/memset_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
106check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common.h>"' 106check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common\(-tools\)*.h>"'
107check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"' 107check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"'
108 108
109# diff non-symmetric files 109# diff non-symmetric files
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/pmu-events/arch/x86/amdfam17h/branch.json b/tools/perf/pmu-events/arch/x86/amdfam17h/branch.json
new file mode 100644
index 000000000000..93ddfd8053ca
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/amdfam17h/branch.json
@@ -0,0 +1,12 @@
1[
2 {
3 "EventName": "bp_l1_btb_correct",
4 "EventCode": "0x8a",
5 "BriefDescription": "L1 BTB Correction."
6 },
7 {
8 "EventName": "bp_l2_btb_correct",
9 "EventCode": "0x8b",
10 "BriefDescription": "L2 BTB Correction."
11 }
12]
diff --git a/tools/perf/pmu-events/arch/x86/amdfam17h/cache.json b/tools/perf/pmu-events/arch/x86/amdfam17h/cache.json
new file mode 100644
index 000000000000..fad4af9142cb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/amdfam17h/cache.json
@@ -0,0 +1,287 @@
1[
2 {
3 "EventName": "ic_fw32",
4 "EventCode": "0x80",
5 "BriefDescription": "The number of 32B fetch windows transferred from IC pipe to DE instruction decoder (includes non-cacheable and cacheable fill responses)."
6 },
7 {
8 "EventName": "ic_fw32_miss",
9 "EventCode": "0x81",
10 "BriefDescription": "The number of 32B fetch windows tried to read the L1 IC and missed in the full tag."
11 },
12 {
13 "EventName": "ic_cache_fill_l2",
14 "EventCode": "0x82",
15 "BriefDescription": "The number of 64 byte instruction cache line was fulfilled from the L2 cache."
16 },
17 {
18 "EventName": "ic_cache_fill_sys",
19 "EventCode": "0x83",
20 "BriefDescription": "The number of 64 byte instruction cache line fulfilled from system memory or another cache."
21 },
22 {
23 "EventName": "bp_l1_tlb_miss_l2_hit",
24 "EventCode": "0x84",
25 "BriefDescription": "The number of instruction fetches that miss in the L1 ITLB but hit in the L2 ITLB."
26 },
27 {
28 "EventName": "bp_l1_tlb_miss_l2_miss",
29 "EventCode": "0x85",
30 "BriefDescription": "The number of instruction fetches that miss in both the L1 and L2 TLBs."
31 },
32 {
33 "EventName": "bp_snp_re_sync",
34 "EventCode": "0x86",
35 "BriefDescription": "The number of pipeline restarts caused by invalidating probes that hit on the instruction stream currently being executed. This would happen if the active instruction stream was being modified by another processor in an MP system - typically a highly unlikely event."
36 },
37 {
38 "EventName": "ic_fetch_stall.ic_stall_any",
39 "EventCode": "0x87",
40 "BriefDescription": "IC pipe was stalled during this clock cycle for any reason (nothing valid in pipe ICM1).",
41 "PublicDescription": "Instruction Pipe Stall. IC pipe was stalled during this clock cycle for any reason (nothing valid in pipe ICM1).",
42 "UMask": "0x4"
43 },
44 {
45 "EventName": "ic_fetch_stall.ic_stall_dq_empty",
46 "EventCode": "0x87",
47 "BriefDescription": "IC pipe was stalled during this clock cycle (including IC to OC fetches) due to DQ empty.",
48 "PublicDescription": "Instruction Pipe Stall. IC pipe was stalled during this clock cycle (including IC to OC fetches) due to DQ empty.",
49 "UMask": "0x2"
50 },
51 {
52 "EventName": "ic_fetch_stall.ic_stall_back_pressure",
53 "EventCode": "0x87",
54 "BriefDescription": "IC pipe was stalled during this clock cycle (including IC to OC fetches) due to back-pressure.",
55 "PublicDescription": "Instruction Pipe Stall. IC pipe was stalled during this clock cycle (including IC to OC fetches) due to back-pressure.",
56 "UMask": "0x1"
57 },
58 {
59 "EventName": "ic_cache_inval.l2_invalidating_probe",
60 "EventCode": "0x8c",
61 "BriefDescription": "IC line invalidated due to L2 invalidating probe (external or LS).",
62 "PublicDescription": "The number of instruction cache lines invalidated. A non-SMC event is CMC (cross modifying code), either from the other thread of the core or another core. IC line invalidated due to L2 invalidating probe (external or LS).",
63 "UMask": "0x2"
64 },
65 {
66 "EventName": "ic_cache_inval.fill_invalidated",
67 "EventCode": "0x8c",
68 "BriefDescription": "IC line invalidated due to overwriting fill response.",
69 "PublicDescription": "The number of instruction cache lines invalidated. A non-SMC event is CMC (cross modifying code), either from the other thread of the core or another core. IC line invalidated due to overwriting fill response.",
70 "UMask": "0x1"
71 },
72 {
73 "EventName": "bp_tlb_rel",
74 "EventCode": "0x99",
75 "BriefDescription": "The number of ITLB reload requests."
76 },
77 {
78 "EventName": "l2_request_g1.rd_blk_l",
79 "EventCode": "0x60",
80 "BriefDescription": "Requests to L2 Group1.",
81 "PublicDescription": "Requests to L2 Group1.",
82 "UMask": "0x80"
83 },
84 {
85 "EventName": "l2_request_g1.rd_blk_x",
86 "EventCode": "0x60",
87 "BriefDescription": "Requests to L2 Group1.",
88 "PublicDescription": "Requests to L2 Group1.",
89 "UMask": "0x40"
90 },
91 {
92 "EventName": "l2_request_g1.ls_rd_blk_c_s",
93 "EventCode": "0x60",
94 "BriefDescription": "Requests to L2 Group1.",
95 "PublicDescription": "Requests to L2 Group1.",
96 "UMask": "0x20"
97 },
98 {
99 "EventName": "l2_request_g1.cacheable_ic_read",
100 "EventCode": "0x60",
101 "BriefDescription": "Requests to L2 Group1.",
102 "PublicDescription": "Requests to L2 Group1.",
103 "UMask": "0x10"
104 },
105 {
106 "EventName": "l2_request_g1.change_to_x",
107 "EventCode": "0x60",
108 "BriefDescription": "Requests to L2 Group1.",
109 "PublicDescription": "Requests to L2 Group1.",
110 "UMask": "0x8"
111 },
112 {
113 "EventName": "l2_request_g1.prefetch_l2",
114 "EventCode": "0x60",
115 "BriefDescription": "Requests to L2 Group1.",
116 "PublicDescription": "Requests to L2 Group1.",
117 "UMask": "0x4"
118 },
119 {
120 "EventName": "l2_request_g1.l2_hw_pf",
121 "EventCode": "0x60",
122 "BriefDescription": "Requests to L2 Group1.",
123 "PublicDescription": "Requests to L2 Group1.",
124 "UMask": "0x2"
125 },
126 {
127 "EventName": "l2_request_g1.other_requests",
128 "EventCode": "0x60",
129 "BriefDescription": "Events covered by l2_request_g2.",
130 "PublicDescription": "Requests to L2 Group1. Events covered by l2_request_g2.",
131 "UMask": "0x1"
132 },
133 {
134 "EventName": "l2_request_g2.group1",
135 "EventCode": "0x61",
136 "BriefDescription": "All Group 1 commands not in unit0.",
137 "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous. All Group 1 commands not in unit0.",
138 "UMask": "0x80"
139 },
140 {
141 "EventName": "l2_request_g2.ls_rd_sized",
142 "EventCode": "0x61",
143 "BriefDescription": "RdSized, RdSized32, RdSized64.",
144 "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous. RdSized, RdSized32, RdSized64.",
145 "UMask": "0x40"
146 },
147 {
148 "EventName": "l2_request_g2.ls_rd_sized_nc",
149 "EventCode": "0x61",
150 "BriefDescription": "RdSizedNC, RdSized32NC, RdSized64NC.",
151 "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous. RdSizedNC, RdSized32NC, RdSized64NC.",
152 "UMask": "0x20"
153 },
154 {
155 "EventName": "l2_request_g2.ic_rd_sized",
156 "EventCode": "0x61",
157 "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
158 "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
159 "UMask": "0x10"
160 },
161 {
162 "EventName": "l2_request_g2.ic_rd_sized_nc",
163 "EventCode": "0x61",
164 "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
165 "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
166 "UMask": "0x8"
167 },
168 {
169 "EventName": "l2_request_g2.smc_inval",
170 "EventCode": "0x61",
171 "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
172 "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
173 "UMask": "0x4"
174 },
175 {
176 "EventName": "l2_request_g2.bus_locks_originator",
177 "EventCode": "0x61",
178 "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
179 "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
180 "UMask": "0x2"
181 },
182 {
183 "EventName": "l2_request_g2.bus_locks_responses",
184 "EventCode": "0x61",
185 "BriefDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
186 "PublicDescription": "Multi-events in that LS and IF requests can be received simultaneous.",
187 "UMask": "0x1"
188 },
189 {
190 "EventName": "l2_latency.l2_cycles_waiting_on_fills",
191 "EventCode": "0x62",
192 "BriefDescription": "Total cycles spent waiting for L2 fills to complete from L3 or memory, divided by four. Event counts are for both threads. To calculate average latency, the number of fills from both threads must be used.",
193 "PublicDescription": "Total cycles spent waiting for L2 fills to complete from L3 or memory, divided by four. Event counts are for both threads. To calculate average latency, the number of fills from both threads must be used.",
194 "UMask": "0x1"
195 },
196 {
197 "EventName": "l2_wcb_req.wcb_write",
198 "EventCode": "0x63",
199 "PublicDescription": "LS (Load/Store unit) to L2 WCB (Write Combining Buffer) write requests.",
200 "BriefDescription": "LS to L2 WCB write requests.",
201 "UMask": "0x40"
202 },
203 {
204 "EventName": "l2_wcb_req.wcb_close",
205 "EventCode": "0x63",
206 "BriefDescription": "LS to L2 WCB close requests.",
207 "PublicDescription": "LS (Load/Store unit) to L2 WCB (Write Combining Buffer) close requests.",
208 "UMask": "0x20"
209 },
210 {
211 "EventName": "l2_wcb_req.zero_byte_store",
212 "EventCode": "0x63",
213 "BriefDescription": "LS to L2 WCB zero byte store requests.",
214 "PublicDescription": "LS (Load/Store unit) to L2 WCB (Write Combining Buffer) zero byte store requests.",
215 "UMask": "0x4"
216 },
217 {
218 "EventName": "l2_wcb_req.cl_zero",
219 "EventCode": "0x63",
220 "PublicDescription": "LS to L2 WCB cache line zeroing requests.",
221 "BriefDescription": "LS (Load/Store unit) to L2 WCB (Write Combining Buffer) cache line zeroing requests.",
222 "UMask": "0x1"
223 },
224 {
225 "EventName": "l2_cache_req_stat.ls_rd_blk_cs",
226 "EventCode": "0x64",
227 "BriefDescription": "LS ReadBlock C/S Hit.",
228 "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LS ReadBlock C/S Hit.",
229 "UMask": "0x80"
230 },
231 {
232 "EventName": "l2_cache_req_stat.ls_rd_blk_l_hit_x",
233 "EventCode": "0x64",
234 "BriefDescription": "LS Read Block L Hit X.",
235 "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LS Read Block L Hit X.",
236 "UMask": "0x40"
237 },
238 {
239 "EventName": "l2_cache_req_stat.ls_rd_blk_l_hit_s",
240 "EventCode": "0x64",
241 "BriefDescription": "LsRdBlkL Hit Shared.",
242 "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LsRdBlkL Hit Shared.",
243 "UMask": "0x20"
244 },
245 {
246 "EventName": "l2_cache_req_stat.ls_rd_blk_x",
247 "EventCode": "0x64",
248 "BriefDescription": "LsRdBlkX/ChgToX Hit X. Count RdBlkX finding Shared as a Miss.",
249 "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LsRdBlkX/ChgToX Hit X. Count RdBlkX finding Shared as a Miss.",
250 "UMask": "0x10"
251 },
252 {
253 "EventName": "l2_cache_req_stat.ls_rd_blk_c",
254 "EventCode": "0x64",
255 "BriefDescription": "LS Read Block C S L X Change to X Miss.",
256 "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. LS Read Block C S L X Change to X Miss.",
257 "UMask": "0x8"
258 },
259 {
260 "EventName": "l2_cache_req_stat.ic_fill_hit_x",
261 "EventCode": "0x64",
262 "BriefDescription": "IC Fill Hit Exclusive Stale.",
263 "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. IC Fill Hit Exclusive Stale.",
264 "UMask": "0x4"
265 },
266 {
267 "EventName": "l2_cache_req_stat.ic_fill_hit_s",
268 "EventCode": "0x64",
269 "BriefDescription": "IC Fill Hit Shared.",
270 "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. IC Fill Hit Shared.",
271 "UMask": "0x2"
272 },
273 {
274 "EventName": "l2_cache_req_stat.ic_fill_miss",
275 "EventCode": "0x64",
276 "BriefDescription": "IC Fill Miss.",
277 "PublicDescription": "This event does not count accesses to the L2 cache by the L2 prefetcher, but it does count accesses by the L1 prefetcher. IC Fill Miss.",
278 "UMask": "0x1"
279 },
280 {
281 "EventName": "l2_fill_pending.l2_fill_busy",
282 "EventCode": "0x6d",
283 "BriefDescription": "Total cycles spent with one or more fill requests in flight from L2.",
284 "PublicDescription": "Total cycles spent with one or more fill requests in flight from L2.",
285 "UMask": "0x1"
286 }
287]
diff --git a/tools/perf/pmu-events/arch/x86/amdfam17h/core.json b/tools/perf/pmu-events/arch/x86/amdfam17h/core.json
new file mode 100644
index 000000000000..7b285b0a7f35
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/amdfam17h/core.json
@@ -0,0 +1,134 @@
1[
2 {
3 "EventName": "ex_ret_instr",
4 "EventCode": "0xc0",
5 "BriefDescription": "Retired Instructions."
6 },
7 {
8 "EventName": "ex_ret_cops",
9 "EventCode": "0xc1",
10 "BriefDescription": "Retired Uops.",
11 "PublicDescription": "The number of uOps retired. This includes all processor activity (instructions, exceptions, interrupts, microcode assists, etc.). The number of events logged per cycle can vary from 0 to 4."
12 },
13 {
14 "EventName": "ex_ret_brn",
15 "EventCode": "0xc2",
16 "BriefDescription": "[Retired Branch Instructions.",
17 "PublicDescription": "The number of branch instructions retired. This includes all types of architectural control flow changes, including exceptions and interrupts."
18 },
19 {
20 "EventName": "ex_ret_brn_misp",
21 "EventCode": "0xc3",
22 "BriefDescription": "Retired Branch Instructions Mispredicted.",
23 "PublicDescription": "The number of branch instructions retired, of any type, that were not correctly predicted. This includes those for which prediction is not attempted (far control transfers, exceptions and interrupts)."
24 },
25 {
26 "EventName": "ex_ret_brn_tkn",
27 "EventCode": "0xc4",
28 "BriefDescription": "Retired Taken Branch Instructions.",
29 "PublicDescription": "The number of taken branches that were retired. This includes all types of architectural control flow changes, including exceptions and interrupts."
30 },
31 {
32 "EventName": "ex_ret_brn_tkn_misp",
33 "EventCode": "0xc5",
34 "BriefDescription": "Retired Taken Branch Instructions Mispredicted.",
35 "PublicDescription": "The number of retired taken branch instructions that were mispredicted."
36 },
37 {
38 "EventName": "ex_ret_brn_far",
39 "EventCode": "0xc6",
40 "BriefDescription": "Retired Far Control Transfers.",
41 "PublicDescription": "The number of far control transfers retired including far call/jump/return, IRET, SYSCALL and SYSRET, plus exceptions and interrupts. Far control transfers are not subject to branch prediction."
42 },
43 {
44 "EventName": "ex_ret_brn_resync",
45 "EventCode": "0xc7",
46 "BriefDescription": "Retired Branch Resyncs.",
47 "PublicDescription": "The number of resync branches. These reflect pipeline restarts due to certain microcode assists and events such as writes to the active instruction stream, among other things. Each occurrence reflects a restart penalty similar to a branch mispredict. This is relatively rare."
48 },
49 {
50 "EventName": "ex_ret_near_ret",
51 "EventCode": "0xc8",
52 "BriefDescription": "Retired Near Returns.",
53 "PublicDescription": "The number of near return instructions (RET or RET Iw) retired."
54 },
55 {
56 "EventName": "ex_ret_near_ret_mispred",
57 "EventCode": "0xc9",
58 "BriefDescription": "Retired Near Returns Mispredicted.",
59 "PublicDescription": "The number of near returns retired that were not correctly predicted by the return address predictor. Each such mispredict incurs the same penalty as a mispredicted conditional branch instruction."
60 },
61 {
62 "EventName": "ex_ret_brn_ind_misp",
63 "EventCode": "0xca",
64 "BriefDescription": "Retired Indirect Branch Instructions Mispredicted.",
65 "PublicDescription": "Retired Indirect Branch Instructions Mispredicted."
66 },
67 {
68 "EventName": "ex_ret_mmx_fp_instr.sse_instr",
69 "EventCode": "0xcb",
70 "BriefDescription": "SSE instructions (SSE, SSE2, SSE3, SSSE3, SSE4A, SSE41, SSE42, AVX).",
71 "PublicDescription": "The number of MMX, SSE or x87 instructions retired. The UnitMask allows the selection of the individual classes of instructions as given in the table. Each increment represents one complete instruction. Since this event includes non-numeric instructions it is not suitable for measuring MFLOPS. SSE instructions (SSE, SSE2, SSE3, SSSE3, SSE4A, SSE41, SSE42, AVX).",
72 "UMask": "0x4"
73 },
74 {
75 "EventName": "ex_ret_mmx_fp_instr.mmx_instr",
76 "EventCode": "0xcb",
77 "BriefDescription": "MMX instructions.",
78 "PublicDescription": "The number of MMX, SSE or x87 instructions retired. The UnitMask allows the selection of the individual classes of instructions as given in the table. Each increment represents one complete instruction. Since this event includes non-numeric instructions it is not suitable for measuring MFLOPS. MMX instructions.",
79 "UMask": "0x2"
80 },
81 {
82 "EventName": "ex_ret_mmx_fp_instr.x87_instr",
83 "EventCode": "0xcb",
84 "BriefDescription": "x87 instructions.",
85 "PublicDescription": "The number of MMX, SSE or x87 instructions retired. The UnitMask allows the selection of the individual classes of instructions as given in the table. Each increment represents one complete instruction. Since this event includes non-numeric instructions it is not suitable for measuring MFLOPS. x87 instructions.",
86 "UMask": "0x1"
87 },
88 {
89 "EventName": "ex_ret_cond",
90 "EventCode": "0xd1",
91 "BriefDescription": "Retired Conditional Branch Instructions."
92 },
93 {
94 "EventName": "ex_ret_cond_misp",
95 "EventCode": "0xd2",
96 "BriefDescription": "Retired Conditional Branch Instructions Mispredicted."
97 },
98 {
99 "EventName": "ex_div_busy",
100 "EventCode": "0xd3",
101 "BriefDescription": "Div Cycles Busy count."
102 },
103 {
104 "EventName": "ex_div_count",
105 "EventCode": "0xd4",
106 "BriefDescription": "Div Op Count."
107 },
108 {
109 "EventName": "ex_tagged_ibs_ops.ibs_count_rollover",
110 "EventCode": "0x1cf",
111 "BriefDescription": "Number of times an op could not be tagged by IBS because of a previous tagged op that has not retired.",
112 "PublicDescription": "Tagged IBS Ops. Number of times an op could not be tagged by IBS because of a previous tagged op that has not retired.",
113 "UMask": "0x4"
114 },
115 {
116 "EventName": "ex_tagged_ibs_ops.ibs_tagged_ops_ret",
117 "EventCode": "0x1cf",
118 "BriefDescription": "Number of Ops tagged by IBS that retired.",
119 "PublicDescription": "Tagged IBS Ops. Number of Ops tagged by IBS that retired.",
120 "UMask": "0x2"
121 },
122 {
123 "EventName": "ex_tagged_ibs_ops.ibs_tagged_ops",
124 "EventCode": "0x1cf",
125 "BriefDescription": "Number of Ops tagged by IBS.",
126 "PublicDescription": "Tagged IBS Ops. Number of Ops tagged by IBS.",
127 "UMask": "0x1"
128 },
129 {
130 "EventName": "ex_ret_fus_brnch_inst",
131 "EventCode": "0x1d0",
132 "BriefDescription": "The number of fused retired branch instructions retired per cycle. The number of events logged per cycle can vary from 0 to 3."
133 }
134]
diff --git a/tools/perf/pmu-events/arch/x86/amdfam17h/floating-point.json b/tools/perf/pmu-events/arch/x86/amdfam17h/floating-point.json
new file mode 100644
index 000000000000..ea4711983d1d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/amdfam17h/floating-point.json
@@ -0,0 +1,168 @@
1[
2 {
3 "EventName": "fpu_pipe_assignment.dual",
4 "EventCode": "0x00",
5 "BriefDescription": "Total number multi-pipe uOps.",
6 "PublicDescription": "The number of operations (uOps) and dual-pipe uOps dispatched to each of the 4 FPU execution pipelines. This event reflects how busy the FPU pipelines are and may be used for workload characterization. This includes all operations performed by x87, MMX, and SSE instructions, including moves. Each increment represents a one- cycle dispatch event. This event is a speculative event. Since this event includes non-numeric operations it is not suitable for measuring MFLOPS. Total number multi-pipe uOps assigned to Pipe 3.",
7 "UMask": "0xf0"
8 },
9 {
10 "EventName": "fpu_pipe_assignment.total",
11 "EventCode": "0x00",
12 "BriefDescription": "Total number uOps.",
13 "PublicDescription": "The number of operations (uOps) and dual-pipe uOps dispatched to each of the 4 FPU execution pipelines. This event reflects how busy the FPU pipelines are and may be used for workload characterization. This includes all operations performed by x87, MMX, and SSE instructions, including moves. Each increment represents a one- cycle dispatch event. This event is a speculative event. Since this event includes non-numeric operations it is not suitable for measuring MFLOPS. Total number uOps assigned to Pipe 3.",
14 "UMask": "0xf"
15 },
16 {
17 "EventName": "fp_sched_empty",
18 "EventCode": "0x01",
19 "BriefDescription": "This is a speculative event. The number of cycles in which the FPU scheduler is empty. Note that some Ops like FP loads bypass the scheduler."
20 },
21 {
22 "EventName": "fp_retx87_fp_ops.all",
23 "EventCode": "0x02",
24 "BriefDescription": "All Ops.",
25 "PublicDescription": "The number of x87 floating-point Ops that have retired. The number of events logged per cycle can vary from 0 to 8.",
26 "UMask": "0x7"
27 },
28 {
29 "EventName": "fp_retx87_fp_ops.div_sqr_r_ops",
30 "EventCode": "0x02",
31 "BriefDescription": "Divide and square root Ops.",
32 "PublicDescription": "The number of x87 floating-point Ops that have retired. The number of events logged per cycle can vary from 0 to 8. Divide and square root Ops.",
33 "UMask": "0x4"
34 },
35 {
36 "EventName": "fp_retx87_fp_ops.mul_ops",
37 "EventCode": "0x02",
38 "BriefDescription": "Multiply Ops.",
39 "PublicDescription": "The number of x87 floating-point Ops that have retired. The number of events logged per cycle can vary from 0 to 8. Multiply Ops.",
40 "UMask": "0x2"
41 },
42 {
43 "EventName": "fp_retx87_fp_ops.add_sub_ops",
44 "EventCode": "0x02",
45 "BriefDescription": "Add/subtract Ops.",
46 "PublicDescription": "The number of x87 floating-point Ops that have retired. The number of events logged per cycle can vary from 0 to 8. Add/subtract Ops.",
47 "UMask": "0x1"
48 },
49 {
50 "EventName": "fp_ret_sse_avx_ops.all",
51 "EventCode": "0x03",
52 "BriefDescription": "All FLOPS.",
53 "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15.",
54 "UMask": "0xff"
55 },
56 {
57 "EventName": "fp_ret_sse_avx_ops.dp_mult_add_flops",
58 "EventCode": "0x03",
59 "BriefDescription": "Double precision multiply-add FLOPS. Multiply-add counts as 2 FLOPS.",
60 "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Double precision multiply-add FLOPS. Multiply-add counts as 2 FLOPS.",
61 "UMask": "0x80"
62 },
63 {
64 "EventName": "fp_ret_sse_avx_ops.dp_div_flops",
65 "EventCode": "0x03",
66 "BriefDescription": "Double precision divide/square root FLOPS.",
67 "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Double precision divide/square root FLOPS.",
68 "UMask": "0x40"
69 },
70 {
71 "EventName": "fp_ret_sse_avx_ops.dp_mult_flops",
72 "EventCode": "0x03",
73 "BriefDescription": "Double precision multiply FLOPS.",
74 "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Double precision multiply FLOPS.",
75 "UMask": "0x20"
76 },
77 {
78 "EventName": "fp_ret_sse_avx_ops.dp_add_sub_flops",
79 "EventCode": "0x03",
80 "BriefDescription": "Double precision add/subtract FLOPS.",
81 "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Double precision add/subtract FLOPS.",
82 "UMask": "0x10"
83 },
84 {
85 "EventName": "fp_ret_sse_avx_ops.sp_mult_add_flops",
86 "EventCode": "0x03",
87 "BriefDescription": "Single precision multiply-add FLOPS. Multiply-add counts as 2 FLOPS.",
88 "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Single precision multiply-add FLOPS. Multiply-add counts as 2 FLOPS.",
89 "UMask": "0x8"
90 },
91 {
92 "EventName": "fp_ret_sse_avx_ops.sp_div_flops",
93 "EventCode": "0x03",
94 "BriefDescription": "Single-precision divide/square root FLOPS.",
95 "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Single-precision divide/square root FLOPS.",
96 "UMask": "0x4"
97 },
98 {
99 "EventName": "fp_ret_sse_avx_ops.sp_mult_flops",
100 "EventCode": "0x03",
101 "BriefDescription": "Single-precision multiply FLOPS.",
102 "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Single-precision multiply FLOPS.",
103 "UMask": "0x2"
104 },
105 {
106 "EventName": "fp_ret_sse_avx_ops.sp_add_sub_flops",
107 "EventCode": "0x03",
108 "BriefDescription": "Single-precision add/subtract FLOPS.",
109 "PublicDescription": "This is a retire-based event. The number of retired SSE/AVX FLOPS. The number of events logged per cycle can vary from 0 to 64. This event can count above 15. Single-precision add/subtract FLOPS.",
110 "UMask": "0x1"
111 },
112 {
113 "EventName": "fp_num_mov_elim_scal_op.optimized",
114 "EventCode": "0x04",
115 "BriefDescription": "Number of Scalar Ops optimized.",
116 "PublicDescription": "This is a dispatch based speculative event, and is useful for measuring the effectiveness of the Move elimination and Scalar code optimization schemes. Number of Scalar Ops optimized.",
117 "UMask": "0x8"
118 },
119 {
120 "EventName": "fp_num_mov_elim_scal_op.opt_potential",
121 "EventCode": "0x04",
122 "BriefDescription": "Number of Ops that are candidates for optimization (have Z-bit either set or pass).",
123 "PublicDescription": "This is a dispatch based speculative event, and is useful for measuring the effectiveness of the Move elimination and Scalar code optimization schemes. Number of Ops that are candidates for optimization (have Z-bit either set or pass).",
124 "UMask": "0x4"
125 },
126 {
127 "EventName": "fp_num_mov_elim_scal_op.sse_mov_ops_elim",
128 "EventCode": "0x04",
129 "BriefDescription": "Number of SSE Move Ops eliminated.",
130 "PublicDescription": "This is a dispatch based speculative event, and is useful for measuring the effectiveness of the Move elimination and Scalar code optimization schemes. Number of SSE Move Ops eliminated.",
131 "UMask": "0x2"
132 },
133 {
134 "EventName": "fp_num_mov_elim_scal_op.sse_mov_ops",
135 "EventCode": "0x04",
136 "BriefDescription": "Number of SSE Move Ops.",
137 "PublicDescription": "This is a dispatch based speculative event, and is useful for measuring the effectiveness of the Move elimination and Scalar code optimization schemes. Number of SSE Move Ops.",
138 "UMask": "0x1"
139 },
140 {
141 "EventName": "fp_retired_ser_ops.x87_ctrl_ret",
142 "EventCode": "0x05",
143 "BriefDescription": "x87 control word mispredict traps due to mispredictions in RC or PC, or changes in mask bits.",
144 "PublicDescription": "The number of serializing Ops retired. x87 control word mispredict traps due to mispredictions in RC or PC, or changes in mask bits.",
145 "UMask": "0x8"
146 },
147 {
148 "EventName": "fp_retired_ser_ops.x87_bot_ret",
149 "EventCode": "0x05",
150 "BriefDescription": "x87 bottom-executing uOps retired.",
151 "PublicDescription": "The number of serializing Ops retired. x87 bottom-executing uOps retired.",
152 "UMask": "0x4"
153 },
154 {
155 "EventName": "fp_retired_ser_ops.sse_ctrl_ret",
156 "EventCode": "0x05",
157 "BriefDescription": "SSE control word mispredict traps due to mispredictions in RC, FTZ or DAZ, or changes in mask bits.",
158 "PublicDescription": "The number of serializing Ops retired. SSE control word mispredict traps due to mispredictions in RC, FTZ or DAZ, or changes in mask bits.",
159 "UMask": "0x2"
160 },
161 {
162 "EventName": "fp_retired_ser_ops.sse_bot_ret",
163 "EventCode": "0x05",
164 "BriefDescription": "SSE bottom-executing uOps retired.",
165 "PublicDescription": "The number of serializing Ops retired. SSE bottom-executing uOps retired.",
166 "UMask": "0x1"
167 }
168]
diff --git a/tools/perf/pmu-events/arch/x86/amdfam17h/memory.json b/tools/perf/pmu-events/arch/x86/amdfam17h/memory.json
new file mode 100644
index 000000000000..fa2d60d4def0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/amdfam17h/memory.json
@@ -0,0 +1,162 @@
1[
2 {
3 "EventName": "ls_locks.bus_lock",
4 "EventCode": "0x25",
5 "BriefDescription": "Bus lock when a locked operations crosses a cache boundary or is done on an uncacheable memory type.",
6 "PublicDescription": "Bus lock when a locked operations crosses a cache boundary or is done on an uncacheable memory type.",
7 "UMask": "0x1"
8 },
9 {
10 "EventName": "ls_dispatch.ld_st_dispatch",
11 "EventCode": "0x29",
12 "BriefDescription": "Load-op-Stores.",
13 "PublicDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed. Load-op-Stores.",
14 "UMask": "0x4"
15 },
16 {
17 "EventName": "ls_dispatch.store_dispatch",
18 "EventCode": "0x29",
19 "BriefDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed.",
20 "PublicDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed.",
21 "UMask": "0x2"
22 },
23 {
24 "EventName": "ls_dispatch.ld_dispatch",
25 "EventCode": "0x29",
26 "BriefDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed.",
27 "PublicDescription": "Counts the number of operations dispatched to the LS unit. Unit Masks ADDed.",
28 "UMask": "0x1"
29 },
30 {
31 "EventName": "ls_stlf",
32 "EventCode": "0x35",
33 "BriefDescription": "Number of STLF hits."
34 },
35 {
36 "EventName": "ls_dc_accesses",
37 "EventCode": "0x40",
38 "BriefDescription": "The number of accesses to the data cache for load and store references. This may include certain microcode scratchpad accesses, although these are generally rare. Each increment represents an eight-byte access, although the instruction may only be accessing a portion of that. This event is a speculative event."
39 },
40 {
41 "EventName": "ls_l1_d_tlb_miss.all",
42 "EventCode": "0x45",
43 "BriefDescription": "L1 DTLB Miss or Reload off all sizes.",
44 "PublicDescription": "L1 DTLB Miss or Reload off all sizes.",
45 "UMask": "0xff"
46 },
47 {
48 "EventName": "ls_l1_d_tlb_miss.tlb_reload_1g_l2_miss",
49 "EventCode": "0x45",
50 "BriefDescription": "L1 DTLB Miss of a page of 1G size.",
51 "PublicDescription": "L1 DTLB Miss of a page of 1G size.",
52 "UMask": "0x80"
53 },
54 {
55 "EventName": "ls_l1_d_tlb_miss.tlb_reload_2m_l2_miss",
56 "EventCode": "0x45",
57 "BriefDescription": "L1 DTLB Miss of a page of 2M size.",
58 "PublicDescription": "L1 DTLB Miss of a page of 2M size.",
59 "UMask": "0x40"
60 },
61 {
62 "EventName": "ls_l1_d_tlb_miss.tlb_reload_32k_l2_miss",
63 "EventCode": "0x45",
64 "BriefDescription": "L1 DTLB Miss of a page of 32K size.",
65 "PublicDescription": "L1 DTLB Miss of a page of 32K size.",
66 "UMask": "0x20"
67 },
68 {
69 "EventName": "ls_l1_d_tlb_miss.tlb_reload_4k_l2_miss",
70 "EventCode": "0x45",
71 "BriefDescription": "L1 DTLB Miss of a page of 4K size.",
72 "PublicDescription": "L1 DTLB Miss of a page of 4K size.",
73 "UMask": "0x10"
74 },
75 {
76 "EventName": "ls_l1_d_tlb_miss.tlb_reload_1g_l2_hit",
77 "EventCode": "0x45",
78 "BriefDescription": "L1 DTLB Reload of a page of 1G size.",
79 "PublicDescription": "L1 DTLB Reload of a page of 1G size.",
80 "UMask": "0x8"
81 },
82 {
83 "EventName": "ls_l1_d_tlb_miss.tlb_reload_2m_l2_hit",
84 "EventCode": "0x45",
85 "BriefDescription": "L1 DTLB Reload of a page of 2M size.",
86 "PublicDescription": "L1 DTLB Reload of a page of 2M size.",
87 "UMask": "0x4"
88 },
89 {
90 "EventName": "ls_l1_d_tlb_miss.tlb_reload_32k_l2_hit",
91 "EventCode": "0x45",
92 "BriefDescription": "L1 DTLB Reload of a page of 32K size.",
93 "PublicDescription": "L1 DTLB Reload of a page of 32K size.",
94 "UMask": "0x2"
95 },
96 {
97 "EventName": "ls_l1_d_tlb_miss.tlb_reload_4k_l2_hit",
98 "EventCode": "0x45",
99 "BriefDescription": "L1 DTLB Reload of a page of 4K size.",
100 "PublicDescription": "L1 DTLB Reload of a page of 4K size.",
101 "UMask": "0x1"
102 },
103 {
104 "EventName": "ls_tablewalker.perf_mon_tablewalk_alloc_iside",
105 "EventCode": "0x46",
106 "BriefDescription": "Tablewalker allocation.",
107 "PublicDescription": "Tablewalker allocation.",
108 "UMask": "0xc"
109 },
110 {
111 "EventName": "ls_tablewalker.perf_mon_tablewalk_alloc_dside",
112 "EventCode": "0x46",
113 "BriefDescription": "Tablewalker allocation.",
114 "PublicDescription": "Tablewalker allocation.",
115 "UMask": "0x3"
116 },
117 {
118 "EventName": "ls_misal_accesses",
119 "EventCode": "0x47",
120 "BriefDescription": "Misaligned loads."
121 },
122 {
123 "EventName": "ls_pref_instr_disp.prefetch_nta",
124 "EventCode": "0x4b",
125 "BriefDescription": "Software Prefetch Instructions (PREFETCHNTA instruction) Dispatched.",
126 "PublicDescription": "Software Prefetch Instructions (PREFETCHNTA instruction) Dispatched.",
127 "UMask": "0x4"
128 },
129 {
130 "EventName": "ls_pref_instr_disp.store_prefetch_w",
131 "EventCode": "0x4b",
132 "BriefDescription": "Software Prefetch Instructions (3DNow PREFETCHW instruction) Dispatched.",
133 "PublicDescription": "Software Prefetch Instructions (3DNow PREFETCHW instruction) Dispatched.",
134 "UMask": "0x2"
135 },
136 {
137 "EventName": "ls_pref_instr_disp.load_prefetch_w",
138 "EventCode": "0x4b",
139 "BriefDescription": "Prefetch, Prefetch_T0_T1_T2.",
140 "PublicDescription": "Software Prefetch Instructions Dispatched. Prefetch, Prefetch_T0_T1_T2.",
141 "UMask": "0x1"
142 },
143 {
144 "EventName": "ls_inef_sw_pref.mab_mch_cnt",
145 "EventCode": "0x52",
146 "BriefDescription": "The number of software prefetches that did not fetch data outside of the processor core.",
147 "PublicDescription": "The number of software prefetches that did not fetch data outside of the processor core.",
148 "UMask": "0x2"
149 },
150 {
151 "EventName": "ls_inef_sw_pref.data_pipe_sw_pf_dc_hit",
152 "EventCode": "0x52",
153 "BriefDescription": "The number of software prefetches that did not fetch data outside of the processor core.",
154 "PublicDescription": "The number of software prefetches that did not fetch data outside of the processor core.",
155 "UMask": "0x1"
156 },
157 {
158 "EventName": "ls_not_halted_cyc",
159 "EventCode": "0x76",
160 "BriefDescription": "Cycles not in Halt."
161 }
162]
diff --git a/tools/perf/pmu-events/arch/x86/amdfam17h/other.json b/tools/perf/pmu-events/arch/x86/amdfam17h/other.json
new file mode 100644
index 000000000000..b26a00d05a2e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/amdfam17h/other.json
@@ -0,0 +1,65 @@
1[
2 {
3 "EventName": "ic_oc_mode_switch.oc_ic_mode_switch",
4 "EventCode": "0x28a",
5 "BriefDescription": "OC to IC mode switch.",
6 "PublicDescription": "OC Mode Switch. OC to IC mode switch.",
7 "UMask": "0x2"
8 },
9 {
10 "EventName": "ic_oc_mode_switch.ic_oc_mode_switch",
11 "EventCode": "0x28a",
12 "BriefDescription": "IC to OC mode switch.",
13 "PublicDescription": "OC Mode Switch. IC to OC mode switch.",
14 "UMask": "0x1"
15 },
16 {
17 "EventName": "de_dis_dispatch_token_stalls0.retire_token_stall",
18 "EventCode": "0xaf",
19 "BriefDescription": "RETIRE Tokens unavailable.",
20 "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. RETIRE Tokens unavailable.",
21 "UMask": "0x40"
22 },
23 {
24 "EventName": "de_dis_dispatch_token_stalls0.agsq_token_stall",
25 "EventCode": "0xaf",
26 "BriefDescription": "AGSQ Tokens unavailable.",
27 "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. AGSQ Tokens unavailable.",
28 "UMask": "0x20"
29 },
30 {
31 "EventName": "de_dis_dispatch_token_stalls0.alu_token_stall",
32 "EventCode": "0xaf",
33 "BriefDescription": "ALU tokens total unavailable.",
34 "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. ALU tokens total unavailable.",
35 "UMask": "0x10"
36 },
37 {
38 "EventName": "de_dis_dispatch_token_stalls0.alsq3_0_token_stall",
39 "EventCode": "0xaf",
40 "BriefDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall.",
41 "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall.",
42 "UMask": "0x8"
43 },
44 {
45 "EventName": "de_dis_dispatch_token_stalls0.alsq3_token_stall",
46 "EventCode": "0xaf",
47 "BriefDescription": "ALSQ 3 Tokens unavailable.",
48 "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. ALSQ 3 Tokens unavailable.",
49 "UMask": "0x4"
50 },
51 {
52 "EventName": "de_dis_dispatch_token_stalls0.alsq2_token_stall",
53 "EventCode": "0xaf",
54 "BriefDescription": "ALSQ 2 Tokens unavailable.",
55 "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. ALSQ 2 Tokens unavailable.",
56 "UMask": "0x2"
57 },
58 {
59 "EventName": "de_dis_dispatch_token_stalls0.alsq1_token_stall",
60 "EventCode": "0xaf",
61 "BriefDescription": "ALSQ 1 Tokens unavailable.",
62 "PublicDescription": "Cycles where a dispatch group is valid but does not get dispatched due to a token stall. ALSQ 1 Tokens unavailable.",
63 "UMask": "0x1"
64 }
65]
diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv
index e05c2c8458fc..d6984a3017e0 100644
--- a/tools/perf/pmu-events/arch/x86/mapfile.csv
+++ b/tools/perf/pmu-events/arch/x86/mapfile.csv
@@ -33,3 +33,4 @@ GenuineIntel-6-25,v2,westmereep-sp,core
33GenuineIntel-6-2F,v2,westmereex,core 33GenuineIntel-6-2F,v2,westmereex,core
34GenuineIntel-6-55-[01234],v1,skylakex,core 34GenuineIntel-6-55-[01234],v1,skylakex,core
35GenuineIntel-6-55-[56789ABCDEF],v1,cascadelakex,core 35GenuineIntel-6-55-[56789ABCDEF],v1,cascadelakex,core
36AuthenticAMD-23-[[:xdigit:]]+,v1,amdfam17h,core
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 390a351d15ea..c3eae1d77d36 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -10,6 +10,8 @@
10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11# more details. 11# more details.
12 12
13from __future__ import print_function
14
13import os 15import os
14import sys 16import sys
15import struct 17import struct
@@ -199,6 +201,18 @@ import datetime
199 201
200from PySide.QtSql import * 202from PySide.QtSql import *
201 203
204if sys.version_info < (3, 0):
205 def toserverstr(str):
206 return str
207 def toclientstr(str):
208 return str
209else:
210 # Assume UTF-8 server_encoding and client_encoding
211 def toserverstr(str):
212 return bytes(str, "UTF_8")
213 def toclientstr(str):
214 return bytes(str, "UTF_8")
215
202# Need to access PostgreSQL C library directly to use COPY FROM STDIN 216# Need to access PostgreSQL C library directly to use COPY FROM STDIN
203from ctypes import * 217from ctypes import *
204libpq = CDLL("libpq.so.5") 218libpq = CDLL("libpq.so.5")
@@ -234,12 +248,17 @@ perf_db_export_mode = True
234perf_db_export_calls = False 248perf_db_export_calls = False
235perf_db_export_callchains = False 249perf_db_export_callchains = False
236 250
251def printerr(*args, **kw_args):
252 print(*args, file=sys.stderr, **kw_args)
253
254def printdate(*args, **kw_args):
255 print(datetime.datetime.today(), *args, sep=' ', **kw_args)
237 256
238def usage(): 257def usage():
239 print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]" 258 printerr("Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]")
240 print >> sys.stderr, "where: columns 'all' or 'branches'" 259 printerr("where: columns 'all' or 'branches'")
241 print >> sys.stderr, " calls 'calls' => create calls and call_paths table" 260 printerr(" calls 'calls' => create calls and call_paths table")
242 print >> sys.stderr, " callchains 'callchains' => create call_paths table" 261 printerr(" callchains 'callchains' => create call_paths table")
243 raise Exception("Too few arguments") 262 raise Exception("Too few arguments")
244 263
245if (len(sys.argv) < 2): 264if (len(sys.argv) < 2):
@@ -273,7 +292,7 @@ def do_query(q, s):
273 return 292 return
274 raise Exception("Query failed: " + q.lastError().text()) 293 raise Exception("Query failed: " + q.lastError().text())
275 294
276print datetime.datetime.today(), "Creating database..." 295printdate("Creating database...")
277 296
278db = QSqlDatabase.addDatabase('QPSQL') 297db = QSqlDatabase.addDatabase('QPSQL')
279query = QSqlQuery(db) 298query = QSqlQuery(db)
@@ -506,12 +525,12 @@ do_query(query, 'CREATE VIEW samples_view AS '
506 ' FROM samples') 525 ' FROM samples')
507 526
508 527
509file_header = struct.pack("!11sii", "PGCOPY\n\377\r\n\0", 0, 0) 528file_header = struct.pack("!11sii", b"PGCOPY\n\377\r\n\0", 0, 0)
510file_trailer = "\377\377" 529file_trailer = b"\377\377"
511 530
512def open_output_file(file_name): 531def open_output_file(file_name):
513 path_name = output_dir_name + "/" + file_name 532 path_name = output_dir_name + "/" + file_name
514 file = open(path_name, "w+") 533 file = open(path_name, "wb+")
515 file.write(file_header) 534 file.write(file_header)
516 return file 535 return file
517 536
@@ -526,13 +545,13 @@ def copy_output_file_direct(file, table_name):
526 545
527# Use COPY FROM STDIN because security may prevent postgres from accessing the files directly 546# Use COPY FROM STDIN because security may prevent postgres from accessing the files directly
528def copy_output_file(file, table_name): 547def copy_output_file(file, table_name):
529 conn = PQconnectdb("dbname = " + dbname) 548 conn = PQconnectdb(toclientstr("dbname = " + dbname))
530 if (PQstatus(conn)): 549 if (PQstatus(conn)):
531 raise Exception("COPY FROM STDIN PQconnectdb failed") 550 raise Exception("COPY FROM STDIN PQconnectdb failed")
532 file.write(file_trailer) 551 file.write(file_trailer)
533 file.seek(0) 552 file.seek(0)
534 sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')" 553 sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')"
535 res = PQexec(conn, sql) 554 res = PQexec(conn, toclientstr(sql))
536 if (PQresultStatus(res) != 4): 555 if (PQresultStatus(res) != 4):
537 raise Exception("COPY FROM STDIN PQexec failed") 556 raise Exception("COPY FROM STDIN PQexec failed")
538 data = file.read(65536) 557 data = file.read(65536)
@@ -566,7 +585,7 @@ if perf_db_export_calls:
566 call_file = open_output_file("call_table.bin") 585 call_file = open_output_file("call_table.bin")
567 586
568def trace_begin(): 587def trace_begin():
569 print datetime.datetime.today(), "Writing to intermediate files..." 588 printdate("Writing to intermediate files...")
570 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs 589 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs
571 evsel_table(0, "unknown") 590 evsel_table(0, "unknown")
572 machine_table(0, 0, "unknown") 591 machine_table(0, 0, "unknown")
@@ -582,7 +601,7 @@ def trace_begin():
582unhandled_count = 0 601unhandled_count = 0
583 602
584def trace_end(): 603def trace_end():
585 print datetime.datetime.today(), "Copying to database..." 604 printdate("Copying to database...")
586 copy_output_file(evsel_file, "selected_events") 605 copy_output_file(evsel_file, "selected_events")
587 copy_output_file(machine_file, "machines") 606 copy_output_file(machine_file, "machines")
588 copy_output_file(thread_file, "threads") 607 copy_output_file(thread_file, "threads")
@@ -597,7 +616,7 @@ def trace_end():
597 if perf_db_export_calls: 616 if perf_db_export_calls:
598 copy_output_file(call_file, "calls") 617 copy_output_file(call_file, "calls")
599 618
600 print datetime.datetime.today(), "Removing intermediate files..." 619 printdate("Removing intermediate files...")
601 remove_output_file(evsel_file) 620 remove_output_file(evsel_file)
602 remove_output_file(machine_file) 621 remove_output_file(machine_file)
603 remove_output_file(thread_file) 622 remove_output_file(thread_file)
@@ -612,7 +631,7 @@ def trace_end():
612 if perf_db_export_calls: 631 if perf_db_export_calls:
613 remove_output_file(call_file) 632 remove_output_file(call_file)
614 os.rmdir(output_dir_name) 633 os.rmdir(output_dir_name)
615 print datetime.datetime.today(), "Adding primary keys" 634 printdate("Adding primary keys")
616 do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)') 635 do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)')
617 do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)') 636 do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)')
618 do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)') 637 do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)')
@@ -627,7 +646,7 @@ def trace_end():
627 if perf_db_export_calls: 646 if perf_db_export_calls:
628 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)') 647 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)')
629 648
630 print datetime.datetime.today(), "Adding foreign keys" 649 printdate("Adding foreign keys")
631 do_query(query, 'ALTER TABLE threads ' 650 do_query(query, 'ALTER TABLE threads '
632 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),' 651 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),'
633 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)') 652 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)')
@@ -663,8 +682,8 @@ def trace_end():
663 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') 682 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
664 683
665 if (unhandled_count): 684 if (unhandled_count):
666 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" 685 printdate("Warning: ", unhandled_count, " unhandled events")
667 print datetime.datetime.today(), "Done" 686 printdate("Done")
668 687
669def trace_unhandled(event_name, context, event_fields_dict): 688def trace_unhandled(event_name, context, event_fields_dict):
670 global unhandled_count 689 global unhandled_count
@@ -674,12 +693,14 @@ def sched__sched_switch(*x):
674 pass 693 pass
675 694
676def evsel_table(evsel_id, evsel_name, *x): 695def evsel_table(evsel_id, evsel_name, *x):
696 evsel_name = toserverstr(evsel_name)
677 n = len(evsel_name) 697 n = len(evsel_name)
678 fmt = "!hiqi" + str(n) + "s" 698 fmt = "!hiqi" + str(n) + "s"
679 value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name) 699 value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name)
680 evsel_file.write(value) 700 evsel_file.write(value)
681 701
682def machine_table(machine_id, pid, root_dir, *x): 702def machine_table(machine_id, pid, root_dir, *x):
703 root_dir = toserverstr(root_dir)
683 n = len(root_dir) 704 n = len(root_dir)
684 fmt = "!hiqiii" + str(n) + "s" 705 fmt = "!hiqiii" + str(n) + "s"
685 value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir) 706 value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir)
@@ -690,6 +711,7 @@ def thread_table(thread_id, machine_id, process_id, pid, tid, *x):
690 thread_file.write(value) 711 thread_file.write(value)
691 712
692def comm_table(comm_id, comm_str, *x): 713def comm_table(comm_id, comm_str, *x):
714 comm_str = toserverstr(comm_str)
693 n = len(comm_str) 715 n = len(comm_str)
694 fmt = "!hiqi" + str(n) + "s" 716 fmt = "!hiqi" + str(n) + "s"
695 value = struct.pack(fmt, 2, 8, comm_id, n, comm_str) 717 value = struct.pack(fmt, 2, 8, comm_id, n, comm_str)
@@ -701,6 +723,9 @@ def comm_thread_table(comm_thread_id, comm_id, thread_id, *x):
701 comm_thread_file.write(value) 723 comm_thread_file.write(value)
702 724
703def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x): 725def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x):
726 short_name = toserverstr(short_name)
727 long_name = toserverstr(long_name)
728 build_id = toserverstr(build_id)
704 n1 = len(short_name) 729 n1 = len(short_name)
705 n2 = len(long_name) 730 n2 = len(long_name)
706 n3 = len(build_id) 731 n3 = len(build_id)
@@ -709,12 +734,14 @@ def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x):
709 dso_file.write(value) 734 dso_file.write(value)
710 735
711def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x): 736def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x):
737 symbol_name = toserverstr(symbol_name)
712 n = len(symbol_name) 738 n = len(symbol_name)
713 fmt = "!hiqiqiqiqiii" + str(n) + "s" 739 fmt = "!hiqiqiqiqiii" + str(n) + "s"
714 value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name) 740 value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name)
715 symbol_file.write(value) 741 symbol_file.write(value)
716 742
717def branch_type_table(branch_type, name, *x): 743def branch_type_table(branch_type, name, *x):
744 name = toserverstr(name)
718 n = len(name) 745 n = len(name)
719 fmt = "!hiii" + str(n) + "s" 746 fmt = "!hiii" + str(n) + "s"
720 value = struct.pack(fmt, 2, 4, branch_type, n, name) 747 value = struct.pack(fmt, 2, 4, branch_type, n, name)
diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py
index eb63e6c7107f..3b71902a5a21 100644
--- a/tools/perf/scripts/python/export-to-sqlite.py
+++ b/tools/perf/scripts/python/export-to-sqlite.py
@@ -10,6 +10,8 @@
10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11# more details. 11# more details.
12 12
13from __future__ import print_function
14
13import os 15import os
14import sys 16import sys
15import struct 17import struct
@@ -60,11 +62,17 @@ perf_db_export_mode = True
60perf_db_export_calls = False 62perf_db_export_calls = False
61perf_db_export_callchains = False 63perf_db_export_callchains = False
62 64
65def printerr(*args, **keyword_args):
66 print(*args, file=sys.stderr, **keyword_args)
67
68def printdate(*args, **kw_args):
69 print(datetime.datetime.today(), *args, sep=' ', **kw_args)
70
63def usage(): 71def usage():
64 print >> sys.stderr, "Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>]" 72 printerr("Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>]");
65 print >> sys.stderr, "where: columns 'all' or 'branches'" 73 printerr("where: columns 'all' or 'branches'");
66 print >> sys.stderr, " calls 'calls' => create calls and call_paths table" 74 printerr(" calls 'calls' => create calls and call_paths table");
67 print >> sys.stderr, " callchains 'callchains' => create call_paths table" 75 printerr(" callchains 'callchains' => create call_paths table");
68 raise Exception("Too few arguments") 76 raise Exception("Too few arguments")
69 77
70if (len(sys.argv) < 2): 78if (len(sys.argv) < 2):
@@ -100,7 +108,7 @@ def do_query_(q):
100 return 108 return
101 raise Exception("Query failed: " + q.lastError().text()) 109 raise Exception("Query failed: " + q.lastError().text())
102 110
103print datetime.datetime.today(), "Creating database..." 111printdate("Creating database ...")
104 112
105db_exists = False 113db_exists = False
106try: 114try:
@@ -378,7 +386,7 @@ if perf_db_export_calls:
378 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") 386 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
379 387
380def trace_begin(): 388def trace_begin():
381 print datetime.datetime.today(), "Writing records..." 389 printdate("Writing records...")
382 do_query(query, 'BEGIN TRANSACTION') 390 do_query(query, 'BEGIN TRANSACTION')
383 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs 391 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs
384 evsel_table(0, "unknown") 392 evsel_table(0, "unknown")
@@ -397,14 +405,14 @@ unhandled_count = 0
397def trace_end(): 405def trace_end():
398 do_query(query, 'END TRANSACTION') 406 do_query(query, 'END TRANSACTION')
399 407
400 print datetime.datetime.today(), "Adding indexes" 408 printdate("Adding indexes")
401 if perf_db_export_calls: 409 if perf_db_export_calls:
402 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') 410 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
403 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') 411 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
404 412
405 if (unhandled_count): 413 if (unhandled_count):
406 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" 414 printdate("Warning: ", unhandled_count, " unhandled events")
407 print datetime.datetime.today(), "Done" 415 printdate("Done")
408 416
409def trace_unhandled(event_name, context, event_fields_dict): 417def trace_unhandled(event_name, context, event_fields_dict):
410 global unhandled_count 418 global unhandled_count
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py
index afec9479ca7f..74ef92f1d19a 100755
--- a/tools/perf/scripts/python/exported-sql-viewer.py
+++ b/tools/perf/scripts/python/exported-sql-viewer.py
@@ -88,20 +88,39 @@
88# 7fab593ea956 48 89 15 3b 13 22 00 movq %rdx, 0x22133b(%rip) 88# 7fab593ea956 48 89 15 3b 13 22 00 movq %rdx, 0x22133b(%rip)
89# 8107675243232 2 ls 22011 22011 hardware interrupt No 7fab593ea956 _dl_start+0x26 (ld-2.19.so) -> ffffffff86a012e0 page_fault ([kernel]) 89# 8107675243232 2 ls 22011 22011 hardware interrupt No 7fab593ea956 _dl_start+0x26 (ld-2.19.so) -> ffffffff86a012e0 page_fault ([kernel])
90 90
91from __future__ import print_function
92
91import sys 93import sys
92import weakref 94import weakref
93import threading 95import threading
94import string 96import string
95import cPickle 97try:
98 # Python2
99 import cPickle as pickle
100 # size of pickled integer big enough for record size
101 glb_nsz = 8
102except ImportError:
103 import pickle
104 glb_nsz = 16
96import re 105import re
97import os 106import os
98from PySide.QtCore import * 107from PySide.QtCore import *
99from PySide.QtGui import * 108from PySide.QtGui import *
100from PySide.QtSql import * 109from PySide.QtSql import *
110pyside_version_1 = True
101from decimal import * 111from decimal import *
102from ctypes import * 112from ctypes import *
103from multiprocessing import Process, Array, Value, Event 113from multiprocessing import Process, Array, Value, Event
104 114
115# xrange is range in Python3
116try:
117 xrange
118except NameError:
119 xrange = range
120
121def printerr(*args, **keyword_args):
122 print(*args, file=sys.stderr, **keyword_args)
123
105# Data formatting helpers 124# Data formatting helpers
106 125
107def tohex(ip): 126def tohex(ip):
@@ -1004,10 +1023,6 @@ class ChildDataItemFinder():
1004 1023
1005glb_chunk_sz = 10000 1024glb_chunk_sz = 10000
1006 1025
1007# size of pickled integer big enough for record size
1008
1009glb_nsz = 8
1010
1011# Background process for SQL data fetcher 1026# Background process for SQL data fetcher
1012 1027
1013class SQLFetcherProcess(): 1028class SQLFetcherProcess():
@@ -1066,7 +1081,7 @@ class SQLFetcherProcess():
1066 return True 1081 return True
1067 if space >= glb_nsz: 1082 if space >= glb_nsz:
1068 # Use 0 (or space < glb_nsz) to mean there is no more at the top of the buffer 1083 # Use 0 (or space < glb_nsz) to mean there is no more at the top of the buffer
1069 nd = cPickle.dumps(0, cPickle.HIGHEST_PROTOCOL) 1084 nd = pickle.dumps(0, pickle.HIGHEST_PROTOCOL)
1070 self.buffer[self.local_head : self.local_head + len(nd)] = nd 1085 self.buffer[self.local_head : self.local_head + len(nd)] = nd
1071 self.local_head = 0 1086 self.local_head = 0
1072 if self.local_tail - self.local_head > sz: 1087 if self.local_tail - self.local_head > sz:
@@ -1084,9 +1099,9 @@ class SQLFetcherProcess():
1084 self.wait_event.wait() 1099 self.wait_event.wait()
1085 1100
1086 def AddToBuffer(self, obj): 1101 def AddToBuffer(self, obj):
1087 d = cPickle.dumps(obj, cPickle.HIGHEST_PROTOCOL) 1102 d = pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
1088 n = len(d) 1103 n = len(d)
1089 nd = cPickle.dumps(n, cPickle.HIGHEST_PROTOCOL) 1104 nd = pickle.dumps(n, pickle.HIGHEST_PROTOCOL)
1090 sz = n + glb_nsz 1105 sz = n + glb_nsz
1091 self.WaitForSpace(sz) 1106 self.WaitForSpace(sz)
1092 pos = self.local_head 1107 pos = self.local_head
@@ -1198,12 +1213,12 @@ class SQLFetcher(QObject):
1198 pos = self.local_tail 1213 pos = self.local_tail
1199 if len(self.buffer) - pos < glb_nsz: 1214 if len(self.buffer) - pos < glb_nsz:
1200 pos = 0 1215 pos = 0
1201 n = cPickle.loads(self.buffer[pos : pos + glb_nsz]) 1216 n = pickle.loads(self.buffer[pos : pos + glb_nsz])
1202 if n == 0: 1217 if n == 0:
1203 pos = 0 1218 pos = 0
1204 n = cPickle.loads(self.buffer[0 : glb_nsz]) 1219 n = pickle.loads(self.buffer[0 : glb_nsz])
1205 pos += glb_nsz 1220 pos += glb_nsz
1206 obj = cPickle.loads(self.buffer[pos : pos + n]) 1221 obj = pickle.loads(self.buffer[pos : pos + n])
1207 self.local_tail = pos + n 1222 self.local_tail = pos + n
1208 return obj 1223 return obj
1209 1224
@@ -1512,6 +1527,19 @@ def BranchDataPrep(query):
1512 " (" + dsoname(query.value(15)) + ")") 1527 " (" + dsoname(query.value(15)) + ")")
1513 return data 1528 return data
1514 1529
1530def BranchDataPrepWA(query):
1531 data = []
1532 data.append(query.value(0))
1533 # Workaround pyside failing to handle large integers (i.e. time) in python3 by converting to a string
1534 data.append("{:>19}".format(query.value(1)))
1535 for i in xrange(2, 8):
1536 data.append(query.value(i))
1537 data.append(tohex(query.value(8)).rjust(16) + " " + query.value(9) + offstr(query.value(10)) +
1538 " (" + dsoname(query.value(11)) + ")" + " -> " +
1539 tohex(query.value(12)) + " " + query.value(13) + offstr(query.value(14)) +
1540 " (" + dsoname(query.value(15)) + ")")
1541 return data
1542
1515# Branch data model 1543# Branch data model
1516 1544
1517class BranchModel(TreeModel): 1545class BranchModel(TreeModel):
@@ -1539,7 +1567,11 @@ class BranchModel(TreeModel):
1539 " AND evsel_id = " + str(self.event_id) + 1567 " AND evsel_id = " + str(self.event_id) +
1540 " ORDER BY samples.id" 1568 " ORDER BY samples.id"
1541 " LIMIT " + str(glb_chunk_sz)) 1569 " LIMIT " + str(glb_chunk_sz))
1542 self.fetcher = SQLFetcher(glb, sql, BranchDataPrep, self.AddSample) 1570 if pyside_version_1 and sys.version_info[0] == 3:
1571 prep = BranchDataPrepWA
1572 else:
1573 prep = BranchDataPrep
1574 self.fetcher = SQLFetcher(glb, sql, prep, self.AddSample)
1543 self.fetcher.done.connect(self.Update) 1575 self.fetcher.done.connect(self.Update)
1544 self.fetcher.Fetch(glb_chunk_sz) 1576 self.fetcher.Fetch(glb_chunk_sz)
1545 1577
@@ -2065,14 +2097,6 @@ def IsSelectable(db, table, sql = ""):
2065 return False 2097 return False
2066 return True 2098 return True
2067 2099
2068# SQL data preparation
2069
2070def SQLTableDataPrep(query, count):
2071 data = []
2072 for i in xrange(count):
2073 data.append(query.value(i))
2074 return data
2075
2076# SQL table data model item 2100# SQL table data model item
2077 2101
2078class SQLTableItem(): 2102class SQLTableItem():
@@ -2096,7 +2120,7 @@ class SQLTableModel(TableModel):
2096 self.more = True 2120 self.more = True
2097 self.populated = 0 2121 self.populated = 0
2098 self.column_headers = column_headers 2122 self.column_headers = column_headers
2099 self.fetcher = SQLFetcher(glb, sql, lambda x, y=len(column_headers): SQLTableDataPrep(x, y), self.AddSample) 2123 self.fetcher = SQLFetcher(glb, sql, lambda x, y=len(column_headers): self.SQLTableDataPrep(x, y), self.AddSample)
2100 self.fetcher.done.connect(self.Update) 2124 self.fetcher.done.connect(self.Update)
2101 self.fetcher.Fetch(glb_chunk_sz) 2125 self.fetcher.Fetch(glb_chunk_sz)
2102 2126
@@ -2140,6 +2164,12 @@ class SQLTableModel(TableModel):
2140 def columnHeader(self, column): 2164 def columnHeader(self, column):
2141 return self.column_headers[column] 2165 return self.column_headers[column]
2142 2166
2167 def SQLTableDataPrep(self, query, count):
2168 data = []
2169 for i in xrange(count):
2170 data.append(query.value(i))
2171 return data
2172
2143# SQL automatic table data model 2173# SQL automatic table data model
2144 2174
2145class SQLAutoTableModel(SQLTableModel): 2175class SQLAutoTableModel(SQLTableModel):
@@ -2168,8 +2198,32 @@ class SQLAutoTableModel(SQLTableModel):
2168 QueryExec(query, "SELECT column_name FROM information_schema.columns WHERE table_schema = '" + schema + "' and table_name = '" + select_table_name + "'") 2198 QueryExec(query, "SELECT column_name FROM information_schema.columns WHERE table_schema = '" + schema + "' and table_name = '" + select_table_name + "'")
2169 while query.next(): 2199 while query.next():
2170 column_headers.append(query.value(0)) 2200 column_headers.append(query.value(0))
2201 if pyside_version_1 and sys.version_info[0] == 3:
2202 if table_name == "samples_view":
2203 self.SQLTableDataPrep = self.samples_view_DataPrep
2204 if table_name == "samples":
2205 self.SQLTableDataPrep = self.samples_DataPrep
2171 super(SQLAutoTableModel, self).__init__(glb, sql, column_headers, parent) 2206 super(SQLAutoTableModel, self).__init__(glb, sql, column_headers, parent)
2172 2207
2208 def samples_view_DataPrep(self, query, count):
2209 data = []
2210 data.append(query.value(0))
2211 # Workaround pyside failing to handle large integers (i.e. time) in python3 by converting to a string
2212 data.append("{:>19}".format(query.value(1)))
2213 for i in xrange(2, count):
2214 data.append(query.value(i))
2215 return data
2216
2217 def samples_DataPrep(self, query, count):
2218 data = []
2219 for i in xrange(9):
2220 data.append(query.value(i))
2221 # Workaround pyside failing to handle large integers (i.e. time) in python3 by converting to a string
2222 data.append("{:>19}".format(query.value(9)))
2223 for i in xrange(10, count):
2224 data.append(query.value(i))
2225 return data
2226
2173# Base class for custom ResizeColumnsToContents 2227# Base class for custom ResizeColumnsToContents
2174 2228
2175class ResizeColumnsToContentsBase(QObject): 2229class ResizeColumnsToContentsBase(QObject):
@@ -2854,9 +2908,13 @@ class LibXED():
2854 ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0) 2908 ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0)
2855 if not ok: 2909 if not ok:
2856 return 0, "" 2910 return 0, ""
2911 if sys.version_info[0] == 2:
2912 result = inst.buffer.value
2913 else:
2914 result = inst.buffer.value.decode()
2857 # Return instruction length and the disassembled instruction text 2915 # Return instruction length and the disassembled instruction text
2858 # For now, assume the length is in byte 166 2916 # For now, assume the length is in byte 166
2859 return inst.xedd[166], inst.buffer.value 2917 return inst.xedd[166], result
2860 2918
2861def TryOpen(file_name): 2919def TryOpen(file_name):
2862 try: 2920 try:
@@ -2872,9 +2930,14 @@ def Is64Bit(f):
2872 header = f.read(7) 2930 header = f.read(7)
2873 f.seek(pos) 2931 f.seek(pos)
2874 magic = header[0:4] 2932 magic = header[0:4]
2875 eclass = ord(header[4]) 2933 if sys.version_info[0] == 2:
2876 encoding = ord(header[5]) 2934 eclass = ord(header[4])
2877 version = ord(header[6]) 2935 encoding = ord(header[5])
2936 version = ord(header[6])
2937 else:
2938 eclass = header[4]
2939 encoding = header[5]
2940 version = header[6]
2878 if magic == chr(127) + "ELF" and eclass > 0 and eclass < 3 and encoding > 0 and encoding < 3 and version == 1: 2941 if magic == chr(127) + "ELF" and eclass > 0 and eclass < 3 and encoding > 0 and encoding < 3 and version == 1:
2879 result = True if eclass == 2 else False 2942 result = True if eclass == 2 else False
2880 return result 2943 return result
@@ -2973,7 +3036,7 @@ class DBRef():
2973 3036
2974def Main(): 3037def Main():
2975 if (len(sys.argv) < 2): 3038 if (len(sys.argv) < 2):
2976 print >> sys.stderr, "Usage is: exported-sql-viewer.py {<database name> | --help-only}" 3039 printerr("Usage is: exported-sql-viewer.py {<database name> | --help-only}");
2977 raise Exception("Too few arguments") 3040 raise Exception("Too few arguments")
2978 3041
2979 dbname = sys.argv[1] 3042 dbname = sys.argv[1]
@@ -2986,8 +3049,8 @@ def Main():
2986 3049
2987 is_sqlite3 = False 3050 is_sqlite3 = False
2988 try: 3051 try:
2989 f = open(dbname) 3052 f = open(dbname, "rb")
2990 if f.read(15) == "SQLite format 3": 3053 if f.read(15) == b'SQLite format 3':
2991 is_sqlite3 = True 3054 is_sqlite3 = True
2992 f.close() 3055 f.close()
2993 except: 3056 except:
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/trace/beauty/mmap_flags.sh b/tools/perf/trace/beauty/mmap_flags.sh
index 32bac9c0d694..5f5eefcb3c74 100755
--- a/tools/perf/trace/beauty/mmap_flags.sh
+++ b/tools/perf/trace/beauty/mmap_flags.sh
@@ -1,15 +1,18 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1 2# SPDX-License-Identifier: LGPL-2.1
3 3
4if [ $# -ne 2 ] ; then 4if [ $# -ne 3 ] ; then
5 [ $# -eq 1 ] && hostarch=$1 || hostarch=`uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/` 5 [ $# -eq 1 ] && hostarch=$1 || hostarch=`uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/`
6 linux_header_dir=tools/include/uapi/linux
6 header_dir=tools/include/uapi/asm-generic 7 header_dir=tools/include/uapi/asm-generic
7 arch_header_dir=tools/arch/${hostarch}/include/uapi/asm 8 arch_header_dir=tools/arch/${hostarch}/include/uapi/asm
8else 9else
9 header_dir=$1 10 linux_header_dir=$1
10 arch_header_dir=$2 11 header_dir=$2
12 arch_header_dir=$3
11fi 13fi
12 14
15linux_mman=${linux_header_dir}/mman.h
13arch_mman=${arch_header_dir}/mman.h 16arch_mman=${arch_header_dir}/mman.h
14 17
15# those in egrep -vw are flags, we want just the bits 18# those in egrep -vw are flags, we want just the bits
@@ -20,6 +23,11 @@ egrep -q $regex ${arch_mman} && \
20(egrep $regex ${arch_mman} | \ 23(egrep $regex ${arch_mman} | \
21 sed -r "s/$regex/\2 \1/g" | \ 24 sed -r "s/$regex/\2 \1/g" | \
22 xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n") 25 xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
26egrep -q $regex ${linux_mman} && \
27(egrep $regex ${linux_mman} | \
28 egrep -vw 'MAP_(UNINITIALIZED|TYPE|SHARED_VALIDATE)' | \
29 sed -r "s/$regex/\2 \1/g" | \
30 xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
23([ ! -f ${arch_mman} ] || egrep -q '#[[:space:]]*include[[:space:]]+<uapi/asm-generic/mman.*' ${arch_mman}) && 31([ ! -f ${arch_mman} ] || egrep -q '#[[:space:]]*include[[:space:]]+<uapi/asm-generic/mman.*' ${arch_mman}) &&
24(egrep $regex ${header_dir}/mman-common.h | \ 32(egrep $regex ${header_dir}/mman-common.h | \
25 egrep -vw 'MAP_(UNINITIALIZED|TYPE|SHARED_VALIDATE)' | \ 33 egrep -vw 'MAP_(UNINITIALIZED|TYPE|SHARED_VALIDATE)' | \
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 4f75561424ed..4ad37d8c7d6a 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -611,14 +611,16 @@ void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence)
611 browser->top = browser->entries; 611 browser->top = browser->entries;
612 break; 612 break;
613 case SEEK_CUR: 613 case SEEK_CUR:
614 browser->top = browser->top + browser->top_idx + offset; 614 browser->top = (char **)browser->top + offset;
615 break; 615 break;
616 case SEEK_END: 616 case SEEK_END:
617 browser->top = browser->top + browser->nr_entries - 1 + offset; 617 browser->top = (char **)browser->entries + browser->nr_entries - 1 + offset;
618 break; 618 break;
619 default: 619 default:
620 return; 620 return;
621 } 621 }
622 assert((char **)browser->top < (char **)browser->entries + browser->nr_entries);
623 assert((char **)browser->top >= (char **)browser->entries);
622} 624}
623 625
624unsigned int ui_browser__argv_refresh(struct ui_browser *browser) 626unsigned int ui_browser__argv_refresh(struct ui_browser *browser)
@@ -630,7 +632,9 @@ unsigned int ui_browser__argv_refresh(struct ui_browser *browser)
630 browser->top = browser->entries; 632 browser->top = browser->entries;
631 633
632 pos = (char **)browser->top; 634 pos = (char **)browser->top;
633 while (idx < browser->nr_entries) { 635 while (idx < browser->nr_entries &&
636 row < (unsigned)SLtt_Screen_Rows - 1) {
637 assert(pos < (char **)browser->entries + browser->nr_entries);
634 if (!browser->filter || !browser->filter(browser, *pos)) { 638 if (!browser->filter || !browser->filter(browser, *pos)) {
635 ui_browser__gotorc(browser, row, 0); 639 ui_browser__gotorc(browser, row, 0);
636 browser->write(browser, pos, row); 640 browser->write(browser, pos, row);
diff --git a/tools/perf/ui/browsers/Build b/tools/perf/ui/browsers/Build
index 8fee56b46502..fdf86f7981ca 100644
--- a/tools/perf/ui/browsers/Build
+++ b/tools/perf/ui/browsers/Build
@@ -3,6 +3,7 @@ perf-y += hists.o
3perf-y += map.o 3perf-y += map.o
4perf-y += scripts.o 4perf-y += scripts.o
5perf-y += header.o 5perf-y += header.o
6perf-y += res_sample.o
6 7
7CFLAGS_annotate.o += -DENABLE_SLFUTURE_CONST 8CFLAGS_annotate.o += -DENABLE_SLFUTURE_CONST
8CFLAGS_hists.o += -DENABLE_SLFUTURE_CONST 9CFLAGS_hists.o += -DENABLE_SLFUTURE_CONST
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 35bdfd8b1e71..98d934a36d86 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -750,7 +750,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
750 continue; 750 continue;
751 case 'r': 751 case 'r':
752 { 752 {
753 script_browse(NULL); 753 script_browse(NULL, NULL);
754 continue; 754 continue;
755 } 755 }
756 case 'k': 756 case 'k':
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index aef800d97ea1..3421ecbdd3f0 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -7,6 +7,7 @@
7#include <string.h> 7#include <string.h>
8#include <linux/rbtree.h> 8#include <linux/rbtree.h>
9#include <sys/ttydefaults.h> 9#include <sys/ttydefaults.h>
10#include <linux/time64.h>
10 11
11#include "../../util/callchain.h" 12#include "../../util/callchain.h"
12#include "../../util/evsel.h" 13#include "../../util/evsel.h"
@@ -30,6 +31,7 @@
30#include "srcline.h" 31#include "srcline.h"
31#include "string2.h" 32#include "string2.h"
32#include "units.h" 33#include "units.h"
34#include "time-utils.h"
33 35
34#include "sane_ctype.h" 36#include "sane_ctype.h"
35 37
@@ -1224,6 +1226,8 @@ void hist_browser__init_hpp(void)
1224 hist_browser__hpp_color_overhead_guest_us; 1226 hist_browser__hpp_color_overhead_guest_us;
1225 perf_hpp__format[PERF_HPP__OVERHEAD_ACC].color = 1227 perf_hpp__format[PERF_HPP__OVERHEAD_ACC].color =
1226 hist_browser__hpp_color_overhead_acc; 1228 hist_browser__hpp_color_overhead_acc;
1229
1230 res_sample_init();
1227} 1231}
1228 1232
1229static int hist_browser__show_entry(struct hist_browser *browser, 1233static int hist_browser__show_entry(struct hist_browser *browser,
@@ -2338,9 +2342,12 @@ close_file_and_continue:
2338} 2342}
2339 2343
2340struct popup_action { 2344struct popup_action {
2345 unsigned long time;
2341 struct thread *thread; 2346 struct thread *thread;
2342 struct map_symbol ms; 2347 struct map_symbol ms;
2343 int socket; 2348 int socket;
2349 struct perf_evsel *evsel;
2350 enum rstype rstype;
2344 2351
2345 int (*fn)(struct hist_browser *browser, struct popup_action *act); 2352 int (*fn)(struct hist_browser *browser, struct popup_action *act);
2346}; 2353};
@@ -2527,46 +2534,137 @@ static int
2527do_run_script(struct hist_browser *browser __maybe_unused, 2534do_run_script(struct hist_browser *browser __maybe_unused,
2528 struct popup_action *act) 2535 struct popup_action *act)
2529{ 2536{
2530 char script_opt[64]; 2537 char *script_opt;
2531 memset(script_opt, 0, sizeof(script_opt)); 2538 int len;
2539 int n = 0;
2532 2540
2541 len = 100;
2542 if (act->thread)
2543 len += strlen(thread__comm_str(act->thread));
2544 else if (act->ms.sym)
2545 len += strlen(act->ms.sym->name);
2546 script_opt = malloc(len);
2547 if (!script_opt)
2548 return -1;
2549
2550 script_opt[0] = 0;
2533 if (act->thread) { 2551 if (act->thread) {
2534 scnprintf(script_opt, sizeof(script_opt), " -c %s ", 2552 n = scnprintf(script_opt, len, " -c %s ",
2535 thread__comm_str(act->thread)); 2553 thread__comm_str(act->thread));
2536 } else if (act->ms.sym) { 2554 } else if (act->ms.sym) {
2537 scnprintf(script_opt, sizeof(script_opt), " -S %s ", 2555 n = scnprintf(script_opt, len, " -S %s ",
2538 act->ms.sym->name); 2556 act->ms.sym->name);
2539 } 2557 }
2540 2558
2541 script_browse(script_opt); 2559 if (act->time) {
2560 char start[32], end[32];
2561 unsigned long starttime = act->time;
2562 unsigned long endtime = act->time + symbol_conf.time_quantum;
2563
2564 if (starttime == endtime) { /* Display 1ms as fallback */
2565 starttime -= 1*NSEC_PER_MSEC;
2566 endtime += 1*NSEC_PER_MSEC;
2567 }
2568 timestamp__scnprintf_usec(starttime, start, sizeof start);
2569 timestamp__scnprintf_usec(endtime, end, sizeof end);
2570 n += snprintf(script_opt + n, len - n, " --time %s,%s", start, end);
2571 }
2572
2573 script_browse(script_opt, act->evsel);
2574 free(script_opt);
2542 return 0; 2575 return 0;
2543} 2576}
2544 2577
2545static int 2578static int
2546add_script_opt(struct hist_browser *browser __maybe_unused, 2579do_res_sample_script(struct hist_browser *browser __maybe_unused,
2580 struct popup_action *act)
2581{
2582 struct hist_entry *he;
2583
2584 he = hist_browser__selected_entry(browser);
2585 res_sample_browse(he->res_samples, he->num_res, act->evsel, act->rstype);
2586 return 0;
2587}
2588
2589static int
2590add_script_opt_2(struct hist_browser *browser __maybe_unused,
2547 struct popup_action *act, char **optstr, 2591 struct popup_action *act, char **optstr,
2548 struct thread *thread, struct symbol *sym) 2592 struct thread *thread, struct symbol *sym,
2593 struct perf_evsel *evsel, const char *tstr)
2549{ 2594{
2595
2550 if (thread) { 2596 if (thread) {
2551 if (asprintf(optstr, "Run scripts for samples of thread [%s]", 2597 if (asprintf(optstr, "Run scripts for samples of thread [%s]%s",
2552 thread__comm_str(thread)) < 0) 2598 thread__comm_str(thread), tstr) < 0)
2553 return 0; 2599 return 0;
2554 } else if (sym) { 2600 } else if (sym) {
2555 if (asprintf(optstr, "Run scripts for samples of symbol [%s]", 2601 if (asprintf(optstr, "Run scripts for samples of symbol [%s]%s",
2556 sym->name) < 0) 2602 sym->name, tstr) < 0)
2557 return 0; 2603 return 0;
2558 } else { 2604 } else {
2559 if (asprintf(optstr, "Run scripts for all samples") < 0) 2605 if (asprintf(optstr, "Run scripts for all samples%s", tstr) < 0)
2560 return 0; 2606 return 0;
2561 } 2607 }
2562 2608
2563 act->thread = thread; 2609 act->thread = thread;
2564 act->ms.sym = sym; 2610 act->ms.sym = sym;
2611 act->evsel = evsel;
2565 act->fn = do_run_script; 2612 act->fn = do_run_script;
2566 return 1; 2613 return 1;
2567} 2614}
2568 2615
2569static int 2616static int
2617add_script_opt(struct hist_browser *browser,
2618 struct popup_action *act, char **optstr,
2619 struct thread *thread, struct symbol *sym,
2620 struct perf_evsel *evsel)
2621{
2622 int n, j;
2623 struct hist_entry *he;
2624
2625 n = add_script_opt_2(browser, act, optstr, thread, sym, evsel, "");
2626
2627 he = hist_browser__selected_entry(browser);
2628 if (sort_order && strstr(sort_order, "time")) {
2629 char tstr[128];
2630
2631 optstr++;
2632 act++;
2633 j = sprintf(tstr, " in ");
2634 j += timestamp__scnprintf_usec(he->time, tstr + j,
2635 sizeof tstr - j);
2636 j += sprintf(tstr + j, "-");
2637 timestamp__scnprintf_usec(he->time + symbol_conf.time_quantum,
2638 tstr + j, sizeof tstr - j);
2639 n += add_script_opt_2(browser, act, optstr, thread, sym,
2640 evsel, tstr);
2641 act->time = he->time;
2642 }
2643 return n;
2644}
2645
2646static int
2647add_res_sample_opt(struct hist_browser *browser __maybe_unused,
2648 struct popup_action *act, char **optstr,
2649 struct res_sample *res_sample,
2650 struct perf_evsel *evsel,
2651 enum rstype type)
2652{
2653 if (!res_sample)
2654 return 0;
2655
2656 if (asprintf(optstr, "Show context for individual samples %s",
2657 type == A_ASM ? "with assembler" :
2658 type == A_SOURCE ? "with source" : "") < 0)
2659 return 0;
2660
2661 act->fn = do_res_sample_script;
2662 act->evsel = evsel;
2663 act->rstype = type;
2664 return 1;
2665}
2666
2667static int
2570do_switch_data(struct hist_browser *browser __maybe_unused, 2668do_switch_data(struct hist_browser *browser __maybe_unused,
2571 struct popup_action *act __maybe_unused) 2669 struct popup_action *act __maybe_unused)
2572{ 2670{
@@ -3031,7 +3129,7 @@ skip_annotation:
3031 nr_options += add_script_opt(browser, 3129 nr_options += add_script_opt(browser,
3032 &actions[nr_options], 3130 &actions[nr_options],
3033 &options[nr_options], 3131 &options[nr_options],
3034 thread, NULL); 3132 thread, NULL, evsel);
3035 } 3133 }
3036 /* 3134 /*
3037 * Note that browser->selection != NULL 3135 * Note that browser->selection != NULL
@@ -3046,11 +3144,24 @@ skip_annotation:
3046 nr_options += add_script_opt(browser, 3144 nr_options += add_script_opt(browser,
3047 &actions[nr_options], 3145 &actions[nr_options],
3048 &options[nr_options], 3146 &options[nr_options],
3049 NULL, browser->selection->sym); 3147 NULL, browser->selection->sym,
3148 evsel);
3050 } 3149 }
3051 } 3150 }
3052 nr_options += add_script_opt(browser, &actions[nr_options], 3151 nr_options += add_script_opt(browser, &actions[nr_options],
3053 &options[nr_options], NULL, NULL); 3152 &options[nr_options], NULL, NULL, evsel);
3153 nr_options += add_res_sample_opt(browser, &actions[nr_options],
3154 &options[nr_options],
3155 hist_browser__selected_entry(browser)->res_samples,
3156 evsel, A_NORMAL);
3157 nr_options += add_res_sample_opt(browser, &actions[nr_options],
3158 &options[nr_options],
3159 hist_browser__selected_entry(browser)->res_samples,
3160 evsel, A_ASM);
3161 nr_options += add_res_sample_opt(browser, &actions[nr_options],
3162 &options[nr_options],
3163 hist_browser__selected_entry(browser)->res_samples,
3164 evsel, A_SOURCE);
3054 nr_options += add_switch_opt(browser, &actions[nr_options], 3165 nr_options += add_switch_opt(browser, &actions[nr_options],
3055 &options[nr_options]); 3166 &options[nr_options]);
3056skip_scripting: 3167skip_scripting:
diff --git a/tools/perf/ui/browsers/res_sample.c b/tools/perf/ui/browsers/res_sample.c
new file mode 100644
index 000000000000..c0dd73176d42
--- /dev/null
+++ b/tools/perf/ui/browsers/res_sample.c
@@ -0,0 +1,91 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Display a menu with individual samples to browse with perf script */
3#include "util.h"
4#include "hist.h"
5#include "evsel.h"
6#include "hists.h"
7#include "sort.h"
8#include "config.h"
9#include "time-utils.h"
10#include <linux/time64.h>
11
12static u64 context_len = 10 * NSEC_PER_MSEC;
13
14static int res_sample_config(const char *var, const char *value, void *data __maybe_unused)
15{
16 if (!strcmp(var, "samples.context"))
17 return perf_config_u64(&context_len, var, value);
18 return 0;
19}
20
21void res_sample_init(void)
22{
23 perf_config(res_sample_config, NULL);
24}
25
26int res_sample_browse(struct res_sample *res_samples, int num_res,
27 struct perf_evsel *evsel, enum rstype rstype)
28{
29 char **names;
30 int i, n;
31 int choice;
32 char *cmd;
33 char pbuf[256], tidbuf[32], cpubuf[32];
34 const char *perf = perf_exe(pbuf, sizeof pbuf);
35 char trange[128], tsample[64];
36 struct res_sample *r;
37 char extra_format[256];
38
39 names = calloc(num_res, sizeof(char *));
40 if (!names)
41 return -1;
42 for (i = 0; i < num_res; i++) {
43 char tbuf[64];
44
45 timestamp__scnprintf_nsec(res_samples[i].time, tbuf, sizeof tbuf);
46 if (asprintf(&names[i], "%s: CPU %d tid %d", tbuf,
47 res_samples[i].cpu, res_samples[i].tid) < 0) {
48 while (--i >= 0)
49 free(names[i]);
50 free(names);
51 return -1;
52 }
53 }
54 choice = ui__popup_menu(num_res, names);
55 for (i = 0; i < num_res; i++)
56 free(names[i]);
57 free(names);
58
59 if (choice < 0 || choice >= num_res)
60 return -1;
61 r = &res_samples[choice];
62
63 n = timestamp__scnprintf_nsec(r->time - context_len, trange, sizeof trange);
64 trange[n++] = ',';
65 timestamp__scnprintf_nsec(r->time + context_len, trange + n, sizeof trange - n);
66
67 timestamp__scnprintf_nsec(r->time, tsample, sizeof tsample);
68
69 attr_to_script(extra_format, &evsel->attr);
70
71 if (asprintf(&cmd, "%s script %s%s --time %s %s%s %s%s --ns %s %s %s %s %s | less +/%s",
72 perf,
73 input_name ? "-i " : "",
74 input_name ? input_name : "",
75 trange,
76 r->cpu >= 0 ? "--cpu " : "",
77 r->cpu >= 0 ? (sprintf(cpubuf, "%d", r->cpu), cpubuf) : "",
78 r->tid ? "--tid " : "",
79 r->tid ? (sprintf(tidbuf, "%d", r->tid), tidbuf) : "",
80 extra_format,
81 rstype == A_ASM ? "-F +insn --xed" :
82 rstype == A_SOURCE ? "-F +srcline,+srccode" : "",
83 symbol_conf.inline_name ? "--inline" : "",
84 "--show-lost-events ",
85 r->tid ? "--show-switch-events --show-task-events " : "",
86 tsample) < 0)
87 return -1;
88 run_script(cmd);
89 free(cmd);
90 return 0;
91}
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index 90a32ac69e76..27cf3ab88d13 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -1,34 +1,12 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include <elf.h>
3#include <inttypes.h>
4#include <sys/ttydefaults.h>
5#include <string.h>
6#include "../../util/sort.h" 2#include "../../util/sort.h"
7#include "../../util/util.h" 3#include "../../util/util.h"
8#include "../../util/hist.h" 4#include "../../util/hist.h"
9#include "../../util/debug.h" 5#include "../../util/debug.h"
10#include "../../util/symbol.h" 6#include "../../util/symbol.h"
11#include "../browser.h" 7#include "../browser.h"
12#include "../helpline.h"
13#include "../libslang.h" 8#include "../libslang.h"
14 9#include "config.h"
15/* 2048 lines should be enough for a script output */
16#define MAX_LINES 2048
17
18/* 160 bytes for one output line */
19#define AVERAGE_LINE_LEN 160
20
21struct script_line {
22 struct list_head node;
23 char line[AVERAGE_LINE_LEN];
24};
25
26struct perf_script_browser {
27 struct ui_browser b;
28 struct list_head entries;
29 const char *script_name;
30 int nr_lines;
31};
32 10
33#define SCRIPT_NAMELEN 128 11#define SCRIPT_NAMELEN 128
34#define SCRIPT_MAX_NO 64 12#define SCRIPT_MAX_NO 64
@@ -40,149 +18,169 @@ struct perf_script_browser {
40 */ 18 */
41#define SCRIPT_FULLPATH_LEN 256 19#define SCRIPT_FULLPATH_LEN 256
42 20
21struct script_config {
22 const char **names;
23 char **paths;
24 int index;
25 const char *perf;
26 char extra_format[256];
27};
28
29void attr_to_script(char *extra_format, struct perf_event_attr *attr)
30{
31 extra_format[0] = 0;
32 if (attr->read_format & PERF_FORMAT_GROUP)
33 strcat(extra_format, " -F +metric");
34 if (attr->sample_type & PERF_SAMPLE_BRANCH_STACK)
35 strcat(extra_format, " -F +brstackinsn --xed");
36 if (attr->sample_type & PERF_SAMPLE_REGS_INTR)
37 strcat(extra_format, " -F +iregs");
38 if (attr->sample_type & PERF_SAMPLE_REGS_USER)
39 strcat(extra_format, " -F +uregs");
40 if (attr->sample_type & PERF_SAMPLE_PHYS_ADDR)
41 strcat(extra_format, " -F +phys_addr");
42}
43
44static int add_script_option(const char *name, const char *opt,
45 struct script_config *c)
46{
47 c->names[c->index] = name;
48 if (asprintf(&c->paths[c->index],
49 "%s script %s -F +metric %s %s",
50 c->perf, opt, symbol_conf.inline_name ? " --inline" : "",
51 c->extra_format) < 0)
52 return -1;
53 c->index++;
54 return 0;
55}
56
57static int scripts_config(const char *var, const char *value, void *data)
58{
59 struct script_config *c = data;
60
61 if (!strstarts(var, "scripts."))
62 return -1;
63 if (c->index >= SCRIPT_MAX_NO)
64 return -1;
65 c->names[c->index] = strdup(var + 7);
66 if (!c->names[c->index])
67 return -1;
68 if (asprintf(&c->paths[c->index], "%s %s", value,
69 c->extra_format) < 0)
70 return -1;
71 c->index++;
72 return 0;
73}
74
43/* 75/*
44 * When success, will copy the full path of the selected script 76 * When success, will copy the full path of the selected script
45 * into the buffer pointed by script_name, and return 0. 77 * into the buffer pointed by script_name, and return 0.
46 * Return -1 on failure. 78 * Return -1 on failure.
47 */ 79 */
48static int list_scripts(char *script_name) 80static int list_scripts(char *script_name, bool *custom,
81 struct perf_evsel *evsel)
49{ 82{
50 char *buf, *names[SCRIPT_MAX_NO], *paths[SCRIPT_MAX_NO]; 83 char *buf, *paths[SCRIPT_MAX_NO], *names[SCRIPT_MAX_NO];
51 int i, num, choice, ret = -1; 84 int i, num, choice;
85 int ret = 0;
86 int max_std, custom_perf;
87 char pbuf[256];
88 const char *perf = perf_exe(pbuf, sizeof pbuf);
89 struct script_config scriptc = {
90 .names = (const char **)names,
91 .paths = paths,
92 .perf = perf
93 };
94
95 script_name[0] = 0;
52 96
53 /* Preset the script name to SCRIPT_NAMELEN */ 97 /* Preset the script name to SCRIPT_NAMELEN */
54 buf = malloc(SCRIPT_MAX_NO * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN)); 98 buf = malloc(SCRIPT_MAX_NO * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN));
55 if (!buf) 99 if (!buf)
56 return ret; 100 return -1;
57 101
58 for (i = 0; i < SCRIPT_MAX_NO; i++) { 102 if (evsel)
59 names[i] = buf + i * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN); 103 attr_to_script(scriptc.extra_format, &evsel->attr);
104 add_script_option("Show individual samples", "", &scriptc);
105 add_script_option("Show individual samples with assembler", "-F +insn --xed",
106 &scriptc);
107 add_script_option("Show individual samples with source", "-F +srcline,+srccode",
108 &scriptc);
109 perf_config(scripts_config, &scriptc);
110 custom_perf = scriptc.index;
111 add_script_option("Show samples with custom perf script arguments", "", &scriptc);
112 i = scriptc.index;
113 max_std = i;
114
115 for (; i < SCRIPT_MAX_NO; i++) {
116 names[i] = buf + (i - max_std) * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN);
60 paths[i] = names[i] + SCRIPT_NAMELEN; 117 paths[i] = names[i] + SCRIPT_NAMELEN;
61 } 118 }
62 119
63 num = find_scripts(names, paths); 120 num = find_scripts(names + max_std, paths + max_std, SCRIPT_MAX_NO - max_std,
64 if (num > 0) { 121 SCRIPT_FULLPATH_LEN);
65 choice = ui__popup_menu(num, names); 122 if (num < 0)
66 if (choice < num && choice >= 0) { 123 num = 0;
67 strcpy(script_name, paths[choice]); 124 choice = ui__popup_menu(num + max_std, (char * const *)names);
68 ret = 0; 125 if (choice < 0) {
69 } 126 ret = -1;
127 goto out;
70 } 128 }
129 if (choice == custom_perf) {
130 char script_args[50];
131 int key = ui_browser__input_window("perf script command",
132 "Enter perf script command line (without perf script prefix)",
133 script_args, "", 0);
134 if (key != K_ENTER)
135 return -1;
136 sprintf(script_name, "%s script %s", perf, script_args);
137 } else if (choice < num + max_std) {
138 strcpy(script_name, paths[choice]);
139 }
140 *custom = choice >= max_std;
71 141
142out:
72 free(buf); 143 free(buf);
144 for (i = 0; i < max_std; i++)
145 free(paths[i]);
73 return ret; 146 return ret;
74} 147}
75 148
76static void script_browser__write(struct ui_browser *browser, 149void run_script(char *cmd)
77 void *entry, int row)
78{ 150{
79 struct script_line *sline = list_entry(entry, struct script_line, node); 151 pr_debug("Running %s\n", cmd);
80 bool current_entry = ui_browser__is_current_entry(browser, row); 152 SLang_reset_tty();
81 153 if (system(cmd) < 0)
82 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : 154 pr_warning("Cannot run %s\n", cmd);
83 HE_COLORSET_NORMAL); 155 /*
84 156 * SLang doesn't seem to reset the whole terminal, so be more
85 ui_browser__write_nstring(browser, sline->line, browser->width); 157 * forceful to get back to the original state.
158 */
159 printf("\033[c\033[H\033[J");
160 fflush(stdout);
161 SLang_init_tty(0, 0, 0);
162 SLsmg_refresh();
86} 163}
87 164
88static int script_browser__run(struct perf_script_browser *browser) 165int script_browse(const char *script_opt, struct perf_evsel *evsel)
89{ 166{
90 int key; 167 char *cmd, script_name[SCRIPT_FULLPATH_LEN];
168 bool custom = false;
91 169
92 if (ui_browser__show(&browser->b, browser->script_name, 170 memset(script_name, 0, SCRIPT_FULLPATH_LEN);
93 "Press ESC to exit") < 0) 171 if (list_scripts(script_name, &custom, evsel))
94 return -1; 172 return -1;
95 173
96 while (1) { 174 if (asprintf(&cmd, "%s%s %s %s%s 2>&1 | less",
97 key = ui_browser__run(&browser->b, 0); 175 custom ? "perf script -s " : "",
98 176 script_name,
99 /* We can add some special key handling here if needed */ 177 script_opt ? script_opt : "",
100 break; 178 input_name ? "-i " : "",
101 } 179 input_name ? input_name : "") < 0)
102
103 ui_browser__hide(&browser->b);
104 return key;
105}
106
107
108int script_browse(const char *script_opt)
109{
110 char cmd[SCRIPT_FULLPATH_LEN*2], script_name[SCRIPT_FULLPATH_LEN];
111 char *line = NULL;
112 size_t len = 0;
113 ssize_t retlen;
114 int ret = -1, nr_entries = 0;
115 FILE *fp;
116 void *buf;
117 struct script_line *sline;
118
119 struct perf_script_browser script = {
120 .b = {
121 .refresh = ui_browser__list_head_refresh,
122 .seek = ui_browser__list_head_seek,
123 .write = script_browser__write,
124 },
125 .script_name = script_name,
126 };
127
128 INIT_LIST_HEAD(&script.entries);
129
130 /* Save each line of the output in one struct script_line object. */
131 buf = zalloc((sizeof(*sline)) * MAX_LINES);
132 if (!buf)
133 return -1; 180 return -1;
134 sline = buf;
135
136 memset(script_name, 0, SCRIPT_FULLPATH_LEN);
137 if (list_scripts(script_name))
138 goto exit;
139
140 sprintf(cmd, "perf script -s %s ", script_name);
141 181
142 if (script_opt) 182 run_script(cmd);
143 strcat(cmd, script_opt); 183 free(cmd);
144 184
145 if (input_name) { 185 return 0;
146 strcat(cmd, " -i ");
147 strcat(cmd, input_name);
148 }
149
150 strcat(cmd, " 2>&1");
151
152 fp = popen(cmd, "r");
153 if (!fp)
154 goto exit;
155
156 while ((retlen = getline(&line, &len, fp)) != -1) {
157 strncpy(sline->line, line, AVERAGE_LINE_LEN);
158
159 /* If one output line is very large, just cut it short */
160 if (retlen >= AVERAGE_LINE_LEN) {
161 sline->line[AVERAGE_LINE_LEN - 1] = '\0';
162 sline->line[AVERAGE_LINE_LEN - 2] = '\n';
163 }
164 list_add_tail(&sline->node, &script.entries);
165
166 if (script.b.width < retlen)
167 script.b.width = retlen;
168
169 if (nr_entries++ >= MAX_LINES - 1)
170 break;
171 sline++;
172 }
173
174 if (script.b.width > AVERAGE_LINE_LEN)
175 script.b.width = AVERAGE_LINE_LEN;
176
177 free(line);
178 pclose(fp);
179
180 script.nr_lines = nr_entries;
181 script.b.nr_entries = nr_entries;
182 script.b.entries = &script.entries;
183
184 ret = script_browser__run(&script);
185exit:
186 free(buf);
187 return ret;
188} 186}
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/archinsn.h b/tools/perf/util/archinsn.h
new file mode 100644
index 000000000000..448cbb6b8d7e
--- /dev/null
+++ b/tools/perf/util/archinsn.h
@@ -0,0 +1,12 @@
1#ifndef INSN_H
2#define INSN_H 1
3
4struct perf_sample;
5struct machine;
6struct thread;
7
8void arch_fetch_insn(struct perf_sample *sample,
9 struct thread *thread,
10 struct machine *machine);
11
12#endif
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/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
index ba4c623cd8de..39fe21e1cf93 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -387,6 +387,7 @@ cs_etm_decoder__buffer_range(struct cs_etm_decoder *decoder,
387 break; 387 break;
388 case OCSD_INSTR_ISB: 388 case OCSD_INSTR_ISB:
389 case OCSD_INSTR_DSB_DMB: 389 case OCSD_INSTR_DSB_DMB:
390 case OCSD_INSTR_WFI_WFE:
390 case OCSD_INSTR_OTHER: 391 case OCSD_INSTR_OTHER:
391 default: 392 default:
392 packet->last_instr_taken_branch = false; 393 packet->last_instr_taken_branch = false;
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index e098e189f93e..6a64f713710d 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -14,6 +14,7 @@
14#include "data.h" 14#include "data.h"
15#include "util.h" 15#include "util.h"
16#include "debug.h" 16#include "debug.h"
17#include "header.h"
17 18
18static void close_dir(struct perf_data_file *files, int nr) 19static void close_dir(struct perf_data_file *files, int nr)
19{ 20{
@@ -34,12 +35,16 @@ int perf_data__create_dir(struct perf_data *data, int nr)
34 struct perf_data_file *files = NULL; 35 struct perf_data_file *files = NULL;
35 int i, ret = -1; 36 int i, ret = -1;
36 37
38 if (WARN_ON(!data->is_dir))
39 return -EINVAL;
40
37 files = zalloc(nr * sizeof(*files)); 41 files = zalloc(nr * sizeof(*files));
38 if (!files) 42 if (!files)
39 return -ENOMEM; 43 return -ENOMEM;
40 44
41 data->dir.files = files; 45 data->dir.version = PERF_DIR_VERSION;
42 data->dir.nr = nr; 46 data->dir.files = files;
47 data->dir.nr = nr;
43 48
44 for (i = 0; i < nr; i++) { 49 for (i = 0; i < nr; i++) {
45 struct perf_data_file *file = &files[i]; 50 struct perf_data_file *file = &files[i];
@@ -69,6 +74,13 @@ int perf_data__open_dir(struct perf_data *data)
69 DIR *dir; 74 DIR *dir;
70 int nr = 0; 75 int nr = 0;
71 76
77 if (WARN_ON(!data->is_dir))
78 return -EINVAL;
79
80 /* The version is provided by DIR_FORMAT feature. */
81 if (WARN_ON(data->dir.version != PERF_DIR_VERSION))
82 return -1;
83
72 dir = opendir(data->path); 84 dir = opendir(data->path);
73 if (!dir) 85 if (!dir)
74 return -EINVAL; 86 return -EINVAL;
@@ -118,6 +130,26 @@ out_err:
118 return ret; 130 return ret;
119} 131}
120 132
133int perf_data__update_dir(struct perf_data *data)
134{
135 int i;
136
137 if (WARN_ON(!data->is_dir))
138 return -EINVAL;
139
140 for (i = 0; i < data->dir.nr; i++) {
141 struct perf_data_file *file = &data->dir.files[i];
142 struct stat st;
143
144 if (fstat(file->fd, &st))
145 return -1;
146
147 file->size = st.st_size;
148 }
149
150 return 0;
151}
152
121static bool check_pipe(struct perf_data *data) 153static bool check_pipe(struct perf_data *data)
122{ 154{
123 struct stat st; 155 struct stat st;
@@ -173,6 +205,16 @@ static int check_backup(struct perf_data *data)
173 return 0; 205 return 0;
174} 206}
175 207
208static bool is_dir(struct perf_data *data)
209{
210 struct stat st;
211
212 if (stat(data->path, &st))
213 return false;
214
215 return (st.st_mode & S_IFMT) == S_IFDIR;
216}
217
176static int open_file_read(struct perf_data *data) 218static int open_file_read(struct perf_data *data)
177{ 219{
178 struct stat st; 220 struct stat st;
@@ -254,6 +296,30 @@ static int open_file_dup(struct perf_data *data)
254 return open_file(data); 296 return open_file(data);
255} 297}
256 298
299static int open_dir(struct perf_data *data)
300{
301 int ret;
302
303 /*
304 * So far we open only the header, so we can read the data version and
305 * layout.
306 */
307 if (asprintf(&data->file.path, "%s/header", data->path) < 0)
308 return -1;
309
310 if (perf_data__is_write(data) &&
311 mkdir(data->path, S_IRWXU) < 0)
312 return -1;
313
314 ret = open_file(data);
315
316 /* Cleanup whatever we managed to create so far. */
317 if (ret && perf_data__is_write(data))
318 rm_rf_perf_data(data->path);
319
320 return ret;
321}
322
257int perf_data__open(struct perf_data *data) 323int perf_data__open(struct perf_data *data)
258{ 324{
259 if (check_pipe(data)) 325 if (check_pipe(data))
@@ -265,11 +331,18 @@ int perf_data__open(struct perf_data *data)
265 if (check_backup(data)) 331 if (check_backup(data))
266 return -1; 332 return -1;
267 333
268 return open_file_dup(data); 334 if (perf_data__is_read(data))
335 data->is_dir = is_dir(data);
336
337 return perf_data__is_dir(data) ?
338 open_dir(data) : open_file_dup(data);
269} 339}
270 340
271void perf_data__close(struct perf_data *data) 341void perf_data__close(struct perf_data *data)
272{ 342{
343 if (perf_data__is_dir(data))
344 perf_data__close_dir(data);
345
273 zfree(&data->file.path); 346 zfree(&data->file.path);
274 close(data->file.fd); 347 close(data->file.fd);
275} 348}
@@ -288,9 +361,9 @@ ssize_t perf_data__write(struct perf_data *data,
288 361
289int perf_data__switch(struct perf_data *data, 362int perf_data__switch(struct perf_data *data,
290 const char *postfix, 363 const char *postfix,
291 size_t pos, bool at_exit) 364 size_t pos, bool at_exit,
365 char **new_filepath)
292{ 366{
293 char *new_filepath;
294 int ret; 367 int ret;
295 368
296 if (check_pipe(data)) 369 if (check_pipe(data))
@@ -298,15 +371,15 @@ int perf_data__switch(struct perf_data *data,
298 if (perf_data__is_read(data)) 371 if (perf_data__is_read(data))
299 return -EINVAL; 372 return -EINVAL;
300 373
301 if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0) 374 if (asprintf(new_filepath, "%s.%s", data->path, postfix) < 0)
302 return -ENOMEM; 375 return -ENOMEM;
303 376
304 /* 377 /*
305 * Only fire a warning, don't return error, continue fill 378 * Only fire a warning, don't return error, continue fill
306 * original file. 379 * original file.
307 */ 380 */
308 if (rename(data->path, new_filepath)) 381 if (rename(data->path, *new_filepath))
309 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);
310 383
311 if (!at_exit) { 384 if (!at_exit) {
312 close(data->file.fd); 385 close(data->file.fd);
@@ -323,6 +396,22 @@ int perf_data__switch(struct perf_data *data,
323 } 396 }
324 ret = data->file.fd; 397 ret = data->file.fd;
325out: 398out:
326 free(new_filepath);
327 return ret; 399 return ret;
328} 400}
401
402unsigned long perf_data__size(struct perf_data *data)
403{
404 u64 size = data->file.size;
405 int i;
406
407 if (!data->is_dir)
408 return size;
409
410 for (i = 0; i < data->dir.nr; i++) {
411 struct perf_data_file *file = &data->dir.files[i];
412
413 size += file->size;
414 }
415
416 return size;
417}
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 14b47be2bd69..259868a39019 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -19,10 +19,12 @@ struct perf_data {
19 const char *path; 19 const char *path;
20 struct perf_data_file file; 20 struct perf_data_file file;
21 bool is_pipe; 21 bool is_pipe;
22 bool is_dir;
22 bool force; 23 bool force;
23 enum perf_data_mode mode; 24 enum perf_data_mode mode;
24 25
25 struct { 26 struct {
27 u64 version;
26 struct perf_data_file *files; 28 struct perf_data_file *files;
27 int nr; 29 int nr;
28 } dir; 30 } dir;
@@ -43,14 +45,14 @@ static inline int perf_data__is_pipe(struct perf_data *data)
43 return data->is_pipe; 45 return data->is_pipe;
44} 46}
45 47
46static inline int perf_data__fd(struct perf_data *data) 48static inline bool perf_data__is_dir(struct perf_data *data)
47{ 49{
48 return data->file.fd; 50 return data->is_dir;
49} 51}
50 52
51static inline unsigned long perf_data__size(struct perf_data *data) 53static inline int perf_data__fd(struct perf_data *data)
52{ 54{
53 return data->file.size; 55 return data->file.fd;
54} 56}
55 57
56int perf_data__open(struct perf_data *data); 58int perf_data__open(struct perf_data *data);
@@ -68,9 +70,11 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
68 */ 70 */
69int perf_data__switch(struct perf_data *data, 71int perf_data__switch(struct perf_data *data,
70 const char *postfix, 72 const char *postfix,
71 size_t pos, bool at_exit); 73 size_t pos, bool at_exit, char **new_filepath);
72 74
73int perf_data__create_dir(struct perf_data *data, int nr); 75int perf_data__create_dir(struct perf_data *data, int nr);
74int perf_data__open_dir(struct perf_data *data); 76int perf_data__open_dir(struct perf_data *data);
75void perf_data__close_dir(struct perf_data *data); 77void perf_data__close_dir(struct perf_data *data);
78int perf_data__update_dir(struct perf_data *data);
79unsigned long perf_data__size(struct perf_data *data);
76#endif /* __PERF_DATA_H */ 80#endif /* __PERF_DATA_H */
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..6689378ee577 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
@@ -230,35 +231,6 @@ void perf_evlist__set_leader(struct perf_evlist *evlist)
230 } 231 }
231} 232}
232 233
233void perf_event_attr__set_max_precise_ip(struct perf_event_attr *pattr)
234{
235 struct perf_event_attr attr = {
236 .type = PERF_TYPE_HARDWARE,
237 .config = PERF_COUNT_HW_CPU_CYCLES,
238 .exclude_kernel = 1,
239 .precise_ip = 3,
240 };
241
242 event_attr_init(&attr);
243
244 /*
245 * Unnamed union member, not supported as struct member named
246 * initializer in older compilers such as gcc 4.4.7
247 */
248 attr.sample_period = 1;
249
250 while (attr.precise_ip != 0) {
251 int fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
252 if (fd != -1) {
253 close(fd);
254 break;
255 }
256 --attr.precise_ip;
257 }
258
259 pattr->precise_ip = attr.precise_ip;
260}
261
262int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise) 234int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise)
263{ 235{
264 struct perf_evsel *evsel = perf_evsel__new_cycles(precise); 236 struct perf_evsel *evsel = perf_evsel__new_cycles(precise);
@@ -1856,3 +1828,121 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list,
1856 } 1828 }
1857 return leader; 1829 return leader;
1858} 1830}
1831
1832int perf_evlist__add_sb_event(struct perf_evlist **evlist,
1833 struct perf_event_attr *attr,
1834 perf_evsel__sb_cb_t cb,
1835 void *data)
1836{
1837 struct perf_evsel *evsel;
1838 bool new_evlist = (*evlist) == NULL;
1839
1840 if (*evlist == NULL)
1841 *evlist = perf_evlist__new();
1842 if (*evlist == NULL)
1843 return -1;
1844
1845 if (!attr->sample_id_all) {
1846 pr_warning("enabling sample_id_all for all side band events\n");
1847 attr->sample_id_all = 1;
1848 }
1849
1850 evsel = perf_evsel__new_idx(attr, (*evlist)->nr_entries);
1851 if (!evsel)
1852 goto out_err;
1853
1854 evsel->side_band.cb = cb;
1855 evsel->side_band.data = data;
1856 perf_evlist__add(*evlist, evsel);
1857 return 0;
1858
1859out_err:
1860 if (new_evlist) {
1861 perf_evlist__delete(*evlist);
1862 *evlist = NULL;
1863 }
1864 return -1;
1865}
1866
1867static void *perf_evlist__poll_thread(void *arg)
1868{
1869 struct perf_evlist *evlist = arg;
1870 bool draining = false;
1871 int i;
1872
1873 while (draining || !(evlist->thread.done)) {
1874 if (draining)
1875 draining = false;
1876 else if (evlist->thread.done)
1877 draining = true;
1878
1879 if (!draining)
1880 perf_evlist__poll(evlist, 1000);
1881
1882 for (i = 0; i < evlist->nr_mmaps; i++) {
1883 struct perf_mmap *map = &evlist->mmap[i];
1884 union perf_event *event;
1885
1886 if (perf_mmap__read_init(map))
1887 continue;
1888 while ((event = perf_mmap__read_event(map)) != NULL) {
1889 struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);
1890
1891 if (evsel && evsel->side_band.cb)
1892 evsel->side_band.cb(event, evsel->side_band.data);
1893 else
1894 pr_warning("cannot locate proper evsel for the side band event\n");
1895
1896 perf_mmap__consume(map);
1897 }
1898 perf_mmap__read_done(map);
1899 }
1900 }
1901 return NULL;
1902}
1903
1904int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
1905 struct target *target)
1906{
1907 struct perf_evsel *counter;
1908
1909 if (!evlist)
1910 return 0;
1911
1912 if (perf_evlist__create_maps(evlist, target))
1913 goto out_delete_evlist;
1914
1915 evlist__for_each_entry(evlist, counter) {
1916 if (perf_evsel__open(counter, evlist->cpus,
1917 evlist->threads) < 0)
1918 goto out_delete_evlist;
1919 }
1920
1921 if (perf_evlist__mmap(evlist, UINT_MAX))
1922 goto out_delete_evlist;
1923
1924 evlist__for_each_entry(evlist, counter) {
1925 if (perf_evsel__enable(counter))
1926 goto out_delete_evlist;
1927 }
1928
1929 evlist->thread.done = 0;
1930 if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist))
1931 goto out_delete_evlist;
1932
1933 return 0;
1934
1935out_delete_evlist:
1936 perf_evlist__delete(evlist);
1937 evlist = NULL;
1938 return -1;
1939}
1940
1941void perf_evlist__stop_sb_thread(struct perf_evlist *evlist)
1942{
1943 if (!evlist)
1944 return;
1945 evlist->thread.done = 1;
1946 pthread_join(evlist->thread.th, NULL);
1947 perf_evlist__delete(evlist);
1948}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 744906dd4887..6a94785b9100 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
@@ -303,8 +315,6 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
303void perf_evlist__set_tracking_event(struct perf_evlist *evlist, 315void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
304 struct perf_evsel *tracking_evsel); 316 struct perf_evsel *tracking_evsel);
305 317
306void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr);
307
308struct perf_evsel * 318struct perf_evsel *
309perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str); 319perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str);
310 320
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3bbf73e979c0..66d066f18b5b 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -295,7 +295,6 @@ struct perf_evsel *perf_evsel__new_cycles(bool precise)
295 if (!precise) 295 if (!precise)
296 goto new_event; 296 goto new_event;
297 297
298 perf_event_attr__set_max_precise_ip(&attr);
299 /* 298 /*
300 * Now let the usual logic to set up the perf_event_attr defaults 299 * Now let the usual logic to set up the perf_event_attr defaults
301 * to kick in when we return and before perf_evsel__open() is called. 300 * to kick in when we return and before perf_evsel__open() is called.
@@ -305,6 +304,8 @@ new_event:
305 if (evsel == NULL) 304 if (evsel == NULL)
306 goto out; 305 goto out;
307 306
307 evsel->precise_max = true;
308
308 /* use asprintf() because free(evsel) assumes name is allocated */ 309 /* use asprintf() because free(evsel) assumes name is allocated */
309 if (asprintf(&evsel->name, "cycles%s%s%.*s", 310 if (asprintf(&evsel->name, "cycles%s%s%.*s",
310 (attr.precise_ip || attr.exclude_kernel) ? ":" : "", 311 (attr.precise_ip || attr.exclude_kernel) ? ":" : "",
@@ -1036,7 +1037,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
1036 attr->mmap2 = track && !perf_missing_features.mmap2; 1037 attr->mmap2 = track && !perf_missing_features.mmap2;
1037 attr->comm = track; 1038 attr->comm = track;
1038 attr->ksymbol = track && !perf_missing_features.ksymbol; 1039 attr->ksymbol = track && !perf_missing_features.ksymbol;
1039 attr->bpf_event = track && opts->bpf_event && 1040 attr->bpf_event = track && !opts->no_bpf_event &&
1040 !perf_missing_features.bpf_event; 1041 !perf_missing_features.bpf_event;
1041 1042
1042 if (opts->record_namespaces) 1043 if (opts->record_namespaces)
@@ -1083,7 +1084,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
1083 } 1084 }
1084 1085
1085 if (evsel->precise_max) 1086 if (evsel->precise_max)
1086 perf_event_attr__set_max_precise_ip(attr); 1087 attr->precise_ip = 3;
1087 1088
1088 if (opts->all_user) { 1089 if (opts->all_user) {
1089 attr->exclude_kernel = 1; 1090 attr->exclude_kernel = 1;
@@ -1292,6 +1293,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
1292{ 1293{
1293 assert(list_empty(&evsel->node)); 1294 assert(list_empty(&evsel->node));
1294 assert(evsel->evlist == NULL); 1295 assert(evsel->evlist == NULL);
1296 perf_evsel__free_counts(evsel);
1295 perf_evsel__free_fd(evsel); 1297 perf_evsel__free_fd(evsel);
1296 perf_evsel__free_id(evsel); 1298 perf_evsel__free_id(evsel);
1297 perf_evsel__free_config_terms(evsel); 1299 perf_evsel__free_config_terms(evsel);
@@ -1342,10 +1344,9 @@ void perf_counts_values__scale(struct perf_counts_values *count,
1342 count->val = 0; 1344 count->val = 0;
1343 } else if (count->run < count->ena) { 1345 } else if (count->run < count->ena) {
1344 scaled = 1; 1346 scaled = 1;
1345 count->val = (u64)((double) count->val * count->ena / count->run + 0.5); 1347 count->val = (u64)((double) count->val * count->ena / count->run);
1346 } 1348 }
1347 } else 1349 }
1348 count->ena = count->run = 0;
1349 1350
1350 if (pscaled) 1351 if (pscaled)
1351 *pscaled = scaled; 1352 *pscaled = scaled;
@@ -1749,6 +1750,59 @@ static bool ignore_missing_thread(struct perf_evsel *evsel,
1749 return true; 1750 return true;
1750} 1751}
1751 1752
1753static void display_attr(struct perf_event_attr *attr)
1754{
1755 if (verbose >= 2) {
1756 fprintf(stderr, "%.60s\n", graph_dotted_line);
1757 fprintf(stderr, "perf_event_attr:\n");
1758 perf_event_attr__fprintf(stderr, attr, __open_attr__fprintf, NULL);
1759 fprintf(stderr, "%.60s\n", graph_dotted_line);
1760 }
1761}
1762
1763static int perf_event_open(struct perf_evsel *evsel,
1764 pid_t pid, int cpu, int group_fd,
1765 unsigned long flags)
1766{
1767 int precise_ip = evsel->attr.precise_ip;
1768 int fd;
1769
1770 while (1) {
1771 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
1772 pid, cpu, group_fd, flags);
1773
1774 fd = sys_perf_event_open(&evsel->attr, pid, cpu, group_fd, flags);
1775 if (fd >= 0)
1776 break;
1777
1778 /*
1779 * Do quick precise_ip fallback if:
1780 * - there is precise_ip set in perf_event_attr
1781 * - maximum precise is requested
1782 * - sys_perf_event_open failed with ENOTSUP error,
1783 * which is associated with wrong precise_ip
1784 */
1785 if (!precise_ip || !evsel->precise_max || (errno != ENOTSUP))
1786 break;
1787
1788 /*
1789 * We tried all the precise_ip values, and it's
1790 * still failing, so leave it to standard fallback.
1791 */
1792 if (!evsel->attr.precise_ip) {
1793 evsel->attr.precise_ip = precise_ip;
1794 break;
1795 }
1796
1797 pr_debug2("\nsys_perf_event_open failed, error %d\n", -ENOTSUP);
1798 evsel->attr.precise_ip--;
1799 pr_debug2("decreasing precise_ip by one (%d)\n", evsel->attr.precise_ip);
1800 display_attr(&evsel->attr);
1801 }
1802
1803 return fd;
1804}
1805
1752int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1806int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1753 struct thread_map *threads) 1807 struct thread_map *threads)
1754{ 1808{
@@ -1824,12 +1878,7 @@ retry_sample_id:
1824 if (perf_missing_features.sample_id_all) 1878 if (perf_missing_features.sample_id_all)
1825 evsel->attr.sample_id_all = 0; 1879 evsel->attr.sample_id_all = 0;
1826 1880
1827 if (verbose >= 2) { 1881 display_attr(&evsel->attr);
1828 fprintf(stderr, "%.60s\n", graph_dotted_line);
1829 fprintf(stderr, "perf_event_attr:\n");
1830 perf_event_attr__fprintf(stderr, &evsel->attr, __open_attr__fprintf, NULL);
1831 fprintf(stderr, "%.60s\n", graph_dotted_line);
1832 }
1833 1882
1834 for (cpu = 0; cpu < cpus->nr; cpu++) { 1883 for (cpu = 0; cpu < cpus->nr; cpu++) {
1835 1884
@@ -1841,13 +1890,10 @@ retry_sample_id:
1841 1890
1842 group_fd = get_group_fd(evsel, cpu, thread); 1891 group_fd = get_group_fd(evsel, cpu, thread);
1843retry_open: 1892retry_open:
1844 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
1845 pid, cpus->map[cpu], group_fd, flags);
1846
1847 test_attr__ready(); 1893 test_attr__ready();
1848 1894
1849 fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu], 1895 fd = perf_event_open(evsel, pid, cpus->map[cpu],
1850 group_fd, flags); 1896 group_fd, flags);
1851 1897
1852 FD(evsel, cpu, thread) = fd; 1898 FD(evsel, cpu, thread) = fd;
1853 1899
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 01b324c275b9..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
@@ -861,6 +863,104 @@ static int write_clockid(struct feat_fd *ff,
861 sizeof(ff->ph->env.clockid_res_ns)); 863 sizeof(ff->ph->env.clockid_res_ns));
862} 864}
863 865
866static int write_dir_format(struct feat_fd *ff,
867 struct perf_evlist *evlist __maybe_unused)
868{
869 struct perf_session *session;
870 struct perf_data *data;
871
872 session = container_of(ff->ph, struct perf_session, header);
873 data = session->data;
874
875 if (WARN_ON(!perf_data__is_dir(data)))
876 return -1;
877
878 return do_write(ff, &data->dir.version, sizeof(data->dir.version));
879}
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
864static int cpu_cache_level__sort(const void *a, const void *b) 964static int cpu_cache_level__sort(const void *a, const void *b)
865{ 965{
866 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a; 966 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1341,6 +1441,63 @@ static void print_clockid(struct feat_fd *ff, FILE *fp)
1341 ff->ph->env.clockid_res_ns * 1000); 1441 ff->ph->env.clockid_res_ns * 1000);
1342} 1442}
1343 1443
1444static void print_dir_format(struct feat_fd *ff, FILE *fp)
1445{
1446 struct perf_session *session;
1447 struct perf_data *data;
1448
1449 session = container_of(ff->ph, struct perf_session, header);
1450 data = session->data;
1451
1452 fprintf(fp, "# directory data version : %"PRIu64"\n", data->dir.version);
1453}
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
1344static void free_event_desc(struct perf_evsel *events) 1501static void free_event_desc(struct perf_evsel *events)
1345{ 1502{
1346 struct perf_evsel *evsel; 1503 struct perf_evsel *evsel;
@@ -2373,6 +2530,139 @@ static int process_clockid(struct feat_fd *ff,
2373 return 0; 2530 return 0;
2374} 2531}
2375 2532
2533static int process_dir_format(struct feat_fd *ff,
2534 void *_data __maybe_unused)
2535{
2536 struct perf_session *session;
2537 struct perf_data *data;
2538
2539 session = container_of(ff->ph, struct perf_session, header);
2540 data = session->data;
2541
2542 if (WARN_ON(!perf_data__is_dir(data)))
2543 return -1;
2544
2545 return do_read_u64(ff, &data->dir.version);
2546}
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
2376struct feature_ops { 2666struct feature_ops {
2377 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); 2667 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2378 void (*print)(struct feat_fd *ff, FILE *fp); 2668 void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2432,7 +2722,10 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2432 FEAT_OPN(CACHE, cache, true), 2722 FEAT_OPN(CACHE, cache, true),
2433 FEAT_OPR(SAMPLE_TIME, sample_time, false), 2723 FEAT_OPR(SAMPLE_TIME, sample_time, false),
2434 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true), 2724 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
2435 FEAT_OPR(CLOCKID, clockid, false) 2725 FEAT_OPR(CLOCKID, clockid, 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),
2436}; 2729};
2437 2730
2438struct header_print_data { 2731struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 0d553ddca0a3..386da49e1bfa 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -39,6 +39,9 @@ enum {
39 HEADER_SAMPLE_TIME, 39 HEADER_SAMPLE_TIME,
40 HEADER_MEM_TOPOLOGY, 40 HEADER_MEM_TOPOLOGY,
41 HEADER_CLOCKID, 41 HEADER_CLOCKID,
42 HEADER_DIR_FORMAT,
43 HEADER_BPF_PROG_INFO,
44 HEADER_BPF_BTF,
42 HEADER_LAST_FEATURE, 45 HEADER_LAST_FEATURE,
43 HEADER_FEAT_BITS = 256, 46 HEADER_FEAT_BITS = 256,
44}; 47};
@@ -48,6 +51,10 @@ enum perf_header_version {
48 PERF_HEADER_VERSION_2, 51 PERF_HEADER_VERSION_2,
49}; 52};
50 53
54enum perf_dir_version {
55 PERF_DIR_VERSION = 1,
56};
57
51struct perf_file_section { 58struct perf_file_section {
52 u64 offset; 59 u64 offset;
53 u64 size; 60 u64 size;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f9eb95bf3938..7ace7a10054d 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -19,6 +19,7 @@
19#include <math.h> 19#include <math.h>
20#include <inttypes.h> 20#include <inttypes.h>
21#include <sys/param.h> 21#include <sys/param.h>
22#include <linux/time64.h>
22 23
23static bool hists__filter_entry_by_dso(struct hists *hists, 24static bool hists__filter_entry_by_dso(struct hists *hists,
24 struct hist_entry *he); 25 struct hist_entry *he);
@@ -192,6 +193,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
192 hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3); 193 hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
193 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); 194 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
194 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); 195 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
196 hists__new_col_len(hists, HISTC_TIME, 12);
195 197
196 if (h->srcline) { 198 if (h->srcline) {
197 len = MAX(strlen(h->srcline), strlen(sort_srcline.se_header)); 199 len = MAX(strlen(h->srcline), strlen(sort_srcline.se_header));
@@ -246,6 +248,14 @@ static void he_stat__add_cpumode_period(struct he_stat *he_stat,
246 } 248 }
247} 249}
248 250
251static long hist_time(unsigned long htime)
252{
253 unsigned long time_quantum = symbol_conf.time_quantum;
254 if (time_quantum)
255 return (htime / time_quantum) * time_quantum;
256 return htime;
257}
258
249static void he_stat__add_period(struct he_stat *he_stat, u64 period, 259static void he_stat__add_period(struct he_stat *he_stat, u64 period,
250 u64 weight) 260 u64 weight)
251{ 261{
@@ -426,6 +436,13 @@ static int hist_entry__init(struct hist_entry *he,
426 goto err_rawdata; 436 goto err_rawdata;
427 } 437 }
428 438
439 if (symbol_conf.res_sample) {
440 he->res_samples = calloc(sizeof(struct res_sample),
441 symbol_conf.res_sample);
442 if (!he->res_samples)
443 goto err_srcline;
444 }
445
429 INIT_LIST_HEAD(&he->pairs.node); 446 INIT_LIST_HEAD(&he->pairs.node);
430 thread__get(he->thread); 447 thread__get(he->thread);
431 he->hroot_in = RB_ROOT_CACHED; 448 he->hroot_in = RB_ROOT_CACHED;
@@ -436,6 +453,9 @@ static int hist_entry__init(struct hist_entry *he,
436 453
437 return 0; 454 return 0;
438 455
456err_srcline:
457 free(he->srcline);
458
439err_rawdata: 459err_rawdata:
440 free(he->raw_data); 460 free(he->raw_data);
441 461
@@ -593,6 +613,32 @@ out:
593 return he; 613 return he;
594} 614}
595 615
616static unsigned random_max(unsigned high)
617{
618 unsigned thresh = -high % high;
619 for (;;) {
620 unsigned r = random();
621 if (r >= thresh)
622 return r % high;
623 }
624}
625
626static void hists__res_sample(struct hist_entry *he, struct perf_sample *sample)
627{
628 struct res_sample *r;
629 int j;
630
631 if (he->num_res < symbol_conf.res_sample) {
632 j = he->num_res++;
633 } else {
634 j = random_max(symbol_conf.res_sample);
635 }
636 r = &he->res_samples[j];
637 r->time = sample->time;
638 r->cpu = sample->cpu;
639 r->tid = sample->tid;
640}
641
596static struct hist_entry* 642static struct hist_entry*
597__hists__add_entry(struct hists *hists, 643__hists__add_entry(struct hists *hists,
598 struct addr_location *al, 644 struct addr_location *al,
@@ -635,10 +681,13 @@ __hists__add_entry(struct hists *hists,
635 .raw_data = sample->raw_data, 681 .raw_data = sample->raw_data,
636 .raw_size = sample->raw_size, 682 .raw_size = sample->raw_size,
637 .ops = ops, 683 .ops = ops,
684 .time = hist_time(sample->time),
638 }, *he = hists__findnew_entry(hists, &entry, al, sample_self); 685 }, *he = hists__findnew_entry(hists, &entry, al, sample_self);
639 686
640 if (!hists->has_callchains && he && he->callchain_size != 0) 687 if (!hists->has_callchains && he && he->callchain_size != 0)
641 hists->has_callchains = true; 688 hists->has_callchains = true;
689 if (he && symbol_conf.res_sample)
690 hists__res_sample(he, sample);
642 return he; 691 return he;
643} 692}
644 693
@@ -1062,8 +1111,10 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
1062 1111
1063 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, 1112 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
1064 iter->evsel, al, max_stack_depth); 1113 iter->evsel, al, max_stack_depth);
1065 if (err) 1114 if (err) {
1115 map__put(alm);
1066 return err; 1116 return err;
1117 }
1067 1118
1068 err = iter->ops->prepare_entry(iter, al); 1119 err = iter->ops->prepare_entry(iter, al);
1069 if (err) 1120 if (err)
@@ -1162,6 +1213,7 @@ void hist_entry__delete(struct hist_entry *he)
1162 mem_info__zput(he->mem_info); 1213 mem_info__zput(he->mem_info);
1163 } 1214 }
1164 1215
1216 zfree(&he->res_samples);
1165 zfree(&he->stat_acc); 1217 zfree(&he->stat_acc);
1166 free_srcline(he->srcline); 1218 free_srcline(he->srcline);
1167 if (he->srcfile && he->srcfile[0]) 1219 if (he->srcfile && he->srcfile[0])
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 4af27fbab24f..76ff6c6d03b8 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -31,6 +31,7 @@ enum hist_filter {
31 31
32enum hist_column { 32enum hist_column {
33 HISTC_SYMBOL, 33 HISTC_SYMBOL,
34 HISTC_TIME,
34 HISTC_DSO, 35 HISTC_DSO,
35 HISTC_THREAD, 36 HISTC_THREAD,
36 HISTC_COMM, 37 HISTC_COMM,
@@ -432,9 +433,18 @@ struct hist_browser_timer {
432}; 433};
433 434
434struct annotation_options; 435struct annotation_options;
436struct res_sample;
437
438enum rstype {
439 A_NORMAL,
440 A_ASM,
441 A_SOURCE
442};
435 443
436#ifdef HAVE_SLANG_SUPPORT 444#ifdef HAVE_SLANG_SUPPORT
437#include "../ui/keysyms.h" 445#include "../ui/keysyms.h"
446void attr_to_script(char *buf, struct perf_event_attr *attr);
447
438int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 448int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
439 struct hist_browser_timer *hbt, 449 struct hist_browser_timer *hbt,
440 struct annotation_options *annotation_opts); 450 struct annotation_options *annotation_opts);
@@ -449,7 +459,13 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
449 struct perf_env *env, 459 struct perf_env *env,
450 bool warn_lost_event, 460 bool warn_lost_event,
451 struct annotation_options *annotation_options); 461 struct annotation_options *annotation_options);
452int script_browse(const char *script_opt); 462
463int script_browse(const char *script_opt, struct perf_evsel *evsel);
464
465void run_script(char *cmd);
466int res_sample_browse(struct res_sample *res_samples, int num_res,
467 struct perf_evsel *evsel, enum rstype rstype);
468void res_sample_init(void);
453#else 469#else
454static inline 470static inline
455int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, 471int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
@@ -478,11 +494,22 @@ static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
478 return 0; 494 return 0;
479} 495}
480 496
481static inline int script_browse(const char *script_opt __maybe_unused) 497static inline int script_browse(const char *script_opt __maybe_unused,
498 struct perf_evsel *evsel __maybe_unused)
482{ 499{
483 return 0; 500 return 0;
484} 501}
485 502
503static inline int res_sample_browse(struct res_sample *res_samples __maybe_unused,
504 int num_res __maybe_unused,
505 struct perf_evsel *evsel __maybe_unused,
506 enum rstype rstype __maybe_unused)
507{
508 return 0;
509}
510
511static inline void res_sample_init(void) {}
512
486#define K_LEFT -1000 513#define K_LEFT -1000
487#define K_RIGHT -2000 514#define K_RIGHT -2000
488#define K_SWITCH_INPUT_DATA -3000 515#define K_SWITCH_INPUT_DATA -3000
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 6e03db142091..872fab163585 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -251,19 +251,15 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
251 if (!(decoder->tsc_ctc_ratio_n % decoder->tsc_ctc_ratio_d)) 251 if (!(decoder->tsc_ctc_ratio_n % decoder->tsc_ctc_ratio_d))
252 decoder->tsc_ctc_mult = decoder->tsc_ctc_ratio_n / 252 decoder->tsc_ctc_mult = decoder->tsc_ctc_ratio_n /
253 decoder->tsc_ctc_ratio_d; 253 decoder->tsc_ctc_ratio_d;
254
255 /*
256 * Allow for timestamps appearing to backwards because a TSC
257 * packet has slipped past a MTC packet, so allow 2 MTC ticks
258 * or ...
259 */
260 decoder->tsc_slip = multdiv(2 << decoder->mtc_shift,
261 decoder->tsc_ctc_ratio_n,
262 decoder->tsc_ctc_ratio_d);
263 } 254 }
264 /* ... or 0x100 paranoia */ 255
265 if (decoder->tsc_slip < 0x100) 256 /*
266 decoder->tsc_slip = 0x100; 257 * A TSC packet can slip past MTC packets so that the timestamp appears
258 * to go backwards. One estimate is that can be up to about 40 CPU
259 * cycles, which is certainly less than 0x1000 TSC ticks, but accept
260 * slippage an order of magnitude more to be on the safe side.
261 */
262 decoder->tsc_slip = 0x10000;
267 263
268 intel_pt_log("timestamp: mtc_shift %u\n", decoder->mtc_shift); 264 intel_pt_log("timestamp: mtc_shift %u\n", decoder->mtc_shift);
269 intel_pt_log("timestamp: tsc_ctc_ratio_n %u\n", decoder->tsc_ctc_ratio_n); 265 intel_pt_log("timestamp: tsc_ctc_ratio_n %u\n", decoder->tsc_ctc_ratio_n);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 61959aba7e27..3c520baa198c 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1421,6 +1421,20 @@ static void machine__set_kernel_mmap(struct machine *machine,
1421 machine->vmlinux_map->end = ~0ULL; 1421 machine->vmlinux_map->end = ~0ULL;
1422} 1422}
1423 1423
1424static void machine__update_kernel_mmap(struct machine *machine,
1425 u64 start, u64 end)
1426{
1427 struct map *map = machine__kernel_map(machine);
1428
1429 map__get(map);
1430 map_groups__remove(&machine->kmaps, map);
1431
1432 machine__set_kernel_mmap(machine, start, end);
1433
1434 map_groups__insert(&machine->kmaps, map);
1435 map__put(map);
1436}
1437
1424int machine__create_kernel_maps(struct machine *machine) 1438int machine__create_kernel_maps(struct machine *machine)
1425{ 1439{
1426 struct dso *kernel = machine__get_kernel(machine); 1440 struct dso *kernel = machine__get_kernel(machine);
@@ -1453,17 +1467,11 @@ int machine__create_kernel_maps(struct machine *machine)
1453 goto out_put; 1467 goto out_put;
1454 } 1468 }
1455 1469
1456 /* we have a real start address now, so re-order the kmaps */ 1470 /*
1457 map = machine__kernel_map(machine); 1471 * we have a real start address now, so re-order the kmaps
1458 1472 * assume it's the last in the kmaps
1459 map__get(map); 1473 */
1460 map_groups__remove(&machine->kmaps, map); 1474 machine__update_kernel_mmap(machine, addr, ~0ULL);
1461
1462 /* assume it's the last in the kmaps */
1463 machine__set_kernel_mmap(machine, addr, ~0ULL);
1464
1465 map_groups__insert(&machine->kmaps, map);
1466 map__put(map);
1467 } 1475 }
1468 1476
1469 if (machine__create_extra_kernel_maps(machine, kernel)) 1477 if (machine__create_extra_kernel_maps(machine, kernel))
@@ -1599,7 +1607,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1599 if (strstr(kernel->long_name, "vmlinux")) 1607 if (strstr(kernel->long_name, "vmlinux"))
1600 dso__set_short_name(kernel, "[kernel.vmlinux]", false); 1608 dso__set_short_name(kernel, "[kernel.vmlinux]", false);
1601 1609
1602 machine__set_kernel_mmap(machine, event->mmap.start, 1610 machine__update_kernel_mmap(machine, event->mmap.start,
1603 event->mmap.start + event->mmap.len); 1611 event->mmap.start + event->mmap.len);
1604 1612
1605 /* 1613 /*
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/pmu.c b/tools/perf/util/pmu.c
index 6199a3174ab9..e0429f4ef335 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -732,10 +732,20 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
732 732
733 if (!is_arm_pmu_core(name)) { 733 if (!is_arm_pmu_core(name)) {
734 pname = pe->pmu ? pe->pmu : "cpu"; 734 pname = pe->pmu ? pe->pmu : "cpu";
735
736 /*
737 * uncore alias may be from different PMU
738 * with common prefix
739 */
740 if (pmu_is_uncore(name) &&
741 !strncmp(pname, name, strlen(pname)))
742 goto new_alias;
743
735 if (strcmp(pname, name)) 744 if (strcmp(pname, name))
736 continue; 745 continue;
737 } 746 }
738 747
748new_alias:
739 /* need type casts to override 'const' */ 749 /* need type casts to override 'const' */
740 __perf_pmu__new_alias(head, NULL, (char *)pe->name, 750 __perf_pmu__new_alias(head, NULL, (char *)pe->name,
741 (char *)pe->desc, (char *)pe->event, 751 (char *)pe->desc, (char *)pe->event,
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a1b8d9649ca7..198e09ff611e 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -160,8 +160,10 @@ static struct map *kernel_get_module_map(const char *module)
160 if (module && strchr(module, '/')) 160 if (module && strchr(module, '/'))
161 return dso__new_map(module); 161 return dso__new_map(module);
162 162
163 if (!module) 163 if (!module) {
164 module = "kernel"; 164 pos = machine__kernel_map(host_machine);
165 return map__get(pos);
166 }
165 167
166 for (pos = maps__first(maps); pos; pos = map__next(pos)) { 168 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
167 /* short_name is "[module]" */ 169 /* short_name is "[module]" */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index db643f3c2b95..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;
@@ -152,6 +153,10 @@ struct perf_session *perf_session__new(struct perf_data *data,
152 } 153 }
153 154
154 perf_evlist__init_trace_event_sample_raw(session->evlist); 155 perf_evlist__init_trace_event_sample_raw(session->evlist);
156
157 /* Open the directory data. */
158 if (data->is_dir && perf_data__open_dir(data))
159 goto out_delete;
155 } 160 }
156 } else { 161 } else {
157 session->machines.host.env = &perf_env; 162 session->machines.host.env = &perf_env;
@@ -1843,10 +1848,17 @@ fetch_mmaped_event(struct perf_session *session,
1843#define NUM_MMAPS 128 1848#define NUM_MMAPS 128
1844#endif 1849#endif
1845 1850
1851struct reader;
1852
1853typedef s64 (*reader_cb_t)(struct perf_session *session,
1854 union perf_event *event,
1855 u64 file_offset);
1856
1846struct reader { 1857struct reader {
1847 int fd; 1858 int fd;
1848 u64 data_size; 1859 u64 data_size;
1849 u64 data_offset; 1860 u64 data_offset;
1861 reader_cb_t process;
1850}; 1862};
1851 1863
1852static int 1864static int
@@ -1917,7 +1929,7 @@ more:
1917 size = event->header.size; 1929 size = event->header.size;
1918 1930
1919 if (size < sizeof(struct perf_event_header) || 1931 if (size < sizeof(struct perf_event_header) ||
1920 (skip = perf_session__process_event(session, event, file_pos)) < 0) { 1932 (skip = rd->process(session, event, file_pos)) < 0) {
1921 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1933 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1922 file_offset + head, event->header.size, 1934 file_offset + head, event->header.size,
1923 event->header.type); 1935 event->header.type);
@@ -1943,12 +1955,20 @@ out:
1943 return err; 1955 return err;
1944} 1956}
1945 1957
1958static s64 process_simple(struct perf_session *session,
1959 union perf_event *event,
1960 u64 file_offset)
1961{
1962 return perf_session__process_event(session, event, file_offset);
1963}
1964
1946static int __perf_session__process_events(struct perf_session *session) 1965static int __perf_session__process_events(struct perf_session *session)
1947{ 1966{
1948 struct reader rd = { 1967 struct reader rd = {
1949 .fd = perf_data__fd(session->data), 1968 .fd = perf_data__fd(session->data),
1950 .data_size = session->header.data_size, 1969 .data_size = session->header.data_size,
1951 .data_offset = session->header.data_offset, 1970 .data_offset = session->header.data_offset,
1971 .process = process_simple,
1952 }; 1972 };
1953 struct ordered_events *oe = &session->ordered_events; 1973 struct ordered_events *oe = &session->ordered_events;
1954 struct perf_tool *tool = session->tool; 1974 struct perf_tool *tool = session->tool;
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index d2299e912e59..5d2518e89fc4 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -3,6 +3,7 @@
3#include <inttypes.h> 3#include <inttypes.h>
4#include <regex.h> 4#include <regex.h>
5#include <linux/mman.h> 5#include <linux/mman.h>
6#include <linux/time64.h>
6#include "sort.h" 7#include "sort.h"
7#include "hist.h" 8#include "hist.h"
8#include "comm.h" 9#include "comm.h"
@@ -12,9 +13,11 @@
12#include "evsel.h" 13#include "evsel.h"
13#include "evlist.h" 14#include "evlist.h"
14#include "strlist.h" 15#include "strlist.h"
16#include "strbuf.h"
15#include <traceevent/event-parse.h> 17#include <traceevent/event-parse.h>
16#include "mem-events.h" 18#include "mem-events.h"
17#include "annotate.h" 19#include "annotate.h"
20#include "time-utils.h"
18#include <linux/kernel.h> 21#include <linux/kernel.h>
19 22
20regex_t parent_regex; 23regex_t parent_regex;
@@ -654,6 +657,42 @@ struct sort_entry sort_socket = {
654 .se_width_idx = HISTC_SOCKET, 657 .se_width_idx = HISTC_SOCKET,
655}; 658};
656 659
660/* --sort time */
661
662static int64_t
663sort__time_cmp(struct hist_entry *left, struct hist_entry *right)
664{
665 return right->time - left->time;
666}
667
668static int hist_entry__time_snprintf(struct hist_entry *he, char *bf,
669 size_t size, unsigned int width)
670{
671 unsigned long secs;
672 unsigned long long nsecs;
673 char he_time[32];
674
675 nsecs = he->time;
676 secs = nsecs / NSEC_PER_SEC;
677 nsecs -= secs * NSEC_PER_SEC;
678
679 if (symbol_conf.nanosecs)
680 snprintf(he_time, sizeof he_time, "%5lu.%09llu: ",
681 secs, nsecs);
682 else
683 timestamp__scnprintf_usec(he->time, he_time,
684 sizeof(he_time));
685
686 return repsep_snprintf(bf, size, "%-.*s", width, he_time);
687}
688
689struct sort_entry sort_time = {
690 .se_header = "Time",
691 .se_cmp = sort__time_cmp,
692 .se_snprintf = hist_entry__time_snprintf,
693 .se_width_idx = HISTC_TIME,
694};
695
657/* --sort trace */ 696/* --sort trace */
658 697
659static char *get_trace_output(struct hist_entry *he) 698static char *get_trace_output(struct hist_entry *he)
@@ -1634,6 +1673,7 @@ static struct sort_dimension common_sort_dimensions[] = {
1634 DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size), 1673 DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size),
1635 DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), 1674 DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id),
1636 DIM(SORT_SYM_IPC_NULL, "ipc_null", sort_sym_ipc_null), 1675 DIM(SORT_SYM_IPC_NULL, "ipc_null", sort_sym_ipc_null),
1676 DIM(SORT_TIME, "time", sort_time),
1637}; 1677};
1638 1678
1639#undef DIM 1679#undef DIM
@@ -3068,3 +3108,54 @@ void reset_output_field(void)
3068 reset_dimensions(); 3108 reset_dimensions();
3069 perf_hpp__reset_output_field(&perf_hpp_list); 3109 perf_hpp__reset_output_field(&perf_hpp_list);
3070} 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 2fbee0b1011c..ce376a73f964 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -47,6 +47,12 @@ extern struct sort_entry sort_srcline;
47extern enum sort_type sort__first_dimension; 47extern enum sort_type sort__first_dimension;
48extern const char default_mem_sort_order[]; 48extern const char default_mem_sort_order[];
49 49
50struct res_sample {
51 u64 time;
52 int cpu;
53 int tid;
54};
55
50struct he_stat { 56struct he_stat {
51 u64 period; 57 u64 period;
52 u64 period_sys; 58 u64 period_sys;
@@ -135,10 +141,13 @@ struct hist_entry {
135 char *srcfile; 141 char *srcfile;
136 struct symbol *parent; 142 struct symbol *parent;
137 struct branch_info *branch_info; 143 struct branch_info *branch_info;
144 long time;
138 struct hists *hists; 145 struct hists *hists;
139 struct mem_info *mem_info; 146 struct mem_info *mem_info;
140 void *raw_data; 147 void *raw_data;
141 u32 raw_size; 148 u32 raw_size;
149 int num_res;
150 struct res_sample *res_samples;
142 void *trace_output; 151 void *trace_output;
143 struct perf_hpp_list *hpp_list; 152 struct perf_hpp_list *hpp_list;
144 struct hist_entry *parent_he; 153 struct hist_entry *parent_he;
@@ -231,6 +240,7 @@ enum sort_type {
231 SORT_DSO_SIZE, 240 SORT_DSO_SIZE,
232 SORT_CGROUP_ID, 241 SORT_CGROUP_ID,
233 SORT_SYM_IPC_NULL, 242 SORT_SYM_IPC_NULL,
243 SORT_TIME,
234 244
235 /* branch stack specific sort keys */ 245 /* branch stack specific sort keys */
236 __SORT_BRANCH_STACK, 246 __SORT_BRANCH_STACK,
@@ -286,6 +296,8 @@ void reset_output_field(void);
286void sort__setup_elide(FILE *fp); 296void sort__setup_elide(FILE *fp);
287void perf_hpp__set_elide(int idx, bool elide); 297void perf_hpp__set_elide(int idx, bool elide);
288 298
299const char *sort_help(const char *prefix);
300
289int 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);
290 302
291bool 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 758bf5f74e6e..5cbad55cd99d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -6,6 +6,7 @@
6#include <string.h> 6#include <string.h>
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/mman.h> 8#include <linux/mman.h>
9#include <linux/time64.h>
9#include <sys/types.h> 10#include <sys/types.h>
10#include <sys/stat.h> 11#include <sys/stat.h>
11#include <sys/param.h> 12#include <sys/param.h>
@@ -39,15 +40,18 @@ int vmlinux_path__nr_entries;
39char **vmlinux_path; 40char **vmlinux_path;
40 41
41struct symbol_conf symbol_conf = { 42struct symbol_conf symbol_conf = {
43 .nanosecs = false,
42 .use_modules = true, 44 .use_modules = true,
43 .try_vmlinux_path = true, 45 .try_vmlinux_path = true,
44 .demangle = true, 46 .demangle = true,
45 .demangle_kernel = false, 47 .demangle_kernel = false,
46 .cumulate_callchain = true, 48 .cumulate_callchain = true,
49 .time_quantum = 100 * NSEC_PER_MSEC, /* 100ms */
47 .show_hist_headers = true, 50 .show_hist_headers = true,
48 .symfs = "", 51 .symfs = "",
49 .event_group = true, 52 .event_group = true,
50 .inline_name = true, 53 .inline_name = true,
54 .res_sample = 0,
51}; 55};
52 56
53static enum dso_binary_type binary_type_symtab[] = { 57static enum dso_binary_type binary_type_symtab[] = {
@@ -1451,6 +1455,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1451 case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: 1455 case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
1452 return true; 1456 return true;
1453 1457
1458 case DSO_BINARY_TYPE__BPF_PROG_INFO:
1454 case DSO_BINARY_TYPE__NOT_FOUND: 1459 case DSO_BINARY_TYPE__NOT_FOUND:
1455 default: 1460 default:
1456 return false; 1461 return false;
diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h
index fffea68c1203..6c55fa6fccec 100644
--- a/tools/perf/util/symbol_conf.h
+++ b/tools/perf/util/symbol_conf.h
@@ -8,6 +8,7 @@ struct strlist;
8struct intlist; 8struct intlist;
9 9
10struct symbol_conf { 10struct symbol_conf {
11 bool nanosecs;
11 unsigned short priv_size; 12 unsigned short priv_size;
12 bool try_vmlinux_path, 13 bool try_vmlinux_path,
13 init_annotation, 14 init_annotation,
@@ -55,6 +56,7 @@ struct symbol_conf {
55 *sym_list_str, 56 *sym_list_str,
56 *col_width_list_str, 57 *col_width_list_str,
57 *bt_stop_list_str; 58 *bt_stop_list_str;
59 unsigned long time_quantum;
58 struct strlist *dso_list, 60 struct strlist *dso_list,
59 *comm_list, 61 *comm_list,
60 *sym_list, 62 *sym_list,
@@ -66,6 +68,7 @@ struct symbol_conf {
66 struct intlist *pid_list, 68 struct intlist *pid_list,
67 *tid_list; 69 *tid_list;
68 const char *symfs; 70 const char *symfs;
71 int res_sample;
69}; 72};
70 73
71extern struct symbol_conf symbol_conf; 74extern struct symbol_conf symbol_conf;
diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index 0f53baec660e..20663a460df3 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -453,6 +453,14 @@ int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
453 return scnprintf(buf, sz, "%"PRIu64".%06"PRIu64, sec, usec); 453 return scnprintf(buf, sz, "%"PRIu64".%06"PRIu64, sec, usec);
454} 454}
455 455
456int timestamp__scnprintf_nsec(u64 timestamp, char *buf, size_t sz)
457{
458 u64 sec = timestamp / NSEC_PER_SEC,
459 nsec = timestamp % NSEC_PER_SEC;
460
461 return scnprintf(buf, sz, "%" PRIu64 ".%09" PRIu64, sec, nsec);
462}
463
456int fetch_current_timestamp(char *buf, size_t sz) 464int fetch_current_timestamp(char *buf, size_t sz)
457{ 465{
458 struct timeval tv; 466 struct timeval tv;
diff --git a/tools/perf/util/time-utils.h b/tools/perf/util/time-utils.h
index b923de44e36f..72a42ea1d513 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -30,6 +30,7 @@ int perf_time__parse_for_ranges(const char *str, struct perf_session *session,
30 int *range_size, int *range_num); 30 int *range_size, int *range_num);
31 31
32int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz); 32int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
33int timestamp__scnprintf_nsec(u64 timestamp, char *buf, size_t sz);
33 34
34int fetch_current_timestamp(char *buf, size_t sz); 35int fetch_current_timestamp(char *buf, size_t sz);
35 36