aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-12-20 21:14:03 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-12-20 21:14:03 -0500
commite219aafe50fd546b8686582ddbafd24c3c2eda04 (patch)
treea665e08ca8d42f20ac8e5dcc8565d666cffb26bd /tools/perf
parentffe12855a5f7f195589130197558e6a5c276caa4 (diff)
parent24c96dc79c5e76d3cff7a33f955a4d3244644766 (diff)
Merge back earlier 'pm-domains' material for v4.5.
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/intel-pt.txt44
-rw-r--r--tools/perf/Documentation/itrace.txt4
-rw-r--r--tools/perf/Documentation/perf-bench.txt54
-rw-r--r--tools/perf/Documentation/perf-inject.txt3
-rw-r--r--tools/perf/Documentation/perf-list.txt3
-rw-r--r--tools/perf/Documentation/perf-record.txt16
-rw-r--r--tools/perf/Documentation/perf-report.txt48
-rw-r--r--tools/perf/Documentation/perf-script.txt17
-rw-r--r--tools/perf/Documentation/perf-stat.txt5
-rw-r--r--tools/perf/Documentation/perf-top.txt5
-rw-r--r--tools/perf/Documentation/perf-trace.txt1
-rw-r--r--tools/perf/Documentation/perf.txt8
-rw-r--r--tools/perf/MANIFEST5
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/Makefile.perf53
-rw-r--r--tools/perf/arch/common.c10
-rw-r--r--tools/perf/arch/common.h4
-rw-r--r--tools/perf/arch/x86/Build2
-rw-r--r--tools/perf/arch/x86/Makefile1
-rw-r--r--tools/perf/arch/x86/include/arch-tests.h19
-rw-r--r--tools/perf/arch/x86/tests/Build10
-rw-r--r--tools/perf/arch/x86/tests/arch-tests.c34
-rw-r--r--tools/perf/arch/x86/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/x86/tests/gen-insn-x86-dat.awk75
-rwxr-xr-xtools/perf/arch/x86/tests/gen-insn-x86-dat.sh43
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-32.c658
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-64.c768
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-src.c877
-rw-r--r--tools/perf/arch/x86/tests/insn-x86.c185
-rw-r--r--tools/perf/arch/x86/tests/intel-cqm.c124
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c (renamed from tools/perf/tests/perf-time-to-tsc.c)4
-rw-r--r--tools/perf/arch/x86/tests/rdpmc.c (renamed from tools/perf/tests/rdpmc.c)7
-rw-r--r--tools/perf/arch/x86/util/dwarf-regs.c122
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c55
-rw-r--r--tools/perf/bench/Build2
-rw-r--r--tools/perf/bench/mem-functions.c379
-rw-r--r--tools/perf/bench/mem-memcpy.c434
-rw-r--r--tools/perf/bench/numa.c4
-rw-r--r--tools/perf/bench/sched-messaging.c10
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-bench.c14
-rw-r--r--tools/perf/builtin-evlist.c4
-rw-r--r--tools/perf/builtin-help.c2
-rw-r--r--tools/perf/builtin-inject.c128
-rw-r--r--tools/perf/builtin-kmem.c2
-rw-r--r--tools/perf/builtin-kvm.c1
-rw-r--r--tools/perf/builtin-list.c20
-rw-r--r--tools/perf/builtin-probe.c147
-rw-r--r--tools/perf/builtin-record.c56
-rw-r--r--tools/perf/builtin-report.c71
-rw-r--r--tools/perf/builtin-sched.c9
-rw-r--r--tools/perf/builtin-script.c113
-rw-r--r--tools/perf/builtin-stat.c311
-rw-r--r--tools/perf/builtin-top.c59
-rw-r--r--tools/perf/builtin-trace.c31
-rw-r--r--tools/perf/config/Makefile23
-rw-r--r--tools/perf/perf.c30
-rwxr-xr-xtools/perf/python/twatch.py23
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py221
-rw-r--r--tools/perf/tests/.gitignore2
-rw-r--r--tools/perf/tests/Build19
-rw-r--r--tools/perf/tests/attr.c3
-rw-r--r--tools/perf/tests/bpf-script-example.c48
-rw-r--r--tools/perf/tests/bpf-script-test-kbuild.c21
-rw-r--r--tools/perf/tests/bpf.c209
-rw-r--r--tools/perf/tests/builtin-test.c80
-rw-r--r--tools/perf/tests/code-reading.c84
-rw-r--r--tools/perf/tests/dwarf-unwind.c4
-rw-r--r--tools/perf/tests/evsel-tp-sched.c10
-rw-r--r--tools/perf/tests/hists_filter.c55
-rw-r--r--tools/perf/tests/keep-tracking.c4
-rw-r--r--tools/perf/tests/llvm.c146
-rw-r--r--tools/perf/tests/llvm.h18
-rw-r--r--tools/perf/tests/make9
-rw-r--r--tools/perf/tests/mmap-basic.c3
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c13
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c5
-rw-r--r--tools/perf/tests/openat-syscall.c13
-rw-r--r--tools/perf/tests/parse-events.c49
-rw-r--r--tools/perf/tests/switch-tracking.c4
-rw-r--r--tools/perf/tests/tests.h11
-rw-r--r--tools/perf/tests/topology.c115
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c4
-rw-r--r--tools/perf/trace/strace/groups/file2
-rw-r--r--tools/perf/ui/browser.c14
-rw-r--r--tools/perf/ui/browser.h2
-rw-r--r--tools/perf/ui/browsers/annotate.c14
-rw-r--r--tools/perf/ui/browsers/hists.c121
-rw-r--r--tools/perf/ui/browsers/map.c2
-rw-r--r--tools/perf/ui/browsers/scripts.c2
-rw-r--r--tools/perf/ui/hist.c16
-rw-r--r--tools/perf/ui/tui/setup.c8
-rw-r--r--tools/perf/util/Build2
-rw-r--r--tools/perf/util/annotate.c26
-rw-r--r--tools/perf/util/annotate.h2
-rw-r--r--tools/perf/util/auxtrace.c24
-rw-r--r--tools/perf/util/auxtrace.h4
-rw-r--r--tools/perf/util/bpf-loader.c457
-rw-r--r--tools/perf/util/bpf-loader.h118
-rw-r--r--tools/perf/util/build-id.c1
-rw-r--r--tools/perf/util/callchain.c42
-rw-r--r--tools/perf/util/callchain.h26
-rw-r--r--tools/perf/util/cpumap.c97
-rw-r--r--tools/perf/util/cpumap.h10
-rw-r--r--tools/perf/util/dso.c17
-rw-r--r--tools/perf/util/dso.h1
-rw-r--r--tools/perf/util/env.c86
-rw-r--r--tools/perf/util/env.h44
-rw-r--r--tools/perf/util/event.c22
-rw-r--r--tools/perf/util/event.h6
-rw-r--r--tools/perf/util/evlist.c47
-rw-r--r--tools/perf/util/evlist.h5
-rw-r--r--tools/perf/util/evsel.c50
-rw-r--r--tools/perf/util/evsel.h10
-rw-r--r--tools/perf/util/header.c136
-rw-r--r--tools/perf/util/header.h27
-rw-r--r--tools/perf/util/hist.c59
-rw-r--r--tools/perf/util/hist.h8
-rw-r--r--tools/perf/util/include/dwarf-regs.h8
-rw-r--r--tools/perf/util/intel-pt-decoder/Build13
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c4
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-log.c21
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-log.h38
-rw-r--r--tools/perf/util/intel-pt-decoder/x86-opcode-map.txt24
-rw-r--r--tools/perf/util/intel-pt.c266
-rw-r--r--tools/perf/util/llvm-utils.c54
-rw-r--r--tools/perf/util/machine.c30
-rw-r--r--tools/perf/util/machine.h9
-rw-r--r--tools/perf/util/map.c31
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/parse-branch-options.c1
-rw-r--r--tools/perf/util/parse-events.c375
-rw-r--r--tools/perf/util/parse-events.h16
-rw-r--r--tools/perf/util/parse-events.l12
-rw-r--r--tools/perf/util/parse-events.y82
-rw-r--r--tools/perf/util/parse-options.c156
-rw-r--r--tools/perf/util/parse-options.h5
-rw-r--r--tools/perf/util/pmu.c42
-rw-r--r--tools/perf/util/probe-event.c234
-rw-r--r--tools/perf/util/probe-event.h11
-rw-r--r--tools/perf/util/probe-file.c62
-rw-r--r--tools/perf/util/probe-file.h4
-rw-r--r--tools/perf/util/probe-finder.c82
-rw-r--r--tools/perf/util/python.c59
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c3
-rw-r--r--tools/perf/util/session.c45
-rw-r--r--tools/perf/util/session.h2
-rw-r--r--tools/perf/util/sort.c74
-rw-r--r--tools/perf/util/sort.h6
-rw-r--r--tools/perf/util/srcline.c29
-rw-r--r--tools/perf/util/stat-shadow.c5
-rw-r--r--tools/perf/util/stat.c13
-rw-r--r--tools/perf/util/stat.h3
-rw-r--r--tools/perf/util/strbuf.c22
-rw-r--r--tools/perf/util/strbuf.h2
-rw-r--r--tools/perf/util/symbol-minimal.c2
-rw-r--r--tools/perf/util/symbol.c63
-rw-r--r--tools/perf/util/symbol.h2
-rw-r--r--tools/perf/util/trace-event-info.c2
-rw-r--r--tools/perf/util/trace-event.c16
-rw-r--r--tools/perf/util/trace-event.h2
-rw-r--r--tools/perf/util/unwind-libunwind.c19
-rw-r--r--tools/perf/util/usage.c5
-rw-r--r--tools/perf/util/util.c102
-rw-r--r--tools/perf/util/util.h20
166 files changed, 8204 insertions, 1675 deletions
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index c94c9de3173e..be764f9ec769 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -671,6 +671,7 @@ The letters are:
671 e synthesize tracing error events 671 e synthesize tracing error events
672 d create a debug log 672 d create a debug log
673 g synthesize a call chain (use with i or x) 673 g synthesize a call chain (use with i or x)
674 l synthesize last branch entries (use with i or x)
674 675
675"Instructions" events look like they were recorded by "perf record -e 676"Instructions" events look like they were recorded by "perf record -e
676instructions". 677instructions".
@@ -707,12 +708,26 @@ on the sample is *not* adjusted and reflects the last known value of TSC.
707 708
708For Intel PT, the default period is 100us. 709For Intel PT, the default period is 100us.
709 710
711Setting it to a zero period means "as often as possible".
712
713In the case of Intel PT that is the same as a period of 1 and a unit of
714'instructions' (i.e. --itrace=i1i).
715
710Also the call chain size (default 16, max. 1024) for instructions or 716Also the call chain size (default 16, max. 1024) for instructions or
711transactions events can be specified. e.g. 717transactions events can be specified. e.g.
712 718
713 --itrace=ig32 719 --itrace=ig32
714 --itrace=xg32 720 --itrace=xg32
715 721
722Also the number of last branch entries (default 64, max. 1024) for instructions or
723transactions events can be specified. e.g.
724
725 --itrace=il10
726 --itrace=xl10
727
728Note that last branch entries are cleared for each sample, so there is no overlap
729from one sample to the next.
730
716To disable trace decoding entirely, use the option --no-itrace. 731To disable trace decoding entirely, use the option --no-itrace.
717 732
718 733
@@ -749,3 +764,32 @@ perf inject also accepts the --itrace option in which case tracing data is
749removed and replaced with the synthesized events. e.g. 764removed and replaced with the synthesized events. e.g.
750 765
751 perf inject --itrace -i perf.data -o perf.data.new 766 perf inject --itrace -i perf.data -o perf.data.new
767
768Below is an example of using Intel PT with autofdo. It requires autofdo
769(https://github.com/google/autofdo) and gcc version 5. The bubble
770sort example is from the AutoFDO tutorial (https://gcc.gnu.org/wiki/AutoFDO/Tutorial)
771amended to take the number of elements as a parameter.
772
773 $ gcc-5 -O3 sort.c -o sort_optimized
774 $ ./sort_optimized 30000
775 Bubble sorting array of 30000 elements
776 2254 ms
777
778 $ cat ~/.perfconfig
779 [intel-pt]
780 mispred-all
781
782 $ perf record -e intel_pt//u ./sort 3000
783 Bubble sorting array of 3000 elements
784 58 ms
785 [ perf record: Woken up 2 times to write data ]
786 [ perf record: Captured and wrote 3.939 MB perf.data ]
787 $ perf inject -i perf.data -o inj --itrace=i100usle --strip
788 $ ./create_gcov --binary=./sort --profile=inj --gcov=sort.gcov -gcov_version=1
789 $ gcc-5 -O3 -fauto-profile=sort.gcov sort.c -o sort_autofdo
790 $ ./sort_autofdo 30000
791 Bubble sorting array of 30000 elements
792 2155 ms
793
794Note there is currently no advantage to using Intel PT instead of LBR, but
795that may change in the future if greater use is made of the data.
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt
index 2ff946677e3b..65453f4c7006 100644
--- a/tools/perf/Documentation/itrace.txt
+++ b/tools/perf/Documentation/itrace.txt
@@ -6,6 +6,7 @@
6 e synthesize error events 6 e synthesize error events
7 d create a debug log 7 d create a debug log
8 g synthesize a call chain (use with i or x) 8 g synthesize a call chain (use with i or x)
9 l synthesize last branch entries (use with i or x)
9 10
10 The default is all events i.e. the same as --itrace=ibxe 11 The default is all events i.e. the same as --itrace=ibxe
11 12
@@ -20,3 +21,6 @@
20 21
21 Also the call chain size (default 16, max. 1024) for instructions or 22 Also the call chain size (default 16, max. 1024) for instructions or
22 transactions events can be specified. 23 transactions events can be specified.
24
25 Also the number of last branch entries (default 64, max. 1024) for
26 instructions or transactions events can be specified.
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt
index ab632d9fbd7d..34750fc32714 100644
--- a/tools/perf/Documentation/perf-bench.txt
+++ b/tools/perf/Documentation/perf-bench.txt
@@ -82,7 +82,7 @@ Be multi thread instead of multi process
82Specify number of groups 82Specify number of groups
83 83
84-l:: 84-l::
85--loop=:: 85--nr_loops=::
86Specify number of loops 86Specify number of loops
87 87
88Example of *messaging* 88Example of *messaging*
@@ -139,64 +139,48 @@ Suite for evaluating performance of simple memory copy in various ways.
139Options of *memcpy* 139Options of *memcpy*
140^^^^^^^^^^^^^^^^^^^ 140^^^^^^^^^^^^^^^^^^^
141-l:: 141-l::
142--length:: 142--size::
143Specify length of memory to copy (default: 1MB). 143Specify size of memory to copy (default: 1MB).
144Available units are B, KB, MB, GB and TB (case insensitive). 144Available units are B, KB, MB, GB and TB (case insensitive).
145 145
146-r:: 146-f::
147--routine:: 147--function::
148Specify routine to copy (default: default). 148Specify function to copy (default: default).
149Available routines are depend on the architecture. 149Available functions are depend on the architecture.
150On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported. 150On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported.
151 151
152-i:: 152-l::
153--iterations:: 153--nr_loops::
154Repeat memcpy invocation this number of times. 154Repeat memcpy invocation this number of times.
155 155
156-c:: 156-c::
157--cycle:: 157--cycles::
158Use perf's cpu-cycles event instead of gettimeofday syscall. 158Use perf's cpu-cycles event instead of gettimeofday syscall.
159 159
160-o::
161--only-prefault::
162Show only the result with page faults before memcpy.
163
164-n::
165--no-prefault::
166Show only the result without page faults before memcpy.
167
168*memset*:: 160*memset*::
169Suite for evaluating performance of simple memory set in various ways. 161Suite for evaluating performance of simple memory set in various ways.
170 162
171Options of *memset* 163Options of *memset*
172^^^^^^^^^^^^^^^^^^^ 164^^^^^^^^^^^^^^^^^^^
173-l:: 165-l::
174--length:: 166--size::
175Specify length of memory to set (default: 1MB). 167Specify size of memory to set (default: 1MB).
176Available units are B, KB, MB, GB and TB (case insensitive). 168Available units are B, KB, MB, GB and TB (case insensitive).
177 169
178-r:: 170-f::
179--routine:: 171--function::
180Specify routine to set (default: default). 172Specify function to set (default: default).
181Available routines are depend on the architecture. 173Available functions are depend on the architecture.
182On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported. 174On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported.
183 175
184-i:: 176-l::
185--iterations:: 177--nr_loops::
186Repeat memset invocation this number of times. 178Repeat memset invocation this number of times.
187 179
188-c:: 180-c::
189--cycle:: 181--cycles::
190Use perf's cpu-cycles event instead of gettimeofday syscall. 182Use perf's cpu-cycles event instead of gettimeofday syscall.
191 183
192-o::
193--only-prefault::
194Show only the result with page faults before memset.
195
196-n::
197--no-prefault::
198Show only the result without page faults before memset.
199
200SUITES FOR 'numa' 184SUITES FOR 'numa'
201~~~~~~~~~~~~~~~~~ 185~~~~~~~~~~~~~~~~~
202*mem*:: 186*mem*::
diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt
index 0c721c3e37e1..0b1cedeef895 100644
--- a/tools/perf/Documentation/perf-inject.txt
+++ b/tools/perf/Documentation/perf-inject.txt
@@ -50,6 +50,9 @@ OPTIONS
50 50
51include::itrace.txt[] 51include::itrace.txt[]
52 52
53--strip::
54 Use with --itrace to strip out non-synthesized events.
55
53SEE ALSO 56SEE ALSO
54-------- 57--------
55linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1] 58linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index bada8933fdd4..79483f40e991 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -30,6 +30,7 @@ counted. The following modifiers exist:
30 G - guest counting (in KVM guests) 30 G - guest counting (in KVM guests)
31 H - host counting (not in KVM guests) 31 H - host counting (not in KVM guests)
32 p - precise level 32 p - precise level
33 P - use maximum detected precise level
33 S - read sample value (PERF_SAMPLE_READ) 34 S - read sample value (PERF_SAMPLE_READ)
34 D - pin the event to the PMU 35 D - pin the event to the PMU
35 36
@@ -125,6 +126,8 @@ To limit the list use:
125. If none of the above is matched, it will apply the supplied glob to all 126. If none of the above is matched, it will apply the supplied glob to all
126 events, printing the ones that match. 127 events, printing the ones that match.
127 128
129. As a last resort, it will do a substring search in all event names.
130
128One or more types can be used at the same time, listing the events for the 131One or more types can be used at the same time, listing the events for the
129types specified. 132types specified.
130 133
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 2e9ce77b5e14..e630a7d2c348 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -144,7 +144,7 @@ OPTIONS
144 144
145--call-graph:: 145--call-graph::
146 Setup and enable call-graph (stack chain/backtrace) recording, 146 Setup and enable call-graph (stack chain/backtrace) recording,
147 implies -g. 147 implies -g. Default is "fp".
148 148
149 Allows specifying "fp" (frame pointer) or "dwarf" 149 Allows specifying "fp" (frame pointer) or "dwarf"
150 (DWARF's CFI - Call Frame Information) or "lbr" 150 (DWARF's CFI - Call Frame Information) or "lbr"
@@ -154,13 +154,18 @@ OPTIONS
154 In some systems, where binaries are build with gcc 154 In some systems, where binaries are build with gcc
155 --fomit-frame-pointer, using the "fp" method will produce bogus 155 --fomit-frame-pointer, using the "fp" method will produce bogus
156 call graphs, using "dwarf", if available (perf tools linked to 156 call graphs, using "dwarf", if available (perf tools linked to
157 the libunwind library) should be used instead. 157 the libunwind or libdw library) should be used instead.
158 Using the "lbr" method doesn't require any compiler options. It 158 Using the "lbr" method doesn't require any compiler options. It
159 will produce call graphs from the hardware LBR registers. The 159 will produce call graphs from the hardware LBR registers. The
160 main limition is that it is only available on new Intel 160 main limition is that it is only available on new Intel
161 platforms, such as Haswell. It can only get user call chain. It 161 platforms, such as Haswell. It can only get user call chain. It
162 doesn't work with branch stack sampling at the same time. 162 doesn't work with branch stack sampling at the same time.
163 163
164 When "dwarf" recording is used, perf also records (user) stack dump
165 when sampled. Default size of the stack dump is 8192 (bytes).
166 User can change the size by passing the size after comma like
167 "--call-graph dwarf,4096".
168
164-q:: 169-q::
165--quiet:: 170--quiet::
166 Don't print any message, useful for scripting. 171 Don't print any message, useful for scripting.
@@ -236,6 +241,7 @@ following filters are defined:
236 - any_call: any function call or system call 241 - any_call: any function call or system call
237 - any_ret: any function return or system call return 242 - any_ret: any function return or system call return
238 - ind_call: any indirect branch 243 - ind_call: any indirect branch
244 - call: direct calls, including far (to/from kernel) calls
239 - u: only when the branch target is at the user level 245 - u: only when the branch target is at the user level
240 - k: only when the branch target is in the kernel 246 - k: only when the branch target is in the kernel
241 - hv: only when the target is at the hypervisor level 247 - hv: only when the target is at the hypervisor level
@@ -308,6 +314,12 @@ This option sets the time out limit. The default value is 500 ms.
308Record context switch events i.e. events of type PERF_RECORD_SWITCH or 314Record context switch events i.e. events of type PERF_RECORD_SWITCH or
309PERF_RECORD_SWITCH_CPU_WIDE. 315PERF_RECORD_SWITCH_CPU_WIDE.
310 316
317--clang-path::
318Path to clang binary to use for compiling BPF scriptlets.
319
320--clang-opt::
321Options passed to clang when compiling BPF scriptlets.
322
311SEE ALSO 323SEE ALSO
312-------- 324--------
313linkperf:perf-stat[1], linkperf:perf-list[1] 325linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 9c7981bfddad..5ce8da1e1256 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -29,7 +29,7 @@ OPTIONS
29--show-nr-samples:: 29--show-nr-samples::
30 Show the number of samples for each symbol 30 Show the number of samples for each symbol
31 31
32--showcpuutilization:: 32--show-cpu-utilization::
33 Show sample percentage for different cpu modes. 33 Show sample percentage for different cpu modes.
34 34
35-T:: 35-T::
@@ -68,7 +68,7 @@ OPTIONS
68--sort=:: 68--sort=::
69 Sort histogram entries by given key(s) - multiple keys can be specified 69 Sort histogram entries by given key(s) - multiple keys can be specified
70 in CSV format. Following sort keys are available: 70 in CSV format. Following sort keys are available:
71 pid, comm, dso, symbol, parent, cpu, srcline, weight, local_weight. 71 pid, comm, dso, symbol, parent, cpu, socket, srcline, weight, local_weight.
72 72
73 Each key has following meaning: 73 Each key has following meaning:
74 74
@@ -79,6 +79,7 @@ OPTIONS
79 - parent: name of function matched to the parent regex filter. Unmatched 79 - parent: name of function matched to the parent regex filter. Unmatched
80 entries are displayed as "[other]". 80 entries are displayed as "[other]".
81 - cpu: cpu number the task ran at the time of sample 81 - cpu: cpu number the task ran at the time of sample
82 - socket: processor socket number the task ran at the time of sample
82 - srcline: filename and line number executed at the time of sample. The 83 - srcline: filename and line number executed at the time of sample. The
83 DWARF debugging info must be provided. 84 DWARF debugging info must be provided.
84 - srcfile: file name of the source file of the same. Requires dwarf 85 - srcfile: file name of the source file of the same. Requires dwarf
@@ -168,30 +169,40 @@ OPTIONS
168--dump-raw-trace:: 169--dump-raw-trace::
169 Dump raw trace in ASCII. 170 Dump raw trace in ASCII.
170 171
171-g [type,min[,limit],order[,key][,branch]]:: 172-g::
172--call-graph:: 173--call-graph=<print_type,threshold[,print_limit],order,sort_key,branch>::
173 Display call chains using type, min percent threshold, optional print 174 Display call chains using type, min percent threshold, print limit,
174 limit and order. 175 call order, sort key and branch. Note that ordering of parameters is not
175 type can be either: 176 fixed so any parement can be given in an arbitraty order. One exception
177 is the print_limit which should be preceded by threshold.
178
179 print_type can be either:
176 - flat: single column, linear exposure of call chains. 180 - flat: single column, linear exposure of call chains.
177 - graph: use a graph tree, displaying absolute overhead rates. 181 - graph: use a graph tree, displaying absolute overhead rates. (default)
178 - fractal: like graph, but displays relative rates. Each branch of 182 - fractal: like graph, but displays relative rates. Each branch of
179 the tree is considered as a new profiled object. + 183 the tree is considered as a new profiled object.
184 - none: disable call chain display.
185
186 threshold is a percentage value which specifies a minimum percent to be
187 included in the output call graph. Default is 0.5 (%).
188
189 print_limit is only applied when stdio interface is used. It's to limit
190 number of call graph entries in a single hist entry. Note that it needs
191 to be given after threshold (but not necessarily consecutive).
192 Default is 0 (unlimited).
180 193
181 order can be either: 194 order can be either:
182 - callee: callee based call graph. 195 - callee: callee based call graph.
183 - caller: inverted caller based call graph. 196 - caller: inverted caller based call graph.
197 Default is 'caller' when --children is used, otherwise 'callee'.
184 198
185 key can be: 199 sort_key can be:
186 - function: compare on functions 200 - function: compare on functions (default)
187 - address: compare on individual code addresses 201 - address: compare on individual code addresses
188 202
189 branch can be: 203 branch can be:
190 - branch: include last branch information in callgraph 204 - branch: include last branch information in callgraph when available.
191 when available. Usually more convenient to use --branch-history 205 Usually more convenient to use --branch-history for this.
192 for this.
193
194 Default: fractal,0.5,callee,function.
195 206
196--children:: 207--children::
197 Accumulate callchain of children to parent entry so that then can 208 Accumulate callchain of children to parent entry so that then can
@@ -204,6 +215,8 @@ OPTIONS
204 beyond the specified depth will be ignored. This is a trade-off 215 beyond the specified depth will be ignored. This is a trade-off
205 between information loss and faster processing especially for 216 between information loss and faster processing especially for
206 workloads that can have a very long callchain stack. 217 workloads that can have a very long callchain stack.
218 Note that when using the --itrace option the synthesized callchain size
219 will override this value if the synthesized callchain size is bigger.
207 220
208 Default: 127 221 Default: 127
209 222
@@ -349,6 +362,9 @@ include::itrace.txt[]
349 This option extends the perf report to show reference callgraphs, 362 This option extends the perf report to show reference callgraphs,
350 which collected by reference event, in no callgraph event. 363 which collected by reference event, in no callgraph event.
351 364
365--socket-filter::
366 Only report the samples on the processor socket that match with this filter
367
352include::callchain-overhead-calculation.txt[] 368include::callchain-overhead-calculation.txt[]
353 369
354SEE ALSO 370SEE ALSO
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index dc3ec783b7bd..382ddfb45d1d 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -112,11 +112,11 @@ OPTIONS
112--debug-mode:: 112--debug-mode::
113 Do various checks like samples ordering and lost events. 113 Do various checks like samples ordering and lost events.
114 114
115-f:: 115-F::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
119 srcline, period, iregs, flags. 119 srcline, period, iregs, brstack, brstacksym, flags.
120 Field list can be prepended with the type, trace, sw or hw, 120 Field list can be prepended with the type, trace, sw or hw,
121 to indicate to which event type the field list applies. 121 to indicate to which event type the field list applies.
122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -175,6 +175,16 @@ OPTIONS
175 Finally, a user may not set fields to none for all event types. 175 Finally, a user may not set fields to none for all event types.
176 i.e., -f "" is not allowed. 176 i.e., -f "" is not allowed.
177 177
178 The brstack output includes branch related information with raw addresses using the
179 /v/v/v/v/ syntax in the following order:
180 FROM: branch source instruction
181 TO : branch target instruction
182 M/P/-: M=branch target mispredicted or branch direction was mispredicted, P=target predicted or direction predicted, -=not supported
183 X/- : X=branch inside a transactional region, -=not in transaction region or not supported
184 A/- : A=TSX abort entry, -=not aborted region or not supported
185
186 The brstacksym is identical to brstack, except that the FROM and TO addresses are printed in a symbolic form if possible.
187
178-k:: 188-k::
179--vmlinux=<file>:: 189--vmlinux=<file>::
180 vmlinux pathname 190 vmlinux pathname
@@ -249,6 +259,9 @@ include::itrace.txt[]
249--full-source-path:: 259--full-source-path::
250 Show the full path for source files for srcline output. 260 Show the full path for source files for srcline output.
251 261
262--ns::
263 Use 9 decimal places when displaying time (i.e. show the nanoseconds)
264
252SEE ALSO 265SEE ALSO
253-------- 266--------
254linkperf:perf-record[1], linkperf:perf-script-perl[1], 267linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 47469abdcc1c..4e074a660826 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -128,8 +128,9 @@ perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' -- m
128 128
129-I msecs:: 129-I msecs::
130--interval-print msecs:: 130--interval-print msecs::
131 Print count deltas every N milliseconds (minimum: 100ms) 131Print count deltas every N milliseconds (minimum: 10ms)
132 example: perf stat -I 1000 -e cycles -a sleep 5 132The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution.
133 example: 'perf stat -I 1000 -e cycles -a sleep 5'
133 134
134--per-socket:: 135--per-socket::
135Aggregate counts per processor socket for system-wide mode measurements. This 136Aggregate counts per processor socket for system-wide mode measurements. This
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index f6a23eb294e7..556cec09bf50 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -160,9 +160,10 @@ Default is to monitor all CPUS.
160-g:: 160-g::
161 Enables call-graph (stack chain/backtrace) recording. 161 Enables call-graph (stack chain/backtrace) recording.
162 162
163--call-graph:: 163--call-graph [mode,type,min[,limit],order[,key][,branch]]::
164 Setup and enable call-graph (stack chain/backtrace) recording, 164 Setup and enable call-graph (stack chain/backtrace) recording,
165 implies -g. 165 implies -g. See `--call-graph` section in perf-record and
166 perf-report man pages for details.
166 167
167--children:: 168--children::
168 Accumulate callchain of children to parent entry so that then can 169 Accumulate callchain of children to parent entry so that then can
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 7ea078658a87..13293de8869f 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -62,7 +62,6 @@ OPTIONS
62--verbose=:: 62--verbose=::
63 Verbosity level. 63 Verbosity level.
64 64
65-i::
66--no-inherit:: 65--no-inherit::
67 Child tasks do not inherit counters. 66 Child tasks do not inherit counters.
68 67
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt
index 2b131776363e..864e37597252 100644
--- a/tools/perf/Documentation/perf.txt
+++ b/tools/perf/Documentation/perf.txt
@@ -27,6 +27,14 @@ OPTIONS
27 Setup buildid cache directory. It has higher priority than 27 Setup buildid cache directory. It has higher priority than
28 buildid.dir config file option. 28 buildid.dir config file option.
29 29
30-v::
31--version::
32 Display perf version.
33
34-h::
35--help::
36 Run perf help command.
37
30DESCRIPTION 38DESCRIPTION
31----------- 39-----------
32Performance counters for Linux are a new kernel-based subsystem 40Performance counters for Linux are a new kernel-based subsystem
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index af009bd6e6b7..39c38cb45b00 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -17,6 +17,7 @@ tools/build
17tools/arch/x86/include/asm/atomic.h 17tools/arch/x86/include/asm/atomic.h
18tools/arch/x86/include/asm/rmwcc.h 18tools/arch/x86/include/asm/rmwcc.h
19tools/lib/traceevent 19tools/lib/traceevent
20tools/lib/bpf
20tools/lib/api 21tools/lib/api
21tools/lib/bpf 22tools/lib/bpf
22tools/lib/hweight.c 23tools/lib/hweight.c
@@ -41,6 +42,7 @@ tools/include/asm-generic/bitops.h
41tools/include/linux/atomic.h 42tools/include/linux/atomic.h
42tools/include/linux/bitops.h 43tools/include/linux/bitops.h
43tools/include/linux/compiler.h 44tools/include/linux/compiler.h
45tools/include/linux/filter.h
44tools/include/linux/hash.h 46tools/include/linux/hash.h
45tools/include/linux/kernel.h 47tools/include/linux/kernel.h
46tools/include/linux/list.h 48tools/include/linux/list.h
@@ -49,6 +51,7 @@ tools/include/linux/poison.h
49tools/include/linux/rbtree.h 51tools/include/linux/rbtree.h
50tools/include/linux/rbtree_augmented.h 52tools/include/linux/rbtree_augmented.h
51tools/include/linux/types.h 53tools/include/linux/types.h
54tools/include/linux/err.h
52include/asm-generic/bitops/arch_hweight.h 55include/asm-generic/bitops/arch_hweight.h
53include/asm-generic/bitops/const_hweight.h 56include/asm-generic/bitops/const_hweight.h
54include/asm-generic/bitops/fls64.h 57include/asm-generic/bitops/fls64.h
@@ -67,6 +70,8 @@ arch/*/lib/memset*.S
67include/linux/poison.h 70include/linux/poison.h
68include/linux/hw_breakpoint.h 71include/linux/hw_breakpoint.h
69include/uapi/linux/perf_event.h 72include/uapi/linux/perf_event.h
73include/uapi/linux/bpf.h
74include/uapi/linux/bpf_common.h
70include/uapi/linux/const.h 75include/uapi/linux/const.h
71include/uapi/linux/swab.h 76include/uapi/linux/swab.h
72include/uapi/linux/hw_breakpoint.h 77include/uapi/linux/hw_breakpoint.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 480546d5f13b..dcd9a70c7193 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -78,7 +78,7 @@ clean:
78# The build-test target is not really parallel, don't print the jobs info: 78# The build-test target is not really parallel, don't print the jobs info:
79# 79#
80build-test: 80build-test:
81 @$(MAKE) -f tests/make --no-print-directory 81 @$(MAKE) SHUF=1 -f tests/make --no-print-directory
82 82
83# 83#
84# All other targets get passed through: 84# All other targets get passed through:
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d9863cb96f59..0d19d5447d6c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -75,6 +75,8 @@ include config/utilities.mak
75# Define NO_LZMA if you do not want to support compressed (xz) kernel modules 75# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
76# 76#
77# Define NO_AUXTRACE if you do not want AUX area tracing support 77# Define NO_AUXTRACE if you do not want AUX area tracing support
78#
79# Define NO_LIBBPF if you do not want BPF support
78 80
79# As per kernel Makefile, avoid funny character set dependencies 81# As per kernel Makefile, avoid funny character set dependencies
80unexport LC_ALL 82unexport LC_ALL
@@ -145,6 +147,7 @@ AWK = awk
145 147
146LIB_DIR = $(srctree)/tools/lib/api/ 148LIB_DIR = $(srctree)/tools/lib/api/
147TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ 149TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
150BPF_DIR = $(srctree)/tools/lib/bpf/
148 151
149# include config/Makefile by default and rule out 152# include config/Makefile by default and rule out
150# non-config cases 153# non-config cases
@@ -180,6 +183,7 @@ strip-libs = $(filter-out -l%,$(1))
180 183
181ifneq ($(OUTPUT),) 184ifneq ($(OUTPUT),)
182 TE_PATH=$(OUTPUT) 185 TE_PATH=$(OUTPUT)
186 BPF_PATH=$(OUTPUT)
183ifneq ($(subdir),) 187ifneq ($(subdir),)
184 LIB_PATH=$(OUTPUT)/../lib/api/ 188 LIB_PATH=$(OUTPUT)/../lib/api/
185else 189else
@@ -188,6 +192,7 @@ endif
188else 192else
189 TE_PATH=$(TRACE_EVENT_DIR) 193 TE_PATH=$(TRACE_EVENT_DIR)
190 LIB_PATH=$(LIB_DIR) 194 LIB_PATH=$(LIB_DIR)
195 BPF_PATH=$(BPF_DIR)
191endif 196endif
192 197
193LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 198LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
@@ -199,6 +204,8 @@ LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYN
199LIBAPI = $(LIB_PATH)libapi.a 204LIBAPI = $(LIB_PATH)libapi.a
200export LIBAPI 205export LIBAPI
201 206
207LIBBPF = $(BPF_PATH)libbpf.a
208
202# python extension build directories 209# python extension build directories
203PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ 210PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
204PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ 211PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
@@ -251,6 +258,9 @@ export PERL_PATH
251LIB_FILE=$(OUTPUT)libperf.a 258LIB_FILE=$(OUTPUT)libperf.a
252 259
253PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT) 260PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT)
261ifndef NO_LIBBPF
262 PERFLIBS += $(LIBBPF)
263endif
254 264
255# We choose to avoid "if .. else if .. else .. endif endif" 265# We choose to avoid "if .. else if .. else .. endif endif"
256# because maintaining the nesting to match is a pain. If 266# because maintaining the nesting to match is a pain. If
@@ -297,16 +307,16 @@ strip: $(PROGRAMS) $(OUTPUT)perf
297PERF_IN := $(OUTPUT)perf-in.o 307PERF_IN := $(OUTPUT)perf-in.o
298 308
299export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK 309export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
300build := -f $(srctree)/tools/build/Makefile.build dir=. obj 310include $(srctree)/tools/build/Makefile.include
301 311
302$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE 312$(PERF_IN): prepare FORCE
303 $(Q)$(MAKE) $(build)=perf 313 $(Q)$(MAKE) $(build)=perf
304 314
305$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) 315$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
306 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \ 316 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
307 $(PERF_IN) $(LIBS) -o $@ 317 $(PERF_IN) $(LIBS) -o $@
308 318
309$(GTK_IN): FORCE 319$(GTK_IN): fixdep FORCE
310 $(Q)$(MAKE) $(build)=gtk 320 $(Q)$(MAKE) $(build)=gtk
311 321
312$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS) 322$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS)
@@ -349,27 +359,27 @@ endif
349__build-dir = $(subst $(OUTPUT),,$(dir $@)) 359__build-dir = $(subst $(OUTPUT),,$(dir $@))
350build-dir = $(if $(__build-dir),$(__build-dir),.) 360build-dir = $(if $(__build-dir),$(__build-dir),.)
351 361
352single_dep: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h 362prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep
353 363
354$(OUTPUT)%.o: %.c single_dep FORCE 364$(OUTPUT)%.o: %.c prepare FORCE
355 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 365 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
356 366
357$(OUTPUT)%.i: %.c single_dep FORCE 367$(OUTPUT)%.i: %.c prepare FORCE
358 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 368 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
359 369
360$(OUTPUT)%.s: %.c single_dep FORCE 370$(OUTPUT)%.s: %.c prepare FORCE
361 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 371 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
362 372
363$(OUTPUT)%-bison.o: %.c single_dep FORCE 373$(OUTPUT)%-bison.o: %.c prepare FORCE
364 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 374 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
365 375
366$(OUTPUT)%-flex.o: %.c single_dep FORCE 376$(OUTPUT)%-flex.o: %.c prepare FORCE
367 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 377 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
368 378
369$(OUTPUT)%.o: %.S single_dep FORCE 379$(OUTPUT)%.o: %.S prepare FORCE
370 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 380 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
371 381
372$(OUTPUT)%.i: %.S single_dep FORCE 382$(OUTPUT)%.i: %.S prepare FORCE
373 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 383 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
374 384
375$(OUTPUT)perf-%: %.o $(PERFLIBS) 385$(OUTPUT)perf-%: %.o $(PERFLIBS)
@@ -389,7 +399,7 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
389 399
390LIBPERF_IN := $(OUTPUT)libperf-in.o 400LIBPERF_IN := $(OUTPUT)libperf-in.o
391 401
392$(LIBPERF_IN): FORCE 402$(LIBPERF_IN): fixdep FORCE
393 $(Q)$(MAKE) $(build)=libperf 403 $(Q)$(MAKE) $(build)=libperf
394 404
395$(LIB_FILE): $(LIBPERF_IN) 405$(LIB_FILE): $(LIBPERF_IN)
@@ -397,10 +407,10 @@ $(LIB_FILE): $(LIBPERF_IN)
397 407
398LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 408LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
399 409
400$(LIBTRACEEVENT): FORCE 410$(LIBTRACEEVENT): fixdep FORCE
401 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a 411 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a
402 412
403libtraceevent_plugins: FORCE 413libtraceevent_plugins: fixdep FORCE
404 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins 414 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins
405 415
406$(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins 416$(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins
@@ -413,13 +423,20 @@ $(LIBTRACEEVENT)-clean:
413install-traceevent-plugins: $(LIBTRACEEVENT) 423install-traceevent-plugins: $(LIBTRACEEVENT)
414 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins 424 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins
415 425
416$(LIBAPI): FORCE 426$(LIBAPI): fixdep FORCE
417 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a 427 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a
418 428
419$(LIBAPI)-clean: 429$(LIBAPI)-clean:
420 $(call QUIET_CLEAN, libapi) 430 $(call QUIET_CLEAN, libapi)
421 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null 431 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
422 432
433$(LIBBPF): fixdep FORCE
434 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a
435
436$(LIBBPF)-clean:
437 $(call QUIET_CLEAN, libbpf)
438 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null
439
423help: 440help:
424 @echo 'Perf make targets:' 441 @echo 'Perf make targets:'
425 @echo ' doc - make *all* documentation (see below)' 442 @echo ' doc - make *all* documentation (see below)'
@@ -459,7 +476,7 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
459$(DOC_TARGETS): 476$(DOC_TARGETS):
460 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all) 477 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
461 478
462TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol 479TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include ../lib/bpf
463TAG_FILES= ../../include/uapi/linux/perf_event.h 480TAG_FILES= ../../include/uapi/linux/perf_event.h
464 481
465TAGS: 482TAGS:
@@ -567,7 +584,7 @@ config-clean:
567 $(call QUIET_CLEAN, config) 584 $(call QUIET_CLEAN, config)
568 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null 585 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
569 586
570clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean 587clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean config-clean
571 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) 588 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
572 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 589 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
573 $(Q)$(RM) $(OUTPUT).config-detected 590 $(Q)$(RM) $(OUTPUT).config-detected
@@ -591,6 +608,6 @@ FORCE:
591 608
592.PHONY: all install clean config-clean strip install-gtk 609.PHONY: all install clean config-clean strip install-gtk
593.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 610.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
594.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep 611.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare
595.PHONY: libtraceevent_plugins 612.PHONY: libtraceevent_plugins
596 613
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index b00dfd92ea73..e83c8ce24303 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -128,9 +128,8 @@ static const char *normalize_arch(char *arch)
128 return arch; 128 return arch;
129} 129}
130 130
131static int perf_session_env__lookup_binutils_path(struct perf_env *env, 131static int perf_env__lookup_binutils_path(struct perf_env *env,
132 const char *name, 132 const char *name, const char **path)
133 const char **path)
134{ 133{
135 int idx; 134 int idx;
136 const char *arch, *cross_env; 135 const char *arch, *cross_env;
@@ -206,7 +205,7 @@ out_error:
206 return -1; 205 return -1;
207} 206}
208 207
209int perf_session_env__lookup_objdump(struct perf_env *env) 208int perf_env__lookup_objdump(struct perf_env *env)
210{ 209{
211 /* 210 /*
212 * For live mode, env->arch will be NULL and we can use 211 * For live mode, env->arch will be NULL and we can use
@@ -215,6 +214,5 @@ int perf_session_env__lookup_objdump(struct perf_env *env)
215 if (env->arch == NULL) 214 if (env->arch == NULL)
216 return 0; 215 return 0;
217 216
218 return perf_session_env__lookup_binutils_path(env, "objdump", 217 return perf_env__lookup_binutils_path(env, "objdump", &objdump_path);
219 &objdump_path);
220} 218}
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
index 20176df69fc8..7529cfb143ce 100644
--- a/tools/perf/arch/common.h
+++ b/tools/perf/arch/common.h
@@ -1,10 +1,10 @@
1#ifndef ARCH_PERF_COMMON_H 1#ifndef ARCH_PERF_COMMON_H
2#define ARCH_PERF_COMMON_H 2#define ARCH_PERF_COMMON_H
3 3
4#include "../util/session.h" 4#include "../util/env.h"
5 5
6extern const char *objdump_path; 6extern const char *objdump_path;
7 7
8int perf_session_env__lookup_objdump(struct perf_env *env); 8int perf_env__lookup_objdump(struct perf_env *env);
9 9
10#endif /* ARCH_PERF_COMMON_H */ 10#endif /* ARCH_PERF_COMMON_H */
diff --git a/tools/perf/arch/x86/Build b/tools/perf/arch/x86/Build
index 41bf61da476a..db52fa22d3a1 100644
--- a/tools/perf/arch/x86/Build
+++ b/tools/perf/arch/x86/Build
@@ -1,2 +1,2 @@
1libperf-y += util/ 1libperf-y += util/
2libperf-$(CONFIG_DWARF_UNWIND) += tests/ 2libperf-y += tests/
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 21322e0385b8..09ba923debe8 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -2,3 +2,4 @@ ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3endif 3endif
4HAVE_KVM_STAT_SUPPORT := 1 4HAVE_KVM_STAT_SUPPORT := 1
5PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h
new file mode 100644
index 000000000000..7ed00f4b0908
--- /dev/null
+++ b/tools/perf/arch/x86/include/arch-tests.h
@@ -0,0 +1,19 @@
1#ifndef ARCH_TESTS_H
2#define ARCH_TESTS_H
3
4/* Tests */
5int test__rdpmc(void);
6int test__perf_time_to_tsc(void);
7int test__insn_x86(void);
8int test__intel_cqm_count_nmi_context(void);
9
10#ifdef HAVE_DWARF_UNWIND_SUPPORT
11struct thread;
12struct perf_sample;
13int test__arch_unwind_sample(struct perf_sample *sample,
14 struct thread *thread);
15#endif
16
17extern struct test arch_tests[];
18
19#endif
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build
index b30eff9bcc83..cbb7e978166b 100644
--- a/tools/perf/arch/x86/tests/Build
+++ b/tools/perf/arch/x86/tests/Build
@@ -1,2 +1,8 @@
1libperf-y += regs_load.o 1libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o
2libperf-y += dwarf-unwind.o 2libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
3
4libperf-y += arch-tests.o
5libperf-y += rdpmc.o
6libperf-y += perf-time-to-tsc.o
7libperf-$(CONFIG_AUXTRACE) += insn-x86.o
8libperf-y += intel-cqm.o
diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c
new file mode 100644
index 000000000000..2218cb64f840
--- /dev/null
+++ b/tools/perf/arch/x86/tests/arch-tests.c
@@ -0,0 +1,34 @@
1#include <string.h>
2#include "tests/tests.h"
3#include "arch-tests.h"
4
5struct test arch_tests[] = {
6 {
7 .desc = "x86 rdpmc test",
8 .func = test__rdpmc,
9 },
10 {
11 .desc = "Test converting perf time to TSC",
12 .func = test__perf_time_to_tsc,
13 },
14#ifdef HAVE_DWARF_UNWIND_SUPPORT
15 {
16 .desc = "Test dwarf unwind",
17 .func = test__dwarf_unwind,
18 },
19#endif
20#ifdef HAVE_AUXTRACE_SUPPORT
21 {
22 .desc = "Test x86 instruction decoder - new instructions",
23 .func = test__insn_x86,
24 },
25#endif
26 {
27 .desc = "Test intel cqm nmi context read",
28 .func = test__intel_cqm_count_nmi_context,
29 },
30 {
31 .func = NULL,
32 },
33
34};
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c
index d8bbf7ad1681..7f209ce827bf 100644
--- a/tools/perf/arch/x86/tests/dwarf-unwind.c
+++ b/tools/perf/arch/x86/tests/dwarf-unwind.c
@@ -5,6 +5,7 @@
5#include "event.h" 5#include "event.h"
6#include "debug.h" 6#include "debug.h"
7#include "tests/tests.h" 7#include "tests/tests.h"
8#include "arch-tests.h"
8 9
9#define STACK_SIZE 8192 10#define STACK_SIZE 8192
10 11
diff --git a/tools/perf/arch/x86/tests/gen-insn-x86-dat.awk b/tools/perf/arch/x86/tests/gen-insn-x86-dat.awk
new file mode 100644
index 000000000000..a21454835cd4
--- /dev/null
+++ b/tools/perf/arch/x86/tests/gen-insn-x86-dat.awk
@@ -0,0 +1,75 @@
1#!/bin/awk -f
2# gen-insn-x86-dat.awk: script to convert data for the insn-x86 test
3# Copyright (c) 2015, Intel Corporation.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms and conditions of the GNU General Public License,
7# version 2, as published by the Free Software Foundation.
8#
9# This program is distributed in the hope it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details.
13
14BEGIN {
15 print "/*"
16 print " * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk"
17 print " * from insn-x86-dat-src.c for inclusion by insn-x86.c"
18 print " * Do not change this code."
19 print "*/\n"
20 op = ""
21 branch = ""
22 rel = 0
23 going = 0
24}
25
26/ Start here / {
27 going = 1
28}
29
30/ Stop here / {
31 going = 0
32}
33
34/^\s*[0-9a-fA-F]+\:/ {
35 if (going) {
36 colon_pos = index($0, ":")
37 useful_line = substr($0, colon_pos + 1)
38 first_pos = match(useful_line, "[0-9a-fA-F]")
39 useful_line = substr(useful_line, first_pos)
40 gsub("\t", "\\t", useful_line)
41 printf "{{"
42 len = 0
43 for (i = 2; i <= NF; i++) {
44 if (match($i, "^[0-9a-fA-F][0-9a-fA-F]$")) {
45 printf "0x%s, ", $i
46 len += 1
47 } else {
48 break
49 }
50 }
51 printf "}, %d, %s, \"%s\", \"%s\",", len, rel, op, branch
52 printf "\n\"%s\",},\n", useful_line
53 op = ""
54 branch = ""
55 rel = 0
56 }
57}
58
59/ Expecting: / {
60 expecting_str = " Expecting: "
61 expecting_len = length(expecting_str)
62 expecting_pos = index($0, expecting_str)
63 useful_line = substr($0, expecting_pos + expecting_len)
64 for (i = 1; i <= NF; i++) {
65 if ($i == "Expecting:") {
66 i++
67 op = $i
68 i++
69 branch = $i
70 i++
71 rel = $i
72 break
73 }
74 }
75}
diff --git a/tools/perf/arch/x86/tests/gen-insn-x86-dat.sh b/tools/perf/arch/x86/tests/gen-insn-x86-dat.sh
new file mode 100755
index 000000000000..2d4ef94cff98
--- /dev/null
+++ b/tools/perf/arch/x86/tests/gen-insn-x86-dat.sh
@@ -0,0 +1,43 @@
1#!/bin/sh
2# gen-insn-x86-dat: generate data for the insn-x86 test
3# Copyright (c) 2015, Intel Corporation.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms and conditions of the GNU General Public License,
7# version 2, as published by the Free Software Foundation.
8#
9# This program is distributed in the hope it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details.
13
14set -e
15
16if [ "$(uname -m)" != "x86_64" ]; then
17 echo "ERROR: This script only works on x86_64"
18 exit 1
19fi
20
21cd $(dirname $0)
22
23trap 'echo "Might need a more recent version of binutils"' EXIT
24
25echo "Compiling insn-x86-dat-src.c to 64-bit object"
26
27gcc -g -c insn-x86-dat-src.c
28
29objdump -dSw insn-x86-dat-src.o | awk -f gen-insn-x86-dat.awk > insn-x86-dat-64.c
30
31rm -f insn-x86-dat-src.o
32
33echo "Compiling insn-x86-dat-src.c to 32-bit object"
34
35gcc -g -c -m32 insn-x86-dat-src.c
36
37objdump -dSw insn-x86-dat-src.o | awk -f gen-insn-x86-dat.awk > insn-x86-dat-32.c
38
39rm -f insn-x86-dat-src.o
40
41trap - EXIT
42
43echo "Done (use git diff to see the changes)"
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-32.c b/tools/perf/arch/x86/tests/insn-x86-dat-32.c
new file mode 100644
index 000000000000..3b491cfe204e
--- /dev/null
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-32.c
@@ -0,0 +1,658 @@
1/*
2 * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk
3 * from insn-x86-dat-src.c for inclusion by insn-x86.c
4 * Do not change this code.
5*/
6
7{{0x0f, 0x31, }, 2, 0, "", "",
8"0f 31 \trdtsc ",},
9{{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "",
10"f3 0f 1b 00 \tbndmk (%eax),%bnd0",},
11{{0xf3, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
12"f3 0f 1b 05 78 56 34 12 \tbndmk 0x12345678,%bnd0",},
13{{0xf3, 0x0f, 0x1b, 0x18, }, 4, 0, "", "",
14"f3 0f 1b 18 \tbndmk (%eax),%bnd3",},
15{{0xf3, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "",
16"f3 0f 1b 04 01 \tbndmk (%ecx,%eax,1),%bnd0",},
17{{0xf3, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
18"f3 0f 1b 04 05 78 56 34 12 \tbndmk 0x12345678(,%eax,1),%bnd0",},
19{{0xf3, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "",
20"f3 0f 1b 04 08 \tbndmk (%eax,%ecx,1),%bnd0",},
21{{0xf3, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "",
22"f3 0f 1b 04 c8 \tbndmk (%eax,%ecx,8),%bnd0",},
23{{0xf3, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "",
24"f3 0f 1b 40 12 \tbndmk 0x12(%eax),%bnd0",},
25{{0xf3, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "",
26"f3 0f 1b 45 12 \tbndmk 0x12(%ebp),%bnd0",},
27{{0xf3, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "",
28"f3 0f 1b 44 01 12 \tbndmk 0x12(%ecx,%eax,1),%bnd0",},
29{{0xf3, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "",
30"f3 0f 1b 44 05 12 \tbndmk 0x12(%ebp,%eax,1),%bnd0",},
31{{0xf3, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "",
32"f3 0f 1b 44 08 12 \tbndmk 0x12(%eax,%ecx,1),%bnd0",},
33{{0xf3, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
34"f3 0f 1b 44 c8 12 \tbndmk 0x12(%eax,%ecx,8),%bnd0",},
35{{0xf3, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
36"f3 0f 1b 80 78 56 34 12 \tbndmk 0x12345678(%eax),%bnd0",},
37{{0xf3, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
38"f3 0f 1b 85 78 56 34 12 \tbndmk 0x12345678(%ebp),%bnd0",},
39{{0xf3, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
40"f3 0f 1b 84 01 78 56 34 12 \tbndmk 0x12345678(%ecx,%eax,1),%bnd0",},
41{{0xf3, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
42"f3 0f 1b 84 05 78 56 34 12 \tbndmk 0x12345678(%ebp,%eax,1),%bnd0",},
43{{0xf3, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
44"f3 0f 1b 84 08 78 56 34 12 \tbndmk 0x12345678(%eax,%ecx,1),%bnd0",},
45{{0xf3, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
46"f3 0f 1b 84 c8 78 56 34 12 \tbndmk 0x12345678(%eax,%ecx,8),%bnd0",},
47{{0xf3, 0x0f, 0x1a, 0x00, }, 4, 0, "", "",
48"f3 0f 1a 00 \tbndcl (%eax),%bnd0",},
49{{0xf3, 0x0f, 0x1a, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
50"f3 0f 1a 05 78 56 34 12 \tbndcl 0x12345678,%bnd0",},
51{{0xf3, 0x0f, 0x1a, 0x18, }, 4, 0, "", "",
52"f3 0f 1a 18 \tbndcl (%eax),%bnd3",},
53{{0xf3, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "",
54"f3 0f 1a 04 01 \tbndcl (%ecx,%eax,1),%bnd0",},
55{{0xf3, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
56"f3 0f 1a 04 05 78 56 34 12 \tbndcl 0x12345678(,%eax,1),%bnd0",},
57{{0xf3, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "",
58"f3 0f 1a 04 08 \tbndcl (%eax,%ecx,1),%bnd0",},
59{{0xf3, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "",
60"f3 0f 1a 04 c8 \tbndcl (%eax,%ecx,8),%bnd0",},
61{{0xf3, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "",
62"f3 0f 1a 40 12 \tbndcl 0x12(%eax),%bnd0",},
63{{0xf3, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "",
64"f3 0f 1a 45 12 \tbndcl 0x12(%ebp),%bnd0",},
65{{0xf3, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "",
66"f3 0f 1a 44 01 12 \tbndcl 0x12(%ecx,%eax,1),%bnd0",},
67{{0xf3, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "",
68"f3 0f 1a 44 05 12 \tbndcl 0x12(%ebp,%eax,1),%bnd0",},
69{{0xf3, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "",
70"f3 0f 1a 44 08 12 \tbndcl 0x12(%eax,%ecx,1),%bnd0",},
71{{0xf3, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
72"f3 0f 1a 44 c8 12 \tbndcl 0x12(%eax,%ecx,8),%bnd0",},
73{{0xf3, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
74"f3 0f 1a 80 78 56 34 12 \tbndcl 0x12345678(%eax),%bnd0",},
75{{0xf3, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
76"f3 0f 1a 85 78 56 34 12 \tbndcl 0x12345678(%ebp),%bnd0",},
77{{0xf3, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
78"f3 0f 1a 84 01 78 56 34 12 \tbndcl 0x12345678(%ecx,%eax,1),%bnd0",},
79{{0xf3, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
80"f3 0f 1a 84 05 78 56 34 12 \tbndcl 0x12345678(%ebp,%eax,1),%bnd0",},
81{{0xf3, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
82"f3 0f 1a 84 08 78 56 34 12 \tbndcl 0x12345678(%eax,%ecx,1),%bnd0",},
83{{0xf3, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
84"f3 0f 1a 84 c8 78 56 34 12 \tbndcl 0x12345678(%eax,%ecx,8),%bnd0",},
85{{0xf3, 0x0f, 0x1a, 0xc0, }, 4, 0, "", "",
86"f3 0f 1a c0 \tbndcl %eax,%bnd0",},
87{{0xf2, 0x0f, 0x1a, 0x00, }, 4, 0, "", "",
88"f2 0f 1a 00 \tbndcu (%eax),%bnd0",},
89{{0xf2, 0x0f, 0x1a, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
90"f2 0f 1a 05 78 56 34 12 \tbndcu 0x12345678,%bnd0",},
91{{0xf2, 0x0f, 0x1a, 0x18, }, 4, 0, "", "",
92"f2 0f 1a 18 \tbndcu (%eax),%bnd3",},
93{{0xf2, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "",
94"f2 0f 1a 04 01 \tbndcu (%ecx,%eax,1),%bnd0",},
95{{0xf2, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
96"f2 0f 1a 04 05 78 56 34 12 \tbndcu 0x12345678(,%eax,1),%bnd0",},
97{{0xf2, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "",
98"f2 0f 1a 04 08 \tbndcu (%eax,%ecx,1),%bnd0",},
99{{0xf2, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "",
100"f2 0f 1a 04 c8 \tbndcu (%eax,%ecx,8),%bnd0",},
101{{0xf2, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "",
102"f2 0f 1a 40 12 \tbndcu 0x12(%eax),%bnd0",},
103{{0xf2, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "",
104"f2 0f 1a 45 12 \tbndcu 0x12(%ebp),%bnd0",},
105{{0xf2, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "",
106"f2 0f 1a 44 01 12 \tbndcu 0x12(%ecx,%eax,1),%bnd0",},
107{{0xf2, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "",
108"f2 0f 1a 44 05 12 \tbndcu 0x12(%ebp,%eax,1),%bnd0",},
109{{0xf2, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "",
110"f2 0f 1a 44 08 12 \tbndcu 0x12(%eax,%ecx,1),%bnd0",},
111{{0xf2, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
112"f2 0f 1a 44 c8 12 \tbndcu 0x12(%eax,%ecx,8),%bnd0",},
113{{0xf2, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
114"f2 0f 1a 80 78 56 34 12 \tbndcu 0x12345678(%eax),%bnd0",},
115{{0xf2, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
116"f2 0f 1a 85 78 56 34 12 \tbndcu 0x12345678(%ebp),%bnd0",},
117{{0xf2, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
118"f2 0f 1a 84 01 78 56 34 12 \tbndcu 0x12345678(%ecx,%eax,1),%bnd0",},
119{{0xf2, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
120"f2 0f 1a 84 05 78 56 34 12 \tbndcu 0x12345678(%ebp,%eax,1),%bnd0",},
121{{0xf2, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
122"f2 0f 1a 84 08 78 56 34 12 \tbndcu 0x12345678(%eax,%ecx,1),%bnd0",},
123{{0xf2, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
124"f2 0f 1a 84 c8 78 56 34 12 \tbndcu 0x12345678(%eax,%ecx,8),%bnd0",},
125{{0xf2, 0x0f, 0x1a, 0xc0, }, 4, 0, "", "",
126"f2 0f 1a c0 \tbndcu %eax,%bnd0",},
127{{0xf2, 0x0f, 0x1b, 0x00, }, 4, 0, "", "",
128"f2 0f 1b 00 \tbndcn (%eax),%bnd0",},
129{{0xf2, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
130"f2 0f 1b 05 78 56 34 12 \tbndcn 0x12345678,%bnd0",},
131{{0xf2, 0x0f, 0x1b, 0x18, }, 4, 0, "", "",
132"f2 0f 1b 18 \tbndcn (%eax),%bnd3",},
133{{0xf2, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "",
134"f2 0f 1b 04 01 \tbndcn (%ecx,%eax,1),%bnd0",},
135{{0xf2, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
136"f2 0f 1b 04 05 78 56 34 12 \tbndcn 0x12345678(,%eax,1),%bnd0",},
137{{0xf2, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "",
138"f2 0f 1b 04 08 \tbndcn (%eax,%ecx,1),%bnd0",},
139{{0xf2, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "",
140"f2 0f 1b 04 c8 \tbndcn (%eax,%ecx,8),%bnd0",},
141{{0xf2, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "",
142"f2 0f 1b 40 12 \tbndcn 0x12(%eax),%bnd0",},
143{{0xf2, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "",
144"f2 0f 1b 45 12 \tbndcn 0x12(%ebp),%bnd0",},
145{{0xf2, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "",
146"f2 0f 1b 44 01 12 \tbndcn 0x12(%ecx,%eax,1),%bnd0",},
147{{0xf2, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "",
148"f2 0f 1b 44 05 12 \tbndcn 0x12(%ebp,%eax,1),%bnd0",},
149{{0xf2, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "",
150"f2 0f 1b 44 08 12 \tbndcn 0x12(%eax,%ecx,1),%bnd0",},
151{{0xf2, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
152"f2 0f 1b 44 c8 12 \tbndcn 0x12(%eax,%ecx,8),%bnd0",},
153{{0xf2, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
154"f2 0f 1b 80 78 56 34 12 \tbndcn 0x12345678(%eax),%bnd0",},
155{{0xf2, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
156"f2 0f 1b 85 78 56 34 12 \tbndcn 0x12345678(%ebp),%bnd0",},
157{{0xf2, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
158"f2 0f 1b 84 01 78 56 34 12 \tbndcn 0x12345678(%ecx,%eax,1),%bnd0",},
159{{0xf2, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
160"f2 0f 1b 84 05 78 56 34 12 \tbndcn 0x12345678(%ebp,%eax,1),%bnd0",},
161{{0xf2, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
162"f2 0f 1b 84 08 78 56 34 12 \tbndcn 0x12345678(%eax,%ecx,1),%bnd0",},
163{{0xf2, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
164"f2 0f 1b 84 c8 78 56 34 12 \tbndcn 0x12345678(%eax,%ecx,8),%bnd0",},
165{{0xf2, 0x0f, 0x1b, 0xc0, }, 4, 0, "", "",
166"f2 0f 1b c0 \tbndcn %eax,%bnd0",},
167{{0x66, 0x0f, 0x1a, 0x00, }, 4, 0, "", "",
168"66 0f 1a 00 \tbndmov (%eax),%bnd0",},
169{{0x66, 0x0f, 0x1a, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
170"66 0f 1a 05 78 56 34 12 \tbndmov 0x12345678,%bnd0",},
171{{0x66, 0x0f, 0x1a, 0x18, }, 4, 0, "", "",
172"66 0f 1a 18 \tbndmov (%eax),%bnd3",},
173{{0x66, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "",
174"66 0f 1a 04 01 \tbndmov (%ecx,%eax,1),%bnd0",},
175{{0x66, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
176"66 0f 1a 04 05 78 56 34 12 \tbndmov 0x12345678(,%eax,1),%bnd0",},
177{{0x66, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "",
178"66 0f 1a 04 08 \tbndmov (%eax,%ecx,1),%bnd0",},
179{{0x66, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "",
180"66 0f 1a 04 c8 \tbndmov (%eax,%ecx,8),%bnd0",},
181{{0x66, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "",
182"66 0f 1a 40 12 \tbndmov 0x12(%eax),%bnd0",},
183{{0x66, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "",
184"66 0f 1a 45 12 \tbndmov 0x12(%ebp),%bnd0",},
185{{0x66, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "",
186"66 0f 1a 44 01 12 \tbndmov 0x12(%ecx,%eax,1),%bnd0",},
187{{0x66, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "",
188"66 0f 1a 44 05 12 \tbndmov 0x12(%ebp,%eax,1),%bnd0",},
189{{0x66, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "",
190"66 0f 1a 44 08 12 \tbndmov 0x12(%eax,%ecx,1),%bnd0",},
191{{0x66, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
192"66 0f 1a 44 c8 12 \tbndmov 0x12(%eax,%ecx,8),%bnd0",},
193{{0x66, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
194"66 0f 1a 80 78 56 34 12 \tbndmov 0x12345678(%eax),%bnd0",},
195{{0x66, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
196"66 0f 1a 85 78 56 34 12 \tbndmov 0x12345678(%ebp),%bnd0",},
197{{0x66, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
198"66 0f 1a 84 01 78 56 34 12 \tbndmov 0x12345678(%ecx,%eax,1),%bnd0",},
199{{0x66, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
200"66 0f 1a 84 05 78 56 34 12 \tbndmov 0x12345678(%ebp,%eax,1),%bnd0",},
201{{0x66, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
202"66 0f 1a 84 08 78 56 34 12 \tbndmov 0x12345678(%eax,%ecx,1),%bnd0",},
203{{0x66, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
204"66 0f 1a 84 c8 78 56 34 12 \tbndmov 0x12345678(%eax,%ecx,8),%bnd0",},
205{{0x66, 0x0f, 0x1b, 0x00, }, 4, 0, "", "",
206"66 0f 1b 00 \tbndmov %bnd0,(%eax)",},
207{{0x66, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
208"66 0f 1b 05 78 56 34 12 \tbndmov %bnd0,0x12345678",},
209{{0x66, 0x0f, 0x1b, 0x18, }, 4, 0, "", "",
210"66 0f 1b 18 \tbndmov %bnd3,(%eax)",},
211{{0x66, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "",
212"66 0f 1b 04 01 \tbndmov %bnd0,(%ecx,%eax,1)",},
213{{0x66, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
214"66 0f 1b 04 05 78 56 34 12 \tbndmov %bnd0,0x12345678(,%eax,1)",},
215{{0x66, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "",
216"66 0f 1b 04 08 \tbndmov %bnd0,(%eax,%ecx,1)",},
217{{0x66, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "",
218"66 0f 1b 04 c8 \tbndmov %bnd0,(%eax,%ecx,8)",},
219{{0x66, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "",
220"66 0f 1b 40 12 \tbndmov %bnd0,0x12(%eax)",},
221{{0x66, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "",
222"66 0f 1b 45 12 \tbndmov %bnd0,0x12(%ebp)",},
223{{0x66, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "",
224"66 0f 1b 44 01 12 \tbndmov %bnd0,0x12(%ecx,%eax,1)",},
225{{0x66, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "",
226"66 0f 1b 44 05 12 \tbndmov %bnd0,0x12(%ebp,%eax,1)",},
227{{0x66, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "",
228"66 0f 1b 44 08 12 \tbndmov %bnd0,0x12(%eax,%ecx,1)",},
229{{0x66, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
230"66 0f 1b 44 c8 12 \tbndmov %bnd0,0x12(%eax,%ecx,8)",},
231{{0x66, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
232"66 0f 1b 80 78 56 34 12 \tbndmov %bnd0,0x12345678(%eax)",},
233{{0x66, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
234"66 0f 1b 85 78 56 34 12 \tbndmov %bnd0,0x12345678(%ebp)",},
235{{0x66, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
236"66 0f 1b 84 01 78 56 34 12 \tbndmov %bnd0,0x12345678(%ecx,%eax,1)",},
237{{0x66, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
238"66 0f 1b 84 05 78 56 34 12 \tbndmov %bnd0,0x12345678(%ebp,%eax,1)",},
239{{0x66, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
240"66 0f 1b 84 08 78 56 34 12 \tbndmov %bnd0,0x12345678(%eax,%ecx,1)",},
241{{0x66, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
242"66 0f 1b 84 c8 78 56 34 12 \tbndmov %bnd0,0x12345678(%eax,%ecx,8)",},
243{{0x66, 0x0f, 0x1a, 0xc8, }, 4, 0, "", "",
244"66 0f 1a c8 \tbndmov %bnd0,%bnd1",},
245{{0x66, 0x0f, 0x1a, 0xc1, }, 4, 0, "", "",
246"66 0f 1a c1 \tbndmov %bnd1,%bnd0",},
247{{0x0f, 0x1a, 0x00, }, 3, 0, "", "",
248"0f 1a 00 \tbndldx (%eax),%bnd0",},
249{{0x0f, 0x1a, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
250"0f 1a 05 78 56 34 12 \tbndldx 0x12345678,%bnd0",},
251{{0x0f, 0x1a, 0x18, }, 3, 0, "", "",
252"0f 1a 18 \tbndldx (%eax),%bnd3",},
253{{0x0f, 0x1a, 0x04, 0x01, }, 4, 0, "", "",
254"0f 1a 04 01 \tbndldx (%ecx,%eax,1),%bnd0",},
255{{0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
256"0f 1a 04 05 78 56 34 12 \tbndldx 0x12345678(,%eax,1),%bnd0",},
257{{0x0f, 0x1a, 0x04, 0x08, }, 4, 0, "", "",
258"0f 1a 04 08 \tbndldx (%eax,%ecx,1),%bnd0",},
259{{0x0f, 0x1a, 0x40, 0x12, }, 4, 0, "", "",
260"0f 1a 40 12 \tbndldx 0x12(%eax),%bnd0",},
261{{0x0f, 0x1a, 0x45, 0x12, }, 4, 0, "", "",
262"0f 1a 45 12 \tbndldx 0x12(%ebp),%bnd0",},
263{{0x0f, 0x1a, 0x44, 0x01, 0x12, }, 5, 0, "", "",
264"0f 1a 44 01 12 \tbndldx 0x12(%ecx,%eax,1),%bnd0",},
265{{0x0f, 0x1a, 0x44, 0x05, 0x12, }, 5, 0, "", "",
266"0f 1a 44 05 12 \tbndldx 0x12(%ebp,%eax,1),%bnd0",},
267{{0x0f, 0x1a, 0x44, 0x08, 0x12, }, 5, 0, "", "",
268"0f 1a 44 08 12 \tbndldx 0x12(%eax,%ecx,1),%bnd0",},
269{{0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
270"0f 1a 80 78 56 34 12 \tbndldx 0x12345678(%eax),%bnd0",},
271{{0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
272"0f 1a 85 78 56 34 12 \tbndldx 0x12345678(%ebp),%bnd0",},
273{{0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
274"0f 1a 84 01 78 56 34 12 \tbndldx 0x12345678(%ecx,%eax,1),%bnd0",},
275{{0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
276"0f 1a 84 05 78 56 34 12 \tbndldx 0x12345678(%ebp,%eax,1),%bnd0",},
277{{0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
278"0f 1a 84 08 78 56 34 12 \tbndldx 0x12345678(%eax,%ecx,1),%bnd0",},
279{{0x0f, 0x1b, 0x00, }, 3, 0, "", "",
280"0f 1b 00 \tbndstx %bnd0,(%eax)",},
281{{0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
282"0f 1b 05 78 56 34 12 \tbndstx %bnd0,0x12345678",},
283{{0x0f, 0x1b, 0x18, }, 3, 0, "", "",
284"0f 1b 18 \tbndstx %bnd3,(%eax)",},
285{{0x0f, 0x1b, 0x04, 0x01, }, 4, 0, "", "",
286"0f 1b 04 01 \tbndstx %bnd0,(%ecx,%eax,1)",},
287{{0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
288"0f 1b 04 05 78 56 34 12 \tbndstx %bnd0,0x12345678(,%eax,1)",},
289{{0x0f, 0x1b, 0x04, 0x08, }, 4, 0, "", "",
290"0f 1b 04 08 \tbndstx %bnd0,(%eax,%ecx,1)",},
291{{0x0f, 0x1b, 0x40, 0x12, }, 4, 0, "", "",
292"0f 1b 40 12 \tbndstx %bnd0,0x12(%eax)",},
293{{0x0f, 0x1b, 0x45, 0x12, }, 4, 0, "", "",
294"0f 1b 45 12 \tbndstx %bnd0,0x12(%ebp)",},
295{{0x0f, 0x1b, 0x44, 0x01, 0x12, }, 5, 0, "", "",
296"0f 1b 44 01 12 \tbndstx %bnd0,0x12(%ecx,%eax,1)",},
297{{0x0f, 0x1b, 0x44, 0x05, 0x12, }, 5, 0, "", "",
298"0f 1b 44 05 12 \tbndstx %bnd0,0x12(%ebp,%eax,1)",},
299{{0x0f, 0x1b, 0x44, 0x08, 0x12, }, 5, 0, "", "",
300"0f 1b 44 08 12 \tbndstx %bnd0,0x12(%eax,%ecx,1)",},
301{{0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
302"0f 1b 80 78 56 34 12 \tbndstx %bnd0,0x12345678(%eax)",},
303{{0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
304"0f 1b 85 78 56 34 12 \tbndstx %bnd0,0x12345678(%ebp)",},
305{{0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
306"0f 1b 84 01 78 56 34 12 \tbndstx %bnd0,0x12345678(%ecx,%eax,1)",},
307{{0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
308"0f 1b 84 05 78 56 34 12 \tbndstx %bnd0,0x12345678(%ebp,%eax,1)",},
309{{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
310"0f 1b 84 08 78 56 34 12 \tbndstx %bnd0,0x12345678(%eax,%ecx,1)",},
311{{0xf2, 0xe8, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "call", "unconditional",
312"f2 e8 fc ff ff ff \tbnd call 3c3 <main+0x3c3>",},
313{{0xf2, 0xff, 0x10, }, 3, 0, "call", "indirect",
314"f2 ff 10 \tbnd call *(%eax)",},
315{{0xf2, 0xc3, }, 2, 0, "ret", "indirect",
316"f2 c3 \tbnd ret ",},
317{{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional",
318"f2 e9 fc ff ff ff \tbnd jmp 3ce <main+0x3ce>",},
319{{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional",
320"f2 e9 fc ff ff ff \tbnd jmp 3d4 <main+0x3d4>",},
321{{0xf2, 0xff, 0x21, }, 3, 0, "jmp", "indirect",
322"f2 ff 21 \tbnd jmp *(%ecx)",},
323{{0xf2, 0x0f, 0x85, 0xfc, 0xff, 0xff, 0xff, }, 7, 0xfffffffc, "jcc", "conditional",
324"f2 0f 85 fc ff ff ff \tbnd jne 3de <main+0x3de>",},
325{{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "",
326"0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",},
327{{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "",
328"0f 3a cc d7 91 \tsha1rnds4 $0x91,%xmm7,%xmm2",},
329{{0x0f, 0x3a, 0xcc, 0x00, 0x91, }, 5, 0, "", "",
330"0f 3a cc 00 91 \tsha1rnds4 $0x91,(%eax),%xmm0",},
331{{0x0f, 0x3a, 0xcc, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "",
332"0f 3a cc 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678,%xmm0",},
333{{0x0f, 0x3a, 0xcc, 0x18, 0x91, }, 5, 0, "", "",
334"0f 3a cc 18 91 \tsha1rnds4 $0x91,(%eax),%xmm3",},
335{{0x0f, 0x3a, 0xcc, 0x04, 0x01, 0x91, }, 6, 0, "", "",
336"0f 3a cc 04 01 91 \tsha1rnds4 $0x91,(%ecx,%eax,1),%xmm0",},
337{{0x0f, 0x3a, 0xcc, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
338"0f 3a cc 04 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(,%eax,1),%xmm0",},
339{{0x0f, 0x3a, 0xcc, 0x04, 0x08, 0x91, }, 6, 0, "", "",
340"0f 3a cc 04 08 91 \tsha1rnds4 $0x91,(%eax,%ecx,1),%xmm0",},
341{{0x0f, 0x3a, 0xcc, 0x04, 0xc8, 0x91, }, 6, 0, "", "",
342"0f 3a cc 04 c8 91 \tsha1rnds4 $0x91,(%eax,%ecx,8),%xmm0",},
343{{0x0f, 0x3a, 0xcc, 0x40, 0x12, 0x91, }, 6, 0, "", "",
344"0f 3a cc 40 12 91 \tsha1rnds4 $0x91,0x12(%eax),%xmm0",},
345{{0x0f, 0x3a, 0xcc, 0x45, 0x12, 0x91, }, 6, 0, "", "",
346"0f 3a cc 45 12 91 \tsha1rnds4 $0x91,0x12(%ebp),%xmm0",},
347{{0x0f, 0x3a, 0xcc, 0x44, 0x01, 0x12, 0x91, }, 7, 0, "", "",
348"0f 3a cc 44 01 12 91 \tsha1rnds4 $0x91,0x12(%ecx,%eax,1),%xmm0",},
349{{0x0f, 0x3a, 0xcc, 0x44, 0x05, 0x12, 0x91, }, 7, 0, "", "",
350"0f 3a cc 44 05 12 91 \tsha1rnds4 $0x91,0x12(%ebp,%eax,1),%xmm0",},
351{{0x0f, 0x3a, 0xcc, 0x44, 0x08, 0x12, 0x91, }, 7, 0, "", "",
352"0f 3a cc 44 08 12 91 \tsha1rnds4 $0x91,0x12(%eax,%ecx,1),%xmm0",},
353{{0x0f, 0x3a, 0xcc, 0x44, 0xc8, 0x12, 0x91, }, 7, 0, "", "",
354"0f 3a cc 44 c8 12 91 \tsha1rnds4 $0x91,0x12(%eax,%ecx,8),%xmm0",},
355{{0x0f, 0x3a, 0xcc, 0x80, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "",
356"0f 3a cc 80 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%eax),%xmm0",},
357{{0x0f, 0x3a, 0xcc, 0x85, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "",
358"0f 3a cc 85 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%ebp),%xmm0",},
359{{0x0f, 0x3a, 0xcc, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
360"0f 3a cc 84 01 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%ecx,%eax,1),%xmm0",},
361{{0x0f, 0x3a, 0xcc, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
362"0f 3a cc 84 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%ebp,%eax,1),%xmm0",},
363{{0x0f, 0x3a, 0xcc, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
364"0f 3a cc 84 08 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%eax,%ecx,1),%xmm0",},
365{{0x0f, 0x3a, 0xcc, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
366"0f 3a cc 84 c8 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%eax,%ecx,8),%xmm0",},
367{{0x0f, 0x38, 0xc8, 0xc1, }, 4, 0, "", "",
368"0f 38 c8 c1 \tsha1nexte %xmm1,%xmm0",},
369{{0x0f, 0x38, 0xc8, 0xd7, }, 4, 0, "", "",
370"0f 38 c8 d7 \tsha1nexte %xmm7,%xmm2",},
371{{0x0f, 0x38, 0xc8, 0x00, }, 4, 0, "", "",
372"0f 38 c8 00 \tsha1nexte (%eax),%xmm0",},
373{{0x0f, 0x38, 0xc8, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
374"0f 38 c8 05 78 56 34 12 \tsha1nexte 0x12345678,%xmm0",},
375{{0x0f, 0x38, 0xc8, 0x18, }, 4, 0, "", "",
376"0f 38 c8 18 \tsha1nexte (%eax),%xmm3",},
377{{0x0f, 0x38, 0xc8, 0x04, 0x01, }, 5, 0, "", "",
378"0f 38 c8 04 01 \tsha1nexte (%ecx,%eax,1),%xmm0",},
379{{0x0f, 0x38, 0xc8, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
380"0f 38 c8 04 05 78 56 34 12 \tsha1nexte 0x12345678(,%eax,1),%xmm0",},
381{{0x0f, 0x38, 0xc8, 0x04, 0x08, }, 5, 0, "", "",
382"0f 38 c8 04 08 \tsha1nexte (%eax,%ecx,1),%xmm0",},
383{{0x0f, 0x38, 0xc8, 0x04, 0xc8, }, 5, 0, "", "",
384"0f 38 c8 04 c8 \tsha1nexte (%eax,%ecx,8),%xmm0",},
385{{0x0f, 0x38, 0xc8, 0x40, 0x12, }, 5, 0, "", "",
386"0f 38 c8 40 12 \tsha1nexte 0x12(%eax),%xmm0",},
387{{0x0f, 0x38, 0xc8, 0x45, 0x12, }, 5, 0, "", "",
388"0f 38 c8 45 12 \tsha1nexte 0x12(%ebp),%xmm0",},
389{{0x0f, 0x38, 0xc8, 0x44, 0x01, 0x12, }, 6, 0, "", "",
390"0f 38 c8 44 01 12 \tsha1nexte 0x12(%ecx,%eax,1),%xmm0",},
391{{0x0f, 0x38, 0xc8, 0x44, 0x05, 0x12, }, 6, 0, "", "",
392"0f 38 c8 44 05 12 \tsha1nexte 0x12(%ebp,%eax,1),%xmm0",},
393{{0x0f, 0x38, 0xc8, 0x44, 0x08, 0x12, }, 6, 0, "", "",
394"0f 38 c8 44 08 12 \tsha1nexte 0x12(%eax,%ecx,1),%xmm0",},
395{{0x0f, 0x38, 0xc8, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
396"0f 38 c8 44 c8 12 \tsha1nexte 0x12(%eax,%ecx,8),%xmm0",},
397{{0x0f, 0x38, 0xc8, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
398"0f 38 c8 80 78 56 34 12 \tsha1nexte 0x12345678(%eax),%xmm0",},
399{{0x0f, 0x38, 0xc8, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
400"0f 38 c8 85 78 56 34 12 \tsha1nexte 0x12345678(%ebp),%xmm0",},
401{{0x0f, 0x38, 0xc8, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
402"0f 38 c8 84 01 78 56 34 12 \tsha1nexte 0x12345678(%ecx,%eax,1),%xmm0",},
403{{0x0f, 0x38, 0xc8, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
404"0f 38 c8 84 05 78 56 34 12 \tsha1nexte 0x12345678(%ebp,%eax,1),%xmm0",},
405{{0x0f, 0x38, 0xc8, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
406"0f 38 c8 84 08 78 56 34 12 \tsha1nexte 0x12345678(%eax,%ecx,1),%xmm0",},
407{{0x0f, 0x38, 0xc8, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
408"0f 38 c8 84 c8 78 56 34 12 \tsha1nexte 0x12345678(%eax,%ecx,8),%xmm0",},
409{{0x0f, 0x38, 0xc9, 0xc1, }, 4, 0, "", "",
410"0f 38 c9 c1 \tsha1msg1 %xmm1,%xmm0",},
411{{0x0f, 0x38, 0xc9, 0xd7, }, 4, 0, "", "",
412"0f 38 c9 d7 \tsha1msg1 %xmm7,%xmm2",},
413{{0x0f, 0x38, 0xc9, 0x00, }, 4, 0, "", "",
414"0f 38 c9 00 \tsha1msg1 (%eax),%xmm0",},
415{{0x0f, 0x38, 0xc9, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
416"0f 38 c9 05 78 56 34 12 \tsha1msg1 0x12345678,%xmm0",},
417{{0x0f, 0x38, 0xc9, 0x18, }, 4, 0, "", "",
418"0f 38 c9 18 \tsha1msg1 (%eax),%xmm3",},
419{{0x0f, 0x38, 0xc9, 0x04, 0x01, }, 5, 0, "", "",
420"0f 38 c9 04 01 \tsha1msg1 (%ecx,%eax,1),%xmm0",},
421{{0x0f, 0x38, 0xc9, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
422"0f 38 c9 04 05 78 56 34 12 \tsha1msg1 0x12345678(,%eax,1),%xmm0",},
423{{0x0f, 0x38, 0xc9, 0x04, 0x08, }, 5, 0, "", "",
424"0f 38 c9 04 08 \tsha1msg1 (%eax,%ecx,1),%xmm0",},
425{{0x0f, 0x38, 0xc9, 0x04, 0xc8, }, 5, 0, "", "",
426"0f 38 c9 04 c8 \tsha1msg1 (%eax,%ecx,8),%xmm0",},
427{{0x0f, 0x38, 0xc9, 0x40, 0x12, }, 5, 0, "", "",
428"0f 38 c9 40 12 \tsha1msg1 0x12(%eax),%xmm0",},
429{{0x0f, 0x38, 0xc9, 0x45, 0x12, }, 5, 0, "", "",
430"0f 38 c9 45 12 \tsha1msg1 0x12(%ebp),%xmm0",},
431{{0x0f, 0x38, 0xc9, 0x44, 0x01, 0x12, }, 6, 0, "", "",
432"0f 38 c9 44 01 12 \tsha1msg1 0x12(%ecx,%eax,1),%xmm0",},
433{{0x0f, 0x38, 0xc9, 0x44, 0x05, 0x12, }, 6, 0, "", "",
434"0f 38 c9 44 05 12 \tsha1msg1 0x12(%ebp,%eax,1),%xmm0",},
435{{0x0f, 0x38, 0xc9, 0x44, 0x08, 0x12, }, 6, 0, "", "",
436"0f 38 c9 44 08 12 \tsha1msg1 0x12(%eax,%ecx,1),%xmm0",},
437{{0x0f, 0x38, 0xc9, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
438"0f 38 c9 44 c8 12 \tsha1msg1 0x12(%eax,%ecx,8),%xmm0",},
439{{0x0f, 0x38, 0xc9, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
440"0f 38 c9 80 78 56 34 12 \tsha1msg1 0x12345678(%eax),%xmm0",},
441{{0x0f, 0x38, 0xc9, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
442"0f 38 c9 85 78 56 34 12 \tsha1msg1 0x12345678(%ebp),%xmm0",},
443{{0x0f, 0x38, 0xc9, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
444"0f 38 c9 84 01 78 56 34 12 \tsha1msg1 0x12345678(%ecx,%eax,1),%xmm0",},
445{{0x0f, 0x38, 0xc9, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
446"0f 38 c9 84 05 78 56 34 12 \tsha1msg1 0x12345678(%ebp,%eax,1),%xmm0",},
447{{0x0f, 0x38, 0xc9, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
448"0f 38 c9 84 08 78 56 34 12 \tsha1msg1 0x12345678(%eax,%ecx,1),%xmm0",},
449{{0x0f, 0x38, 0xc9, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
450"0f 38 c9 84 c8 78 56 34 12 \tsha1msg1 0x12345678(%eax,%ecx,8),%xmm0",},
451{{0x0f, 0x38, 0xca, 0xc1, }, 4, 0, "", "",
452"0f 38 ca c1 \tsha1msg2 %xmm1,%xmm0",},
453{{0x0f, 0x38, 0xca, 0xd7, }, 4, 0, "", "",
454"0f 38 ca d7 \tsha1msg2 %xmm7,%xmm2",},
455{{0x0f, 0x38, 0xca, 0x00, }, 4, 0, "", "",
456"0f 38 ca 00 \tsha1msg2 (%eax),%xmm0",},
457{{0x0f, 0x38, 0xca, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
458"0f 38 ca 05 78 56 34 12 \tsha1msg2 0x12345678,%xmm0",},
459{{0x0f, 0x38, 0xca, 0x18, }, 4, 0, "", "",
460"0f 38 ca 18 \tsha1msg2 (%eax),%xmm3",},
461{{0x0f, 0x38, 0xca, 0x04, 0x01, }, 5, 0, "", "",
462"0f 38 ca 04 01 \tsha1msg2 (%ecx,%eax,1),%xmm0",},
463{{0x0f, 0x38, 0xca, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
464"0f 38 ca 04 05 78 56 34 12 \tsha1msg2 0x12345678(,%eax,1),%xmm0",},
465{{0x0f, 0x38, 0xca, 0x04, 0x08, }, 5, 0, "", "",
466"0f 38 ca 04 08 \tsha1msg2 (%eax,%ecx,1),%xmm0",},
467{{0x0f, 0x38, 0xca, 0x04, 0xc8, }, 5, 0, "", "",
468"0f 38 ca 04 c8 \tsha1msg2 (%eax,%ecx,8),%xmm0",},
469{{0x0f, 0x38, 0xca, 0x40, 0x12, }, 5, 0, "", "",
470"0f 38 ca 40 12 \tsha1msg2 0x12(%eax),%xmm0",},
471{{0x0f, 0x38, 0xca, 0x45, 0x12, }, 5, 0, "", "",
472"0f 38 ca 45 12 \tsha1msg2 0x12(%ebp),%xmm0",},
473{{0x0f, 0x38, 0xca, 0x44, 0x01, 0x12, }, 6, 0, "", "",
474"0f 38 ca 44 01 12 \tsha1msg2 0x12(%ecx,%eax,1),%xmm0",},
475{{0x0f, 0x38, 0xca, 0x44, 0x05, 0x12, }, 6, 0, "", "",
476"0f 38 ca 44 05 12 \tsha1msg2 0x12(%ebp,%eax,1),%xmm0",},
477{{0x0f, 0x38, 0xca, 0x44, 0x08, 0x12, }, 6, 0, "", "",
478"0f 38 ca 44 08 12 \tsha1msg2 0x12(%eax,%ecx,1),%xmm0",},
479{{0x0f, 0x38, 0xca, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
480"0f 38 ca 44 c8 12 \tsha1msg2 0x12(%eax,%ecx,8),%xmm0",},
481{{0x0f, 0x38, 0xca, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
482"0f 38 ca 80 78 56 34 12 \tsha1msg2 0x12345678(%eax),%xmm0",},
483{{0x0f, 0x38, 0xca, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
484"0f 38 ca 85 78 56 34 12 \tsha1msg2 0x12345678(%ebp),%xmm0",},
485{{0x0f, 0x38, 0xca, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
486"0f 38 ca 84 01 78 56 34 12 \tsha1msg2 0x12345678(%ecx,%eax,1),%xmm0",},
487{{0x0f, 0x38, 0xca, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
488"0f 38 ca 84 05 78 56 34 12 \tsha1msg2 0x12345678(%ebp,%eax,1),%xmm0",},
489{{0x0f, 0x38, 0xca, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
490"0f 38 ca 84 08 78 56 34 12 \tsha1msg2 0x12345678(%eax,%ecx,1),%xmm0",},
491{{0x0f, 0x38, 0xca, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
492"0f 38 ca 84 c8 78 56 34 12 \tsha1msg2 0x12345678(%eax,%ecx,8),%xmm0",},
493{{0x0f, 0x38, 0xcb, 0xcc, }, 4, 0, "", "",
494"0f 38 cb cc \tsha256rnds2 %xmm0,%xmm4,%xmm1",},
495{{0x0f, 0x38, 0xcb, 0xd7, }, 4, 0, "", "",
496"0f 38 cb d7 \tsha256rnds2 %xmm0,%xmm7,%xmm2",},
497{{0x0f, 0x38, 0xcb, 0x08, }, 4, 0, "", "",
498"0f 38 cb 08 \tsha256rnds2 %xmm0,(%eax),%xmm1",},
499{{0x0f, 0x38, 0xcb, 0x0d, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
500"0f 38 cb 0d 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678,%xmm1",},
501{{0x0f, 0x38, 0xcb, 0x18, }, 4, 0, "", "",
502"0f 38 cb 18 \tsha256rnds2 %xmm0,(%eax),%xmm3",},
503{{0x0f, 0x38, 0xcb, 0x0c, 0x01, }, 5, 0, "", "",
504"0f 38 cb 0c 01 \tsha256rnds2 %xmm0,(%ecx,%eax,1),%xmm1",},
505{{0x0f, 0x38, 0xcb, 0x0c, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
506"0f 38 cb 0c 05 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(,%eax,1),%xmm1",},
507{{0x0f, 0x38, 0xcb, 0x0c, 0x08, }, 5, 0, "", "",
508"0f 38 cb 0c 08 \tsha256rnds2 %xmm0,(%eax,%ecx,1),%xmm1",},
509{{0x0f, 0x38, 0xcb, 0x0c, 0xc8, }, 5, 0, "", "",
510"0f 38 cb 0c c8 \tsha256rnds2 %xmm0,(%eax,%ecx,8),%xmm1",},
511{{0x0f, 0x38, 0xcb, 0x48, 0x12, }, 5, 0, "", "",
512"0f 38 cb 48 12 \tsha256rnds2 %xmm0,0x12(%eax),%xmm1",},
513{{0x0f, 0x38, 0xcb, 0x4d, 0x12, }, 5, 0, "", "",
514"0f 38 cb 4d 12 \tsha256rnds2 %xmm0,0x12(%ebp),%xmm1",},
515{{0x0f, 0x38, 0xcb, 0x4c, 0x01, 0x12, }, 6, 0, "", "",
516"0f 38 cb 4c 01 12 \tsha256rnds2 %xmm0,0x12(%ecx,%eax,1),%xmm1",},
517{{0x0f, 0x38, 0xcb, 0x4c, 0x05, 0x12, }, 6, 0, "", "",
518"0f 38 cb 4c 05 12 \tsha256rnds2 %xmm0,0x12(%ebp,%eax,1),%xmm1",},
519{{0x0f, 0x38, 0xcb, 0x4c, 0x08, 0x12, }, 6, 0, "", "",
520"0f 38 cb 4c 08 12 \tsha256rnds2 %xmm0,0x12(%eax,%ecx,1),%xmm1",},
521{{0x0f, 0x38, 0xcb, 0x4c, 0xc8, 0x12, }, 6, 0, "", "",
522"0f 38 cb 4c c8 12 \tsha256rnds2 %xmm0,0x12(%eax,%ecx,8),%xmm1",},
523{{0x0f, 0x38, 0xcb, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
524"0f 38 cb 88 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%eax),%xmm1",},
525{{0x0f, 0x38, 0xcb, 0x8d, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
526"0f 38 cb 8d 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%ebp),%xmm1",},
527{{0x0f, 0x38, 0xcb, 0x8c, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
528"0f 38 cb 8c 01 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%ecx,%eax,1),%xmm1",},
529{{0x0f, 0x38, 0xcb, 0x8c, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
530"0f 38 cb 8c 05 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%ebp,%eax,1),%xmm1",},
531{{0x0f, 0x38, 0xcb, 0x8c, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
532"0f 38 cb 8c 08 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%eax,%ecx,1),%xmm1",},
533{{0x0f, 0x38, 0xcb, 0x8c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
534"0f 38 cb 8c c8 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%eax,%ecx,8),%xmm1",},
535{{0x0f, 0x38, 0xcc, 0xc1, }, 4, 0, "", "",
536"0f 38 cc c1 \tsha256msg1 %xmm1,%xmm0",},
537{{0x0f, 0x38, 0xcc, 0xd7, }, 4, 0, "", "",
538"0f 38 cc d7 \tsha256msg1 %xmm7,%xmm2",},
539{{0x0f, 0x38, 0xcc, 0x00, }, 4, 0, "", "",
540"0f 38 cc 00 \tsha256msg1 (%eax),%xmm0",},
541{{0x0f, 0x38, 0xcc, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
542"0f 38 cc 05 78 56 34 12 \tsha256msg1 0x12345678,%xmm0",},
543{{0x0f, 0x38, 0xcc, 0x18, }, 4, 0, "", "",
544"0f 38 cc 18 \tsha256msg1 (%eax),%xmm3",},
545{{0x0f, 0x38, 0xcc, 0x04, 0x01, }, 5, 0, "", "",
546"0f 38 cc 04 01 \tsha256msg1 (%ecx,%eax,1),%xmm0",},
547{{0x0f, 0x38, 0xcc, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
548"0f 38 cc 04 05 78 56 34 12 \tsha256msg1 0x12345678(,%eax,1),%xmm0",},
549{{0x0f, 0x38, 0xcc, 0x04, 0x08, }, 5, 0, "", "",
550"0f 38 cc 04 08 \tsha256msg1 (%eax,%ecx,1),%xmm0",},
551{{0x0f, 0x38, 0xcc, 0x04, 0xc8, }, 5, 0, "", "",
552"0f 38 cc 04 c8 \tsha256msg1 (%eax,%ecx,8),%xmm0",},
553{{0x0f, 0x38, 0xcc, 0x40, 0x12, }, 5, 0, "", "",
554"0f 38 cc 40 12 \tsha256msg1 0x12(%eax),%xmm0",},
555{{0x0f, 0x38, 0xcc, 0x45, 0x12, }, 5, 0, "", "",
556"0f 38 cc 45 12 \tsha256msg1 0x12(%ebp),%xmm0",},
557{{0x0f, 0x38, 0xcc, 0x44, 0x01, 0x12, }, 6, 0, "", "",
558"0f 38 cc 44 01 12 \tsha256msg1 0x12(%ecx,%eax,1),%xmm0",},
559{{0x0f, 0x38, 0xcc, 0x44, 0x05, 0x12, }, 6, 0, "", "",
560"0f 38 cc 44 05 12 \tsha256msg1 0x12(%ebp,%eax,1),%xmm0",},
561{{0x0f, 0x38, 0xcc, 0x44, 0x08, 0x12, }, 6, 0, "", "",
562"0f 38 cc 44 08 12 \tsha256msg1 0x12(%eax,%ecx,1),%xmm0",},
563{{0x0f, 0x38, 0xcc, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
564"0f 38 cc 44 c8 12 \tsha256msg1 0x12(%eax,%ecx,8),%xmm0",},
565{{0x0f, 0x38, 0xcc, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
566"0f 38 cc 80 78 56 34 12 \tsha256msg1 0x12345678(%eax),%xmm0",},
567{{0x0f, 0x38, 0xcc, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
568"0f 38 cc 85 78 56 34 12 \tsha256msg1 0x12345678(%ebp),%xmm0",},
569{{0x0f, 0x38, 0xcc, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
570"0f 38 cc 84 01 78 56 34 12 \tsha256msg1 0x12345678(%ecx,%eax,1),%xmm0",},
571{{0x0f, 0x38, 0xcc, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
572"0f 38 cc 84 05 78 56 34 12 \tsha256msg1 0x12345678(%ebp,%eax,1),%xmm0",},
573{{0x0f, 0x38, 0xcc, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
574"0f 38 cc 84 08 78 56 34 12 \tsha256msg1 0x12345678(%eax,%ecx,1),%xmm0",},
575{{0x0f, 0x38, 0xcc, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
576"0f 38 cc 84 c8 78 56 34 12 \tsha256msg1 0x12345678(%eax,%ecx,8),%xmm0",},
577{{0x0f, 0x38, 0xcd, 0xc1, }, 4, 0, "", "",
578"0f 38 cd c1 \tsha256msg2 %xmm1,%xmm0",},
579{{0x0f, 0x38, 0xcd, 0xd7, }, 4, 0, "", "",
580"0f 38 cd d7 \tsha256msg2 %xmm7,%xmm2",},
581{{0x0f, 0x38, 0xcd, 0x00, }, 4, 0, "", "",
582"0f 38 cd 00 \tsha256msg2 (%eax),%xmm0",},
583{{0x0f, 0x38, 0xcd, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
584"0f 38 cd 05 78 56 34 12 \tsha256msg2 0x12345678,%xmm0",},
585{{0x0f, 0x38, 0xcd, 0x18, }, 4, 0, "", "",
586"0f 38 cd 18 \tsha256msg2 (%eax),%xmm3",},
587{{0x0f, 0x38, 0xcd, 0x04, 0x01, }, 5, 0, "", "",
588"0f 38 cd 04 01 \tsha256msg2 (%ecx,%eax,1),%xmm0",},
589{{0x0f, 0x38, 0xcd, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
590"0f 38 cd 04 05 78 56 34 12 \tsha256msg2 0x12345678(,%eax,1),%xmm0",},
591{{0x0f, 0x38, 0xcd, 0x04, 0x08, }, 5, 0, "", "",
592"0f 38 cd 04 08 \tsha256msg2 (%eax,%ecx,1),%xmm0",},
593{{0x0f, 0x38, 0xcd, 0x04, 0xc8, }, 5, 0, "", "",
594"0f 38 cd 04 c8 \tsha256msg2 (%eax,%ecx,8),%xmm0",},
595{{0x0f, 0x38, 0xcd, 0x40, 0x12, }, 5, 0, "", "",
596"0f 38 cd 40 12 \tsha256msg2 0x12(%eax),%xmm0",},
597{{0x0f, 0x38, 0xcd, 0x45, 0x12, }, 5, 0, "", "",
598"0f 38 cd 45 12 \tsha256msg2 0x12(%ebp),%xmm0",},
599{{0x0f, 0x38, 0xcd, 0x44, 0x01, 0x12, }, 6, 0, "", "",
600"0f 38 cd 44 01 12 \tsha256msg2 0x12(%ecx,%eax,1),%xmm0",},
601{{0x0f, 0x38, 0xcd, 0x44, 0x05, 0x12, }, 6, 0, "", "",
602"0f 38 cd 44 05 12 \tsha256msg2 0x12(%ebp,%eax,1),%xmm0",},
603{{0x0f, 0x38, 0xcd, 0x44, 0x08, 0x12, }, 6, 0, "", "",
604"0f 38 cd 44 08 12 \tsha256msg2 0x12(%eax,%ecx,1),%xmm0",},
605{{0x0f, 0x38, 0xcd, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
606"0f 38 cd 44 c8 12 \tsha256msg2 0x12(%eax,%ecx,8),%xmm0",},
607{{0x0f, 0x38, 0xcd, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
608"0f 38 cd 80 78 56 34 12 \tsha256msg2 0x12345678(%eax),%xmm0",},
609{{0x0f, 0x38, 0xcd, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
610"0f 38 cd 85 78 56 34 12 \tsha256msg2 0x12345678(%ebp),%xmm0",},
611{{0x0f, 0x38, 0xcd, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
612"0f 38 cd 84 01 78 56 34 12 \tsha256msg2 0x12345678(%ecx,%eax,1),%xmm0",},
613{{0x0f, 0x38, 0xcd, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
614"0f 38 cd 84 05 78 56 34 12 \tsha256msg2 0x12345678(%ebp,%eax,1),%xmm0",},
615{{0x0f, 0x38, 0xcd, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
616"0f 38 cd 84 08 78 56 34 12 \tsha256msg2 0x12345678(%eax,%ecx,1),%xmm0",},
617{{0x0f, 0x38, 0xcd, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
618"0f 38 cd 84 c8 78 56 34 12 \tsha256msg2 0x12345678(%eax,%ecx,8),%xmm0",},
619{{0x66, 0x0f, 0xae, 0x38, }, 4, 0, "", "",
620"66 0f ae 38 \tclflushopt (%eax)",},
621{{0x66, 0x0f, 0xae, 0x3d, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
622"66 0f ae 3d 78 56 34 12 \tclflushopt 0x12345678",},
623{{0x66, 0x0f, 0xae, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
624"66 0f ae bc c8 78 56 34 12 \tclflushopt 0x12345678(%eax,%ecx,8)",},
625{{0x0f, 0xae, 0x38, }, 3, 0, "", "",
626"0f ae 38 \tclflush (%eax)",},
627{{0x0f, 0xae, 0xf8, }, 3, 0, "", "",
628"0f ae f8 \tsfence ",},
629{{0x66, 0x0f, 0xae, 0x30, }, 4, 0, "", "",
630"66 0f ae 30 \tclwb (%eax)",},
631{{0x66, 0x0f, 0xae, 0x35, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
632"66 0f ae 35 78 56 34 12 \tclwb 0x12345678",},
633{{0x66, 0x0f, 0xae, 0xb4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
634"66 0f ae b4 c8 78 56 34 12 \tclwb 0x12345678(%eax,%ecx,8)",},
635{{0x0f, 0xae, 0x30, }, 3, 0, "", "",
636"0f ae 30 \txsaveopt (%eax)",},
637{{0x0f, 0xae, 0xf0, }, 3, 0, "", "",
638"0f ae f0 \tmfence ",},
639{{0x0f, 0xc7, 0x20, }, 3, 0, "", "",
640"0f c7 20 \txsavec (%eax)",},
641{{0x0f, 0xc7, 0x25, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
642"0f c7 25 78 56 34 12 \txsavec 0x12345678",},
643{{0x0f, 0xc7, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
644"0f c7 a4 c8 78 56 34 12 \txsavec 0x12345678(%eax,%ecx,8)",},
645{{0x0f, 0xc7, 0x28, }, 3, 0, "", "",
646"0f c7 28 \txsaves (%eax)",},
647{{0x0f, 0xc7, 0x2d, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
648"0f c7 2d 78 56 34 12 \txsaves 0x12345678",},
649{{0x0f, 0xc7, 0xac, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
650"0f c7 ac c8 78 56 34 12 \txsaves 0x12345678(%eax,%ecx,8)",},
651{{0x0f, 0xc7, 0x18, }, 3, 0, "", "",
652"0f c7 18 \txrstors (%eax)",},
653{{0x0f, 0xc7, 0x1d, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
654"0f c7 1d 78 56 34 12 \txrstors 0x12345678",},
655{{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
656"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",},
657{{0x66, 0x0f, 0xae, 0xf8, }, 4, 0, "", "",
658"66 0f ae f8 \tpcommit ",},
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-64.c b/tools/perf/arch/x86/tests/insn-x86-dat-64.c
new file mode 100644
index 000000000000..4fe7cce179c4
--- /dev/null
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-64.c
@@ -0,0 +1,768 @@
1/*
2 * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk
3 * from insn-x86-dat-src.c for inclusion by insn-x86.c
4 * Do not change this code.
5*/
6
7{{0x0f, 0x31, }, 2, 0, "", "",
8"0f 31 \trdtsc ",},
9{{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "",
10"f3 0f 1b 00 \tbndmk (%rax),%bnd0",},
11{{0xf3, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "",
12"f3 41 0f 1b 00 \tbndmk (%r8),%bnd0",},
13{{0xf3, 0x0f, 0x1b, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
14"f3 0f 1b 04 25 78 56 34 12 \tbndmk 0x12345678,%bnd0",},
15{{0xf3, 0x0f, 0x1b, 0x18, }, 4, 0, "", "",
16"f3 0f 1b 18 \tbndmk (%rax),%bnd3",},
17{{0xf3, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "",
18"f3 0f 1b 04 01 \tbndmk (%rcx,%rax,1),%bnd0",},
19{{0xf3, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
20"f3 0f 1b 04 05 78 56 34 12 \tbndmk 0x12345678(,%rax,1),%bnd0",},
21{{0xf3, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "",
22"f3 0f 1b 04 08 \tbndmk (%rax,%rcx,1),%bnd0",},
23{{0xf3, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "",
24"f3 0f 1b 04 c8 \tbndmk (%rax,%rcx,8),%bnd0",},
25{{0xf3, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "",
26"f3 0f 1b 40 12 \tbndmk 0x12(%rax),%bnd0",},
27{{0xf3, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "",
28"f3 0f 1b 45 12 \tbndmk 0x12(%rbp),%bnd0",},
29{{0xf3, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "",
30"f3 0f 1b 44 01 12 \tbndmk 0x12(%rcx,%rax,1),%bnd0",},
31{{0xf3, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "",
32"f3 0f 1b 44 05 12 \tbndmk 0x12(%rbp,%rax,1),%bnd0",},
33{{0xf3, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "",
34"f3 0f 1b 44 08 12 \tbndmk 0x12(%rax,%rcx,1),%bnd0",},
35{{0xf3, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
36"f3 0f 1b 44 c8 12 \tbndmk 0x12(%rax,%rcx,8),%bnd0",},
37{{0xf3, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
38"f3 0f 1b 80 78 56 34 12 \tbndmk 0x12345678(%rax),%bnd0",},
39{{0xf3, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
40"f3 0f 1b 85 78 56 34 12 \tbndmk 0x12345678(%rbp),%bnd0",},
41{{0xf3, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
42"f3 0f 1b 84 01 78 56 34 12 \tbndmk 0x12345678(%rcx,%rax,1),%bnd0",},
43{{0xf3, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
44"f3 0f 1b 84 05 78 56 34 12 \tbndmk 0x12345678(%rbp,%rax,1),%bnd0",},
45{{0xf3, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
46"f3 0f 1b 84 08 78 56 34 12 \tbndmk 0x12345678(%rax,%rcx,1),%bnd0",},
47{{0xf3, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
48"f3 0f 1b 84 c8 78 56 34 12 \tbndmk 0x12345678(%rax,%rcx,8),%bnd0",},
49{{0xf3, 0x0f, 0x1a, 0x00, }, 4, 0, "", "",
50"f3 0f 1a 00 \tbndcl (%rax),%bnd0",},
51{{0xf3, 0x41, 0x0f, 0x1a, 0x00, }, 5, 0, "", "",
52"f3 41 0f 1a 00 \tbndcl (%r8),%bnd0",},
53{{0xf3, 0x0f, 0x1a, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
54"f3 0f 1a 04 25 78 56 34 12 \tbndcl 0x12345678,%bnd0",},
55{{0xf3, 0x0f, 0x1a, 0x18, }, 4, 0, "", "",
56"f3 0f 1a 18 \tbndcl (%rax),%bnd3",},
57{{0xf3, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "",
58"f3 0f 1a 04 01 \tbndcl (%rcx,%rax,1),%bnd0",},
59{{0xf3, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
60"f3 0f 1a 04 05 78 56 34 12 \tbndcl 0x12345678(,%rax,1),%bnd0",},
61{{0xf3, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "",
62"f3 0f 1a 04 08 \tbndcl (%rax,%rcx,1),%bnd0",},
63{{0xf3, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "",
64"f3 0f 1a 04 c8 \tbndcl (%rax,%rcx,8),%bnd0",},
65{{0xf3, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "",
66"f3 0f 1a 40 12 \tbndcl 0x12(%rax),%bnd0",},
67{{0xf3, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "",
68"f3 0f 1a 45 12 \tbndcl 0x12(%rbp),%bnd0",},
69{{0xf3, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "",
70"f3 0f 1a 44 01 12 \tbndcl 0x12(%rcx,%rax,1),%bnd0",},
71{{0xf3, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "",
72"f3 0f 1a 44 05 12 \tbndcl 0x12(%rbp,%rax,1),%bnd0",},
73{{0xf3, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "",
74"f3 0f 1a 44 08 12 \tbndcl 0x12(%rax,%rcx,1),%bnd0",},
75{{0xf3, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
76"f3 0f 1a 44 c8 12 \tbndcl 0x12(%rax,%rcx,8),%bnd0",},
77{{0xf3, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
78"f3 0f 1a 80 78 56 34 12 \tbndcl 0x12345678(%rax),%bnd0",},
79{{0xf3, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
80"f3 0f 1a 85 78 56 34 12 \tbndcl 0x12345678(%rbp),%bnd0",},
81{{0xf3, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
82"f3 0f 1a 84 01 78 56 34 12 \tbndcl 0x12345678(%rcx,%rax,1),%bnd0",},
83{{0xf3, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
84"f3 0f 1a 84 05 78 56 34 12 \tbndcl 0x12345678(%rbp,%rax,1),%bnd0",},
85{{0xf3, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
86"f3 0f 1a 84 08 78 56 34 12 \tbndcl 0x12345678(%rax,%rcx,1),%bnd0",},
87{{0xf3, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
88"f3 0f 1a 84 c8 78 56 34 12 \tbndcl 0x12345678(%rax,%rcx,8),%bnd0",},
89{{0xf3, 0x0f, 0x1a, 0xc0, }, 4, 0, "", "",
90"f3 0f 1a c0 \tbndcl %rax,%bnd0",},
91{{0xf2, 0x0f, 0x1a, 0x00, }, 4, 0, "", "",
92"f2 0f 1a 00 \tbndcu (%rax),%bnd0",},
93{{0xf2, 0x41, 0x0f, 0x1a, 0x00, }, 5, 0, "", "",
94"f2 41 0f 1a 00 \tbndcu (%r8),%bnd0",},
95{{0xf2, 0x0f, 0x1a, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
96"f2 0f 1a 04 25 78 56 34 12 \tbndcu 0x12345678,%bnd0",},
97{{0xf2, 0x0f, 0x1a, 0x18, }, 4, 0, "", "",
98"f2 0f 1a 18 \tbndcu (%rax),%bnd3",},
99{{0xf2, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "",
100"f2 0f 1a 04 01 \tbndcu (%rcx,%rax,1),%bnd0",},
101{{0xf2, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
102"f2 0f 1a 04 05 78 56 34 12 \tbndcu 0x12345678(,%rax,1),%bnd0",},
103{{0xf2, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "",
104"f2 0f 1a 04 08 \tbndcu (%rax,%rcx,1),%bnd0",},
105{{0xf2, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "",
106"f2 0f 1a 04 c8 \tbndcu (%rax,%rcx,8),%bnd0",},
107{{0xf2, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "",
108"f2 0f 1a 40 12 \tbndcu 0x12(%rax),%bnd0",},
109{{0xf2, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "",
110"f2 0f 1a 45 12 \tbndcu 0x12(%rbp),%bnd0",},
111{{0xf2, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "",
112"f2 0f 1a 44 01 12 \tbndcu 0x12(%rcx,%rax,1),%bnd0",},
113{{0xf2, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "",
114"f2 0f 1a 44 05 12 \tbndcu 0x12(%rbp,%rax,1),%bnd0",},
115{{0xf2, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "",
116"f2 0f 1a 44 08 12 \tbndcu 0x12(%rax,%rcx,1),%bnd0",},
117{{0xf2, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
118"f2 0f 1a 44 c8 12 \tbndcu 0x12(%rax,%rcx,8),%bnd0",},
119{{0xf2, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
120"f2 0f 1a 80 78 56 34 12 \tbndcu 0x12345678(%rax),%bnd0",},
121{{0xf2, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
122"f2 0f 1a 85 78 56 34 12 \tbndcu 0x12345678(%rbp),%bnd0",},
123{{0xf2, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
124"f2 0f 1a 84 01 78 56 34 12 \tbndcu 0x12345678(%rcx,%rax,1),%bnd0",},
125{{0xf2, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
126"f2 0f 1a 84 05 78 56 34 12 \tbndcu 0x12345678(%rbp,%rax,1),%bnd0",},
127{{0xf2, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
128"f2 0f 1a 84 08 78 56 34 12 \tbndcu 0x12345678(%rax,%rcx,1),%bnd0",},
129{{0xf2, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
130"f2 0f 1a 84 c8 78 56 34 12 \tbndcu 0x12345678(%rax,%rcx,8),%bnd0",},
131{{0xf2, 0x0f, 0x1a, 0xc0, }, 4, 0, "", "",
132"f2 0f 1a c0 \tbndcu %rax,%bnd0",},
133{{0xf2, 0x0f, 0x1b, 0x00, }, 4, 0, "", "",
134"f2 0f 1b 00 \tbndcn (%rax),%bnd0",},
135{{0xf2, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "",
136"f2 41 0f 1b 00 \tbndcn (%r8),%bnd0",},
137{{0xf2, 0x0f, 0x1b, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
138"f2 0f 1b 04 25 78 56 34 12 \tbndcn 0x12345678,%bnd0",},
139{{0xf2, 0x0f, 0x1b, 0x18, }, 4, 0, "", "",
140"f2 0f 1b 18 \tbndcn (%rax),%bnd3",},
141{{0xf2, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "",
142"f2 0f 1b 04 01 \tbndcn (%rcx,%rax,1),%bnd0",},
143{{0xf2, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
144"f2 0f 1b 04 05 78 56 34 12 \tbndcn 0x12345678(,%rax,1),%bnd0",},
145{{0xf2, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "",
146"f2 0f 1b 04 08 \tbndcn (%rax,%rcx,1),%bnd0",},
147{{0xf2, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "",
148"f2 0f 1b 04 c8 \tbndcn (%rax,%rcx,8),%bnd0",},
149{{0xf2, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "",
150"f2 0f 1b 40 12 \tbndcn 0x12(%rax),%bnd0",},
151{{0xf2, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "",
152"f2 0f 1b 45 12 \tbndcn 0x12(%rbp),%bnd0",},
153{{0xf2, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "",
154"f2 0f 1b 44 01 12 \tbndcn 0x12(%rcx,%rax,1),%bnd0",},
155{{0xf2, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "",
156"f2 0f 1b 44 05 12 \tbndcn 0x12(%rbp,%rax,1),%bnd0",},
157{{0xf2, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "",
158"f2 0f 1b 44 08 12 \tbndcn 0x12(%rax,%rcx,1),%bnd0",},
159{{0xf2, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
160"f2 0f 1b 44 c8 12 \tbndcn 0x12(%rax,%rcx,8),%bnd0",},
161{{0xf2, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
162"f2 0f 1b 80 78 56 34 12 \tbndcn 0x12345678(%rax),%bnd0",},
163{{0xf2, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
164"f2 0f 1b 85 78 56 34 12 \tbndcn 0x12345678(%rbp),%bnd0",},
165{{0xf2, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
166"f2 0f 1b 84 01 78 56 34 12 \tbndcn 0x12345678(%rcx,%rax,1),%bnd0",},
167{{0xf2, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
168"f2 0f 1b 84 05 78 56 34 12 \tbndcn 0x12345678(%rbp,%rax,1),%bnd0",},
169{{0xf2, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
170"f2 0f 1b 84 08 78 56 34 12 \tbndcn 0x12345678(%rax,%rcx,1),%bnd0",},
171{{0xf2, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
172"f2 0f 1b 84 c8 78 56 34 12 \tbndcn 0x12345678(%rax,%rcx,8),%bnd0",},
173{{0xf2, 0x0f, 0x1b, 0xc0, }, 4, 0, "", "",
174"f2 0f 1b c0 \tbndcn %rax,%bnd0",},
175{{0x66, 0x0f, 0x1a, 0x00, }, 4, 0, "", "",
176"66 0f 1a 00 \tbndmov (%rax),%bnd0",},
177{{0x66, 0x41, 0x0f, 0x1a, 0x00, }, 5, 0, "", "",
178"66 41 0f 1a 00 \tbndmov (%r8),%bnd0",},
179{{0x66, 0x0f, 0x1a, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
180"66 0f 1a 04 25 78 56 34 12 \tbndmov 0x12345678,%bnd0",},
181{{0x66, 0x0f, 0x1a, 0x18, }, 4, 0, "", "",
182"66 0f 1a 18 \tbndmov (%rax),%bnd3",},
183{{0x66, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "",
184"66 0f 1a 04 01 \tbndmov (%rcx,%rax,1),%bnd0",},
185{{0x66, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
186"66 0f 1a 04 05 78 56 34 12 \tbndmov 0x12345678(,%rax,1),%bnd0",},
187{{0x66, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "",
188"66 0f 1a 04 08 \tbndmov (%rax,%rcx,1),%bnd0",},
189{{0x66, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "",
190"66 0f 1a 04 c8 \tbndmov (%rax,%rcx,8),%bnd0",},
191{{0x66, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "",
192"66 0f 1a 40 12 \tbndmov 0x12(%rax),%bnd0",},
193{{0x66, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "",
194"66 0f 1a 45 12 \tbndmov 0x12(%rbp),%bnd0",},
195{{0x66, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "",
196"66 0f 1a 44 01 12 \tbndmov 0x12(%rcx,%rax,1),%bnd0",},
197{{0x66, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "",
198"66 0f 1a 44 05 12 \tbndmov 0x12(%rbp,%rax,1),%bnd0",},
199{{0x66, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "",
200"66 0f 1a 44 08 12 \tbndmov 0x12(%rax,%rcx,1),%bnd0",},
201{{0x66, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
202"66 0f 1a 44 c8 12 \tbndmov 0x12(%rax,%rcx,8),%bnd0",},
203{{0x66, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
204"66 0f 1a 80 78 56 34 12 \tbndmov 0x12345678(%rax),%bnd0",},
205{{0x66, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
206"66 0f 1a 85 78 56 34 12 \tbndmov 0x12345678(%rbp),%bnd0",},
207{{0x66, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
208"66 0f 1a 84 01 78 56 34 12 \tbndmov 0x12345678(%rcx,%rax,1),%bnd0",},
209{{0x66, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
210"66 0f 1a 84 05 78 56 34 12 \tbndmov 0x12345678(%rbp,%rax,1),%bnd0",},
211{{0x66, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
212"66 0f 1a 84 08 78 56 34 12 \tbndmov 0x12345678(%rax,%rcx,1),%bnd0",},
213{{0x66, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
214"66 0f 1a 84 c8 78 56 34 12 \tbndmov 0x12345678(%rax,%rcx,8),%bnd0",},
215{{0x66, 0x0f, 0x1b, 0x00, }, 4, 0, "", "",
216"66 0f 1b 00 \tbndmov %bnd0,(%rax)",},
217{{0x66, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "",
218"66 41 0f 1b 00 \tbndmov %bnd0,(%r8)",},
219{{0x66, 0x0f, 0x1b, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
220"66 0f 1b 04 25 78 56 34 12 \tbndmov %bnd0,0x12345678",},
221{{0x66, 0x0f, 0x1b, 0x18, }, 4, 0, "", "",
222"66 0f 1b 18 \tbndmov %bnd3,(%rax)",},
223{{0x66, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "",
224"66 0f 1b 04 01 \tbndmov %bnd0,(%rcx,%rax,1)",},
225{{0x66, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
226"66 0f 1b 04 05 78 56 34 12 \tbndmov %bnd0,0x12345678(,%rax,1)",},
227{{0x66, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "",
228"66 0f 1b 04 08 \tbndmov %bnd0,(%rax,%rcx,1)",},
229{{0x66, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "",
230"66 0f 1b 04 c8 \tbndmov %bnd0,(%rax,%rcx,8)",},
231{{0x66, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "",
232"66 0f 1b 40 12 \tbndmov %bnd0,0x12(%rax)",},
233{{0x66, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "",
234"66 0f 1b 45 12 \tbndmov %bnd0,0x12(%rbp)",},
235{{0x66, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "",
236"66 0f 1b 44 01 12 \tbndmov %bnd0,0x12(%rcx,%rax,1)",},
237{{0x66, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "",
238"66 0f 1b 44 05 12 \tbndmov %bnd0,0x12(%rbp,%rax,1)",},
239{{0x66, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "",
240"66 0f 1b 44 08 12 \tbndmov %bnd0,0x12(%rax,%rcx,1)",},
241{{0x66, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
242"66 0f 1b 44 c8 12 \tbndmov %bnd0,0x12(%rax,%rcx,8)",},
243{{0x66, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
244"66 0f 1b 80 78 56 34 12 \tbndmov %bnd0,0x12345678(%rax)",},
245{{0x66, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
246"66 0f 1b 85 78 56 34 12 \tbndmov %bnd0,0x12345678(%rbp)",},
247{{0x66, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
248"66 0f 1b 84 01 78 56 34 12 \tbndmov %bnd0,0x12345678(%rcx,%rax,1)",},
249{{0x66, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
250"66 0f 1b 84 05 78 56 34 12 \tbndmov %bnd0,0x12345678(%rbp,%rax,1)",},
251{{0x66, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
252"66 0f 1b 84 08 78 56 34 12 \tbndmov %bnd0,0x12345678(%rax,%rcx,1)",},
253{{0x66, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
254"66 0f 1b 84 c8 78 56 34 12 \tbndmov %bnd0,0x12345678(%rax,%rcx,8)",},
255{{0x66, 0x0f, 0x1a, 0xc8, }, 4, 0, "", "",
256"66 0f 1a c8 \tbndmov %bnd0,%bnd1",},
257{{0x66, 0x0f, 0x1a, 0xc1, }, 4, 0, "", "",
258"66 0f 1a c1 \tbndmov %bnd1,%bnd0",},
259{{0x0f, 0x1a, 0x00, }, 3, 0, "", "",
260"0f 1a 00 \tbndldx (%rax),%bnd0",},
261{{0x41, 0x0f, 0x1a, 0x00, }, 4, 0, "", "",
262"41 0f 1a 00 \tbndldx (%r8),%bnd0",},
263{{0x0f, 0x1a, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
264"0f 1a 04 25 78 56 34 12 \tbndldx 0x12345678,%bnd0",},
265{{0x0f, 0x1a, 0x18, }, 3, 0, "", "",
266"0f 1a 18 \tbndldx (%rax),%bnd3",},
267{{0x0f, 0x1a, 0x04, 0x01, }, 4, 0, "", "",
268"0f 1a 04 01 \tbndldx (%rcx,%rax,1),%bnd0",},
269{{0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
270"0f 1a 04 05 78 56 34 12 \tbndldx 0x12345678(,%rax,1),%bnd0",},
271{{0x0f, 0x1a, 0x04, 0x08, }, 4, 0, "", "",
272"0f 1a 04 08 \tbndldx (%rax,%rcx,1),%bnd0",},
273{{0x0f, 0x1a, 0x40, 0x12, }, 4, 0, "", "",
274"0f 1a 40 12 \tbndldx 0x12(%rax),%bnd0",},
275{{0x0f, 0x1a, 0x45, 0x12, }, 4, 0, "", "",
276"0f 1a 45 12 \tbndldx 0x12(%rbp),%bnd0",},
277{{0x0f, 0x1a, 0x44, 0x01, 0x12, }, 5, 0, "", "",
278"0f 1a 44 01 12 \tbndldx 0x12(%rcx,%rax,1),%bnd0",},
279{{0x0f, 0x1a, 0x44, 0x05, 0x12, }, 5, 0, "", "",
280"0f 1a 44 05 12 \tbndldx 0x12(%rbp,%rax,1),%bnd0",},
281{{0x0f, 0x1a, 0x44, 0x08, 0x12, }, 5, 0, "", "",
282"0f 1a 44 08 12 \tbndldx 0x12(%rax,%rcx,1),%bnd0",},
283{{0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
284"0f 1a 80 78 56 34 12 \tbndldx 0x12345678(%rax),%bnd0",},
285{{0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
286"0f 1a 85 78 56 34 12 \tbndldx 0x12345678(%rbp),%bnd0",},
287{{0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
288"0f 1a 84 01 78 56 34 12 \tbndldx 0x12345678(%rcx,%rax,1),%bnd0",},
289{{0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
290"0f 1a 84 05 78 56 34 12 \tbndldx 0x12345678(%rbp,%rax,1),%bnd0",},
291{{0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
292"0f 1a 84 08 78 56 34 12 \tbndldx 0x12345678(%rax,%rcx,1),%bnd0",},
293{{0x0f, 0x1b, 0x00, }, 3, 0, "", "",
294"0f 1b 00 \tbndstx %bnd0,(%rax)",},
295{{0x41, 0x0f, 0x1b, 0x00, }, 4, 0, "", "",
296"41 0f 1b 00 \tbndstx %bnd0,(%r8)",},
297{{0x0f, 0x1b, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
298"0f 1b 04 25 78 56 34 12 \tbndstx %bnd0,0x12345678",},
299{{0x0f, 0x1b, 0x18, }, 3, 0, "", "",
300"0f 1b 18 \tbndstx %bnd3,(%rax)",},
301{{0x0f, 0x1b, 0x04, 0x01, }, 4, 0, "", "",
302"0f 1b 04 01 \tbndstx %bnd0,(%rcx,%rax,1)",},
303{{0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
304"0f 1b 04 05 78 56 34 12 \tbndstx %bnd0,0x12345678(,%rax,1)",},
305{{0x0f, 0x1b, 0x04, 0x08, }, 4, 0, "", "",
306"0f 1b 04 08 \tbndstx %bnd0,(%rax,%rcx,1)",},
307{{0x0f, 0x1b, 0x40, 0x12, }, 4, 0, "", "",
308"0f 1b 40 12 \tbndstx %bnd0,0x12(%rax)",},
309{{0x0f, 0x1b, 0x45, 0x12, }, 4, 0, "", "",
310"0f 1b 45 12 \tbndstx %bnd0,0x12(%rbp)",},
311{{0x0f, 0x1b, 0x44, 0x01, 0x12, }, 5, 0, "", "",
312"0f 1b 44 01 12 \tbndstx %bnd0,0x12(%rcx,%rax,1)",},
313{{0x0f, 0x1b, 0x44, 0x05, 0x12, }, 5, 0, "", "",
314"0f 1b 44 05 12 \tbndstx %bnd0,0x12(%rbp,%rax,1)",},
315{{0x0f, 0x1b, 0x44, 0x08, 0x12, }, 5, 0, "", "",
316"0f 1b 44 08 12 \tbndstx %bnd0,0x12(%rax,%rcx,1)",},
317{{0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
318"0f 1b 80 78 56 34 12 \tbndstx %bnd0,0x12345678(%rax)",},
319{{0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
320"0f 1b 85 78 56 34 12 \tbndstx %bnd0,0x12345678(%rbp)",},
321{{0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
322"0f 1b 84 01 78 56 34 12 \tbndstx %bnd0,0x12345678(%rcx,%rax,1)",},
323{{0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
324"0f 1b 84 05 78 56 34 12 \tbndstx %bnd0,0x12345678(%rbp,%rax,1)",},
325{{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
326"0f 1b 84 08 78 56 34 12 \tbndstx %bnd0,0x12345678(%rax,%rcx,1)",},
327{{0xf2, 0xe8, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "call", "unconditional",
328"f2 e8 00 00 00 00 \tbnd callq 3f6 <main+0x3f6>",},
329{{0x67, 0xf2, 0xff, 0x10, }, 4, 0, "call", "indirect",
330"67 f2 ff 10 \tbnd callq *(%eax)",},
331{{0xf2, 0xc3, }, 2, 0, "ret", "indirect",
332"f2 c3 \tbnd retq ",},
333{{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional",
334"f2 e9 00 00 00 00 \tbnd jmpq 402 <main+0x402>",},
335{{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional",
336"f2 e9 00 00 00 00 \tbnd jmpq 408 <main+0x408>",},
337{{0x67, 0xf2, 0xff, 0x21, }, 4, 0, "jmp", "indirect",
338"67 f2 ff 21 \tbnd jmpq *(%ecx)",},
339{{0xf2, 0x0f, 0x85, 0x00, 0x00, 0x00, 0x00, }, 7, 0, "jcc", "conditional",
340"f2 0f 85 00 00 00 00 \tbnd jne 413 <main+0x413>",},
341{{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "",
342"0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",},
343{{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "",
344"0f 3a cc d7 91 \tsha1rnds4 $0x91,%xmm7,%xmm2",},
345{{0x41, 0x0f, 0x3a, 0xcc, 0xc0, 0x91, }, 6, 0, "", "",
346"41 0f 3a cc c0 91 \tsha1rnds4 $0x91,%xmm8,%xmm0",},
347{{0x44, 0x0f, 0x3a, 0xcc, 0xc7, 0x91, }, 6, 0, "", "",
348"44 0f 3a cc c7 91 \tsha1rnds4 $0x91,%xmm7,%xmm8",},
349{{0x45, 0x0f, 0x3a, 0xcc, 0xc7, 0x91, }, 6, 0, "", "",
350"45 0f 3a cc c7 91 \tsha1rnds4 $0x91,%xmm15,%xmm8",},
351{{0x0f, 0x3a, 0xcc, 0x00, 0x91, }, 5, 0, "", "",
352"0f 3a cc 00 91 \tsha1rnds4 $0x91,(%rax),%xmm0",},
353{{0x41, 0x0f, 0x3a, 0xcc, 0x00, 0x91, }, 6, 0, "", "",
354"41 0f 3a cc 00 91 \tsha1rnds4 $0x91,(%r8),%xmm0",},
355{{0x0f, 0x3a, 0xcc, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
356"0f 3a cc 04 25 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678,%xmm0",},
357{{0x0f, 0x3a, 0xcc, 0x18, 0x91, }, 5, 0, "", "",
358"0f 3a cc 18 91 \tsha1rnds4 $0x91,(%rax),%xmm3",},
359{{0x0f, 0x3a, 0xcc, 0x04, 0x01, 0x91, }, 6, 0, "", "",
360"0f 3a cc 04 01 91 \tsha1rnds4 $0x91,(%rcx,%rax,1),%xmm0",},
361{{0x0f, 0x3a, 0xcc, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
362"0f 3a cc 04 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(,%rax,1),%xmm0",},
363{{0x0f, 0x3a, 0xcc, 0x04, 0x08, 0x91, }, 6, 0, "", "",
364"0f 3a cc 04 08 91 \tsha1rnds4 $0x91,(%rax,%rcx,1),%xmm0",},
365{{0x0f, 0x3a, 0xcc, 0x04, 0xc8, 0x91, }, 6, 0, "", "",
366"0f 3a cc 04 c8 91 \tsha1rnds4 $0x91,(%rax,%rcx,8),%xmm0",},
367{{0x0f, 0x3a, 0xcc, 0x40, 0x12, 0x91, }, 6, 0, "", "",
368"0f 3a cc 40 12 91 \tsha1rnds4 $0x91,0x12(%rax),%xmm0",},
369{{0x0f, 0x3a, 0xcc, 0x45, 0x12, 0x91, }, 6, 0, "", "",
370"0f 3a cc 45 12 91 \tsha1rnds4 $0x91,0x12(%rbp),%xmm0",},
371{{0x0f, 0x3a, 0xcc, 0x44, 0x01, 0x12, 0x91, }, 7, 0, "", "",
372"0f 3a cc 44 01 12 91 \tsha1rnds4 $0x91,0x12(%rcx,%rax,1),%xmm0",},
373{{0x0f, 0x3a, 0xcc, 0x44, 0x05, 0x12, 0x91, }, 7, 0, "", "",
374"0f 3a cc 44 05 12 91 \tsha1rnds4 $0x91,0x12(%rbp,%rax,1),%xmm0",},
375{{0x0f, 0x3a, 0xcc, 0x44, 0x08, 0x12, 0x91, }, 7, 0, "", "",
376"0f 3a cc 44 08 12 91 \tsha1rnds4 $0x91,0x12(%rax,%rcx,1),%xmm0",},
377{{0x0f, 0x3a, 0xcc, 0x44, 0xc8, 0x12, 0x91, }, 7, 0, "", "",
378"0f 3a cc 44 c8 12 91 \tsha1rnds4 $0x91,0x12(%rax,%rcx,8),%xmm0",},
379{{0x0f, 0x3a, 0xcc, 0x80, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "",
380"0f 3a cc 80 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rax),%xmm0",},
381{{0x0f, 0x3a, 0xcc, 0x85, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "",
382"0f 3a cc 85 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rbp),%xmm0",},
383{{0x0f, 0x3a, 0xcc, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
384"0f 3a cc 84 01 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rcx,%rax,1),%xmm0",},
385{{0x0f, 0x3a, 0xcc, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
386"0f 3a cc 84 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rbp,%rax,1),%xmm0",},
387{{0x0f, 0x3a, 0xcc, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
388"0f 3a cc 84 08 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rax,%rcx,1),%xmm0",},
389{{0x0f, 0x3a, 0xcc, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "",
390"0f 3a cc 84 c8 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rax,%rcx,8),%xmm0",},
391{{0x44, 0x0f, 0x3a, 0xcc, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, 0x91, }, 11, 0, "", "",
392"44 0f 3a cc bc c8 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rax,%rcx,8),%xmm15",},
393{{0x0f, 0x38, 0xc8, 0xc1, }, 4, 0, "", "",
394"0f 38 c8 c1 \tsha1nexte %xmm1,%xmm0",},
395{{0x0f, 0x38, 0xc8, 0xd7, }, 4, 0, "", "",
396"0f 38 c8 d7 \tsha1nexte %xmm7,%xmm2",},
397{{0x41, 0x0f, 0x38, 0xc8, 0xc0, }, 5, 0, "", "",
398"41 0f 38 c8 c0 \tsha1nexte %xmm8,%xmm0",},
399{{0x44, 0x0f, 0x38, 0xc8, 0xc7, }, 5, 0, "", "",
400"44 0f 38 c8 c7 \tsha1nexte %xmm7,%xmm8",},
401{{0x45, 0x0f, 0x38, 0xc8, 0xc7, }, 5, 0, "", "",
402"45 0f 38 c8 c7 \tsha1nexte %xmm15,%xmm8",},
403{{0x0f, 0x38, 0xc8, 0x00, }, 4, 0, "", "",
404"0f 38 c8 00 \tsha1nexte (%rax),%xmm0",},
405{{0x41, 0x0f, 0x38, 0xc8, 0x00, }, 5, 0, "", "",
406"41 0f 38 c8 00 \tsha1nexte (%r8),%xmm0",},
407{{0x0f, 0x38, 0xc8, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
408"0f 38 c8 04 25 78 56 34 12 \tsha1nexte 0x12345678,%xmm0",},
409{{0x0f, 0x38, 0xc8, 0x18, }, 4, 0, "", "",
410"0f 38 c8 18 \tsha1nexte (%rax),%xmm3",},
411{{0x0f, 0x38, 0xc8, 0x04, 0x01, }, 5, 0, "", "",
412"0f 38 c8 04 01 \tsha1nexte (%rcx,%rax,1),%xmm0",},
413{{0x0f, 0x38, 0xc8, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
414"0f 38 c8 04 05 78 56 34 12 \tsha1nexte 0x12345678(,%rax,1),%xmm0",},
415{{0x0f, 0x38, 0xc8, 0x04, 0x08, }, 5, 0, "", "",
416"0f 38 c8 04 08 \tsha1nexte (%rax,%rcx,1),%xmm0",},
417{{0x0f, 0x38, 0xc8, 0x04, 0xc8, }, 5, 0, "", "",
418"0f 38 c8 04 c8 \tsha1nexte (%rax,%rcx,8),%xmm0",},
419{{0x0f, 0x38, 0xc8, 0x40, 0x12, }, 5, 0, "", "",
420"0f 38 c8 40 12 \tsha1nexte 0x12(%rax),%xmm0",},
421{{0x0f, 0x38, 0xc8, 0x45, 0x12, }, 5, 0, "", "",
422"0f 38 c8 45 12 \tsha1nexte 0x12(%rbp),%xmm0",},
423{{0x0f, 0x38, 0xc8, 0x44, 0x01, 0x12, }, 6, 0, "", "",
424"0f 38 c8 44 01 12 \tsha1nexte 0x12(%rcx,%rax,1),%xmm0",},
425{{0x0f, 0x38, 0xc8, 0x44, 0x05, 0x12, }, 6, 0, "", "",
426"0f 38 c8 44 05 12 \tsha1nexte 0x12(%rbp,%rax,1),%xmm0",},
427{{0x0f, 0x38, 0xc8, 0x44, 0x08, 0x12, }, 6, 0, "", "",
428"0f 38 c8 44 08 12 \tsha1nexte 0x12(%rax,%rcx,1),%xmm0",},
429{{0x0f, 0x38, 0xc8, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
430"0f 38 c8 44 c8 12 \tsha1nexte 0x12(%rax,%rcx,8),%xmm0",},
431{{0x0f, 0x38, 0xc8, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
432"0f 38 c8 80 78 56 34 12 \tsha1nexte 0x12345678(%rax),%xmm0",},
433{{0x0f, 0x38, 0xc8, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
434"0f 38 c8 85 78 56 34 12 \tsha1nexte 0x12345678(%rbp),%xmm0",},
435{{0x0f, 0x38, 0xc8, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
436"0f 38 c8 84 01 78 56 34 12 \tsha1nexte 0x12345678(%rcx,%rax,1),%xmm0",},
437{{0x0f, 0x38, 0xc8, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
438"0f 38 c8 84 05 78 56 34 12 \tsha1nexte 0x12345678(%rbp,%rax,1),%xmm0",},
439{{0x0f, 0x38, 0xc8, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
440"0f 38 c8 84 08 78 56 34 12 \tsha1nexte 0x12345678(%rax,%rcx,1),%xmm0",},
441{{0x0f, 0x38, 0xc8, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
442"0f 38 c8 84 c8 78 56 34 12 \tsha1nexte 0x12345678(%rax,%rcx,8),%xmm0",},
443{{0x44, 0x0f, 0x38, 0xc8, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
444"44 0f 38 c8 bc c8 78 56 34 12 \tsha1nexte 0x12345678(%rax,%rcx,8),%xmm15",},
445{{0x0f, 0x38, 0xc9, 0xc1, }, 4, 0, "", "",
446"0f 38 c9 c1 \tsha1msg1 %xmm1,%xmm0",},
447{{0x0f, 0x38, 0xc9, 0xd7, }, 4, 0, "", "",
448"0f 38 c9 d7 \tsha1msg1 %xmm7,%xmm2",},
449{{0x41, 0x0f, 0x38, 0xc9, 0xc0, }, 5, 0, "", "",
450"41 0f 38 c9 c0 \tsha1msg1 %xmm8,%xmm0",},
451{{0x44, 0x0f, 0x38, 0xc9, 0xc7, }, 5, 0, "", "",
452"44 0f 38 c9 c7 \tsha1msg1 %xmm7,%xmm8",},
453{{0x45, 0x0f, 0x38, 0xc9, 0xc7, }, 5, 0, "", "",
454"45 0f 38 c9 c7 \tsha1msg1 %xmm15,%xmm8",},
455{{0x0f, 0x38, 0xc9, 0x00, }, 4, 0, "", "",
456"0f 38 c9 00 \tsha1msg1 (%rax),%xmm0",},
457{{0x41, 0x0f, 0x38, 0xc9, 0x00, }, 5, 0, "", "",
458"41 0f 38 c9 00 \tsha1msg1 (%r8),%xmm0",},
459{{0x0f, 0x38, 0xc9, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
460"0f 38 c9 04 25 78 56 34 12 \tsha1msg1 0x12345678,%xmm0",},
461{{0x0f, 0x38, 0xc9, 0x18, }, 4, 0, "", "",
462"0f 38 c9 18 \tsha1msg1 (%rax),%xmm3",},
463{{0x0f, 0x38, 0xc9, 0x04, 0x01, }, 5, 0, "", "",
464"0f 38 c9 04 01 \tsha1msg1 (%rcx,%rax,1),%xmm0",},
465{{0x0f, 0x38, 0xc9, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
466"0f 38 c9 04 05 78 56 34 12 \tsha1msg1 0x12345678(,%rax,1),%xmm0",},
467{{0x0f, 0x38, 0xc9, 0x04, 0x08, }, 5, 0, "", "",
468"0f 38 c9 04 08 \tsha1msg1 (%rax,%rcx,1),%xmm0",},
469{{0x0f, 0x38, 0xc9, 0x04, 0xc8, }, 5, 0, "", "",
470"0f 38 c9 04 c8 \tsha1msg1 (%rax,%rcx,8),%xmm0",},
471{{0x0f, 0x38, 0xc9, 0x40, 0x12, }, 5, 0, "", "",
472"0f 38 c9 40 12 \tsha1msg1 0x12(%rax),%xmm0",},
473{{0x0f, 0x38, 0xc9, 0x45, 0x12, }, 5, 0, "", "",
474"0f 38 c9 45 12 \tsha1msg1 0x12(%rbp),%xmm0",},
475{{0x0f, 0x38, 0xc9, 0x44, 0x01, 0x12, }, 6, 0, "", "",
476"0f 38 c9 44 01 12 \tsha1msg1 0x12(%rcx,%rax,1),%xmm0",},
477{{0x0f, 0x38, 0xc9, 0x44, 0x05, 0x12, }, 6, 0, "", "",
478"0f 38 c9 44 05 12 \tsha1msg1 0x12(%rbp,%rax,1),%xmm0",},
479{{0x0f, 0x38, 0xc9, 0x44, 0x08, 0x12, }, 6, 0, "", "",
480"0f 38 c9 44 08 12 \tsha1msg1 0x12(%rax,%rcx,1),%xmm0",},
481{{0x0f, 0x38, 0xc9, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
482"0f 38 c9 44 c8 12 \tsha1msg1 0x12(%rax,%rcx,8),%xmm0",},
483{{0x0f, 0x38, 0xc9, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
484"0f 38 c9 80 78 56 34 12 \tsha1msg1 0x12345678(%rax),%xmm0",},
485{{0x0f, 0x38, 0xc9, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
486"0f 38 c9 85 78 56 34 12 \tsha1msg1 0x12345678(%rbp),%xmm0",},
487{{0x0f, 0x38, 0xc9, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
488"0f 38 c9 84 01 78 56 34 12 \tsha1msg1 0x12345678(%rcx,%rax,1),%xmm0",},
489{{0x0f, 0x38, 0xc9, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
490"0f 38 c9 84 05 78 56 34 12 \tsha1msg1 0x12345678(%rbp,%rax,1),%xmm0",},
491{{0x0f, 0x38, 0xc9, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
492"0f 38 c9 84 08 78 56 34 12 \tsha1msg1 0x12345678(%rax,%rcx,1),%xmm0",},
493{{0x0f, 0x38, 0xc9, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
494"0f 38 c9 84 c8 78 56 34 12 \tsha1msg1 0x12345678(%rax,%rcx,8),%xmm0",},
495{{0x44, 0x0f, 0x38, 0xc9, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
496"44 0f 38 c9 bc c8 78 56 34 12 \tsha1msg1 0x12345678(%rax,%rcx,8),%xmm15",},
497{{0x0f, 0x38, 0xca, 0xc1, }, 4, 0, "", "",
498"0f 38 ca c1 \tsha1msg2 %xmm1,%xmm0",},
499{{0x0f, 0x38, 0xca, 0xd7, }, 4, 0, "", "",
500"0f 38 ca d7 \tsha1msg2 %xmm7,%xmm2",},
501{{0x41, 0x0f, 0x38, 0xca, 0xc0, }, 5, 0, "", "",
502"41 0f 38 ca c0 \tsha1msg2 %xmm8,%xmm0",},
503{{0x44, 0x0f, 0x38, 0xca, 0xc7, }, 5, 0, "", "",
504"44 0f 38 ca c7 \tsha1msg2 %xmm7,%xmm8",},
505{{0x45, 0x0f, 0x38, 0xca, 0xc7, }, 5, 0, "", "",
506"45 0f 38 ca c7 \tsha1msg2 %xmm15,%xmm8",},
507{{0x0f, 0x38, 0xca, 0x00, }, 4, 0, "", "",
508"0f 38 ca 00 \tsha1msg2 (%rax),%xmm0",},
509{{0x41, 0x0f, 0x38, 0xca, 0x00, }, 5, 0, "", "",
510"41 0f 38 ca 00 \tsha1msg2 (%r8),%xmm0",},
511{{0x0f, 0x38, 0xca, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
512"0f 38 ca 04 25 78 56 34 12 \tsha1msg2 0x12345678,%xmm0",},
513{{0x0f, 0x38, 0xca, 0x18, }, 4, 0, "", "",
514"0f 38 ca 18 \tsha1msg2 (%rax),%xmm3",},
515{{0x0f, 0x38, 0xca, 0x04, 0x01, }, 5, 0, "", "",
516"0f 38 ca 04 01 \tsha1msg2 (%rcx,%rax,1),%xmm0",},
517{{0x0f, 0x38, 0xca, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
518"0f 38 ca 04 05 78 56 34 12 \tsha1msg2 0x12345678(,%rax,1),%xmm0",},
519{{0x0f, 0x38, 0xca, 0x04, 0x08, }, 5, 0, "", "",
520"0f 38 ca 04 08 \tsha1msg2 (%rax,%rcx,1),%xmm0",},
521{{0x0f, 0x38, 0xca, 0x04, 0xc8, }, 5, 0, "", "",
522"0f 38 ca 04 c8 \tsha1msg2 (%rax,%rcx,8),%xmm0",},
523{{0x0f, 0x38, 0xca, 0x40, 0x12, }, 5, 0, "", "",
524"0f 38 ca 40 12 \tsha1msg2 0x12(%rax),%xmm0",},
525{{0x0f, 0x38, 0xca, 0x45, 0x12, }, 5, 0, "", "",
526"0f 38 ca 45 12 \tsha1msg2 0x12(%rbp),%xmm0",},
527{{0x0f, 0x38, 0xca, 0x44, 0x01, 0x12, }, 6, 0, "", "",
528"0f 38 ca 44 01 12 \tsha1msg2 0x12(%rcx,%rax,1),%xmm0",},
529{{0x0f, 0x38, 0xca, 0x44, 0x05, 0x12, }, 6, 0, "", "",
530"0f 38 ca 44 05 12 \tsha1msg2 0x12(%rbp,%rax,1),%xmm0",},
531{{0x0f, 0x38, 0xca, 0x44, 0x08, 0x12, }, 6, 0, "", "",
532"0f 38 ca 44 08 12 \tsha1msg2 0x12(%rax,%rcx,1),%xmm0",},
533{{0x0f, 0x38, 0xca, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
534"0f 38 ca 44 c8 12 \tsha1msg2 0x12(%rax,%rcx,8),%xmm0",},
535{{0x0f, 0x38, 0xca, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
536"0f 38 ca 80 78 56 34 12 \tsha1msg2 0x12345678(%rax),%xmm0",},
537{{0x0f, 0x38, 0xca, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
538"0f 38 ca 85 78 56 34 12 \tsha1msg2 0x12345678(%rbp),%xmm0",},
539{{0x0f, 0x38, 0xca, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
540"0f 38 ca 84 01 78 56 34 12 \tsha1msg2 0x12345678(%rcx,%rax,1),%xmm0",},
541{{0x0f, 0x38, 0xca, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
542"0f 38 ca 84 05 78 56 34 12 \tsha1msg2 0x12345678(%rbp,%rax,1),%xmm0",},
543{{0x0f, 0x38, 0xca, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
544"0f 38 ca 84 08 78 56 34 12 \tsha1msg2 0x12345678(%rax,%rcx,1),%xmm0",},
545{{0x0f, 0x38, 0xca, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
546"0f 38 ca 84 c8 78 56 34 12 \tsha1msg2 0x12345678(%rax,%rcx,8),%xmm0",},
547{{0x44, 0x0f, 0x38, 0xca, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
548"44 0f 38 ca bc c8 78 56 34 12 \tsha1msg2 0x12345678(%rax,%rcx,8),%xmm15",},
549{{0x0f, 0x38, 0xcb, 0xcc, }, 4, 0, "", "",
550"0f 38 cb cc \tsha256rnds2 %xmm0,%xmm4,%xmm1",},
551{{0x0f, 0x38, 0xcb, 0xd7, }, 4, 0, "", "",
552"0f 38 cb d7 \tsha256rnds2 %xmm0,%xmm7,%xmm2",},
553{{0x41, 0x0f, 0x38, 0xcb, 0xc8, }, 5, 0, "", "",
554"41 0f 38 cb c8 \tsha256rnds2 %xmm0,%xmm8,%xmm1",},
555{{0x44, 0x0f, 0x38, 0xcb, 0xc7, }, 5, 0, "", "",
556"44 0f 38 cb c7 \tsha256rnds2 %xmm0,%xmm7,%xmm8",},
557{{0x45, 0x0f, 0x38, 0xcb, 0xc7, }, 5, 0, "", "",
558"45 0f 38 cb c7 \tsha256rnds2 %xmm0,%xmm15,%xmm8",},
559{{0x0f, 0x38, 0xcb, 0x08, }, 4, 0, "", "",
560"0f 38 cb 08 \tsha256rnds2 %xmm0,(%rax),%xmm1",},
561{{0x41, 0x0f, 0x38, 0xcb, 0x08, }, 5, 0, "", "",
562"41 0f 38 cb 08 \tsha256rnds2 %xmm0,(%r8),%xmm1",},
563{{0x0f, 0x38, 0xcb, 0x0c, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
564"0f 38 cb 0c 25 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678,%xmm1",},
565{{0x0f, 0x38, 0xcb, 0x18, }, 4, 0, "", "",
566"0f 38 cb 18 \tsha256rnds2 %xmm0,(%rax),%xmm3",},
567{{0x0f, 0x38, 0xcb, 0x0c, 0x01, }, 5, 0, "", "",
568"0f 38 cb 0c 01 \tsha256rnds2 %xmm0,(%rcx,%rax,1),%xmm1",},
569{{0x0f, 0x38, 0xcb, 0x0c, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
570"0f 38 cb 0c 05 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(,%rax,1),%xmm1",},
571{{0x0f, 0x38, 0xcb, 0x0c, 0x08, }, 5, 0, "", "",
572"0f 38 cb 0c 08 \tsha256rnds2 %xmm0,(%rax,%rcx,1),%xmm1",},
573{{0x0f, 0x38, 0xcb, 0x0c, 0xc8, }, 5, 0, "", "",
574"0f 38 cb 0c c8 \tsha256rnds2 %xmm0,(%rax,%rcx,8),%xmm1",},
575{{0x0f, 0x38, 0xcb, 0x48, 0x12, }, 5, 0, "", "",
576"0f 38 cb 48 12 \tsha256rnds2 %xmm0,0x12(%rax),%xmm1",},
577{{0x0f, 0x38, 0xcb, 0x4d, 0x12, }, 5, 0, "", "",
578"0f 38 cb 4d 12 \tsha256rnds2 %xmm0,0x12(%rbp),%xmm1",},
579{{0x0f, 0x38, 0xcb, 0x4c, 0x01, 0x12, }, 6, 0, "", "",
580"0f 38 cb 4c 01 12 \tsha256rnds2 %xmm0,0x12(%rcx,%rax,1),%xmm1",},
581{{0x0f, 0x38, 0xcb, 0x4c, 0x05, 0x12, }, 6, 0, "", "",
582"0f 38 cb 4c 05 12 \tsha256rnds2 %xmm0,0x12(%rbp,%rax,1),%xmm1",},
583{{0x0f, 0x38, 0xcb, 0x4c, 0x08, 0x12, }, 6, 0, "", "",
584"0f 38 cb 4c 08 12 \tsha256rnds2 %xmm0,0x12(%rax,%rcx,1),%xmm1",},
585{{0x0f, 0x38, 0xcb, 0x4c, 0xc8, 0x12, }, 6, 0, "", "",
586"0f 38 cb 4c c8 12 \tsha256rnds2 %xmm0,0x12(%rax,%rcx,8),%xmm1",},
587{{0x0f, 0x38, 0xcb, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
588"0f 38 cb 88 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rax),%xmm1",},
589{{0x0f, 0x38, 0xcb, 0x8d, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
590"0f 38 cb 8d 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rbp),%xmm1",},
591{{0x0f, 0x38, 0xcb, 0x8c, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
592"0f 38 cb 8c 01 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rcx,%rax,1),%xmm1",},
593{{0x0f, 0x38, 0xcb, 0x8c, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
594"0f 38 cb 8c 05 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rbp,%rax,1),%xmm1",},
595{{0x0f, 0x38, 0xcb, 0x8c, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
596"0f 38 cb 8c 08 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rax,%rcx,1),%xmm1",},
597{{0x0f, 0x38, 0xcb, 0x8c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
598"0f 38 cb 8c c8 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rax,%rcx,8),%xmm1",},
599{{0x44, 0x0f, 0x38, 0xcb, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
600"44 0f 38 cb bc c8 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rax,%rcx,8),%xmm15",},
601{{0x0f, 0x38, 0xcc, 0xc1, }, 4, 0, "", "",
602"0f 38 cc c1 \tsha256msg1 %xmm1,%xmm0",},
603{{0x0f, 0x38, 0xcc, 0xd7, }, 4, 0, "", "",
604"0f 38 cc d7 \tsha256msg1 %xmm7,%xmm2",},
605{{0x41, 0x0f, 0x38, 0xcc, 0xc0, }, 5, 0, "", "",
606"41 0f 38 cc c0 \tsha256msg1 %xmm8,%xmm0",},
607{{0x44, 0x0f, 0x38, 0xcc, 0xc7, }, 5, 0, "", "",
608"44 0f 38 cc c7 \tsha256msg1 %xmm7,%xmm8",},
609{{0x45, 0x0f, 0x38, 0xcc, 0xc7, }, 5, 0, "", "",
610"45 0f 38 cc c7 \tsha256msg1 %xmm15,%xmm8",},
611{{0x0f, 0x38, 0xcc, 0x00, }, 4, 0, "", "",
612"0f 38 cc 00 \tsha256msg1 (%rax),%xmm0",},
613{{0x41, 0x0f, 0x38, 0xcc, 0x00, }, 5, 0, "", "",
614"41 0f 38 cc 00 \tsha256msg1 (%r8),%xmm0",},
615{{0x0f, 0x38, 0xcc, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
616"0f 38 cc 04 25 78 56 34 12 \tsha256msg1 0x12345678,%xmm0",},
617{{0x0f, 0x38, 0xcc, 0x18, }, 4, 0, "", "",
618"0f 38 cc 18 \tsha256msg1 (%rax),%xmm3",},
619{{0x0f, 0x38, 0xcc, 0x04, 0x01, }, 5, 0, "", "",
620"0f 38 cc 04 01 \tsha256msg1 (%rcx,%rax,1),%xmm0",},
621{{0x0f, 0x38, 0xcc, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
622"0f 38 cc 04 05 78 56 34 12 \tsha256msg1 0x12345678(,%rax,1),%xmm0",},
623{{0x0f, 0x38, 0xcc, 0x04, 0x08, }, 5, 0, "", "",
624"0f 38 cc 04 08 \tsha256msg1 (%rax,%rcx,1),%xmm0",},
625{{0x0f, 0x38, 0xcc, 0x04, 0xc8, }, 5, 0, "", "",
626"0f 38 cc 04 c8 \tsha256msg1 (%rax,%rcx,8),%xmm0",},
627{{0x0f, 0x38, 0xcc, 0x40, 0x12, }, 5, 0, "", "",
628"0f 38 cc 40 12 \tsha256msg1 0x12(%rax),%xmm0",},
629{{0x0f, 0x38, 0xcc, 0x45, 0x12, }, 5, 0, "", "",
630"0f 38 cc 45 12 \tsha256msg1 0x12(%rbp),%xmm0",},
631{{0x0f, 0x38, 0xcc, 0x44, 0x01, 0x12, }, 6, 0, "", "",
632"0f 38 cc 44 01 12 \tsha256msg1 0x12(%rcx,%rax,1),%xmm0",},
633{{0x0f, 0x38, 0xcc, 0x44, 0x05, 0x12, }, 6, 0, "", "",
634"0f 38 cc 44 05 12 \tsha256msg1 0x12(%rbp,%rax,1),%xmm0",},
635{{0x0f, 0x38, 0xcc, 0x44, 0x08, 0x12, }, 6, 0, "", "",
636"0f 38 cc 44 08 12 \tsha256msg1 0x12(%rax,%rcx,1),%xmm0",},
637{{0x0f, 0x38, 0xcc, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
638"0f 38 cc 44 c8 12 \tsha256msg1 0x12(%rax,%rcx,8),%xmm0",},
639{{0x0f, 0x38, 0xcc, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
640"0f 38 cc 80 78 56 34 12 \tsha256msg1 0x12345678(%rax),%xmm0",},
641{{0x0f, 0x38, 0xcc, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
642"0f 38 cc 85 78 56 34 12 \tsha256msg1 0x12345678(%rbp),%xmm0",},
643{{0x0f, 0x38, 0xcc, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
644"0f 38 cc 84 01 78 56 34 12 \tsha256msg1 0x12345678(%rcx,%rax,1),%xmm0",},
645{{0x0f, 0x38, 0xcc, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
646"0f 38 cc 84 05 78 56 34 12 \tsha256msg1 0x12345678(%rbp,%rax,1),%xmm0",},
647{{0x0f, 0x38, 0xcc, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
648"0f 38 cc 84 08 78 56 34 12 \tsha256msg1 0x12345678(%rax,%rcx,1),%xmm0",},
649{{0x0f, 0x38, 0xcc, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
650"0f 38 cc 84 c8 78 56 34 12 \tsha256msg1 0x12345678(%rax,%rcx,8),%xmm0",},
651{{0x44, 0x0f, 0x38, 0xcc, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
652"44 0f 38 cc bc c8 78 56 34 12 \tsha256msg1 0x12345678(%rax,%rcx,8),%xmm15",},
653{{0x0f, 0x38, 0xcd, 0xc1, }, 4, 0, "", "",
654"0f 38 cd c1 \tsha256msg2 %xmm1,%xmm0",},
655{{0x0f, 0x38, 0xcd, 0xd7, }, 4, 0, "", "",
656"0f 38 cd d7 \tsha256msg2 %xmm7,%xmm2",},
657{{0x41, 0x0f, 0x38, 0xcd, 0xc0, }, 5, 0, "", "",
658"41 0f 38 cd c0 \tsha256msg2 %xmm8,%xmm0",},
659{{0x44, 0x0f, 0x38, 0xcd, 0xc7, }, 5, 0, "", "",
660"44 0f 38 cd c7 \tsha256msg2 %xmm7,%xmm8",},
661{{0x45, 0x0f, 0x38, 0xcd, 0xc7, }, 5, 0, "", "",
662"45 0f 38 cd c7 \tsha256msg2 %xmm15,%xmm8",},
663{{0x0f, 0x38, 0xcd, 0x00, }, 4, 0, "", "",
664"0f 38 cd 00 \tsha256msg2 (%rax),%xmm0",},
665{{0x41, 0x0f, 0x38, 0xcd, 0x00, }, 5, 0, "", "",
666"41 0f 38 cd 00 \tsha256msg2 (%r8),%xmm0",},
667{{0x0f, 0x38, 0xcd, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
668"0f 38 cd 04 25 78 56 34 12 \tsha256msg2 0x12345678,%xmm0",},
669{{0x0f, 0x38, 0xcd, 0x18, }, 4, 0, "", "",
670"0f 38 cd 18 \tsha256msg2 (%rax),%xmm3",},
671{{0x0f, 0x38, 0xcd, 0x04, 0x01, }, 5, 0, "", "",
672"0f 38 cd 04 01 \tsha256msg2 (%rcx,%rax,1),%xmm0",},
673{{0x0f, 0x38, 0xcd, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
674"0f 38 cd 04 05 78 56 34 12 \tsha256msg2 0x12345678(,%rax,1),%xmm0",},
675{{0x0f, 0x38, 0xcd, 0x04, 0x08, }, 5, 0, "", "",
676"0f 38 cd 04 08 \tsha256msg2 (%rax,%rcx,1),%xmm0",},
677{{0x0f, 0x38, 0xcd, 0x04, 0xc8, }, 5, 0, "", "",
678"0f 38 cd 04 c8 \tsha256msg2 (%rax,%rcx,8),%xmm0",},
679{{0x0f, 0x38, 0xcd, 0x40, 0x12, }, 5, 0, "", "",
680"0f 38 cd 40 12 \tsha256msg2 0x12(%rax),%xmm0",},
681{{0x0f, 0x38, 0xcd, 0x45, 0x12, }, 5, 0, "", "",
682"0f 38 cd 45 12 \tsha256msg2 0x12(%rbp),%xmm0",},
683{{0x0f, 0x38, 0xcd, 0x44, 0x01, 0x12, }, 6, 0, "", "",
684"0f 38 cd 44 01 12 \tsha256msg2 0x12(%rcx,%rax,1),%xmm0",},
685{{0x0f, 0x38, 0xcd, 0x44, 0x05, 0x12, }, 6, 0, "", "",
686"0f 38 cd 44 05 12 \tsha256msg2 0x12(%rbp,%rax,1),%xmm0",},
687{{0x0f, 0x38, 0xcd, 0x44, 0x08, 0x12, }, 6, 0, "", "",
688"0f 38 cd 44 08 12 \tsha256msg2 0x12(%rax,%rcx,1),%xmm0",},
689{{0x0f, 0x38, 0xcd, 0x44, 0xc8, 0x12, }, 6, 0, "", "",
690"0f 38 cd 44 c8 12 \tsha256msg2 0x12(%rax,%rcx,8),%xmm0",},
691{{0x0f, 0x38, 0xcd, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
692"0f 38 cd 80 78 56 34 12 \tsha256msg2 0x12345678(%rax),%xmm0",},
693{{0x0f, 0x38, 0xcd, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
694"0f 38 cd 85 78 56 34 12 \tsha256msg2 0x12345678(%rbp),%xmm0",},
695{{0x0f, 0x38, 0xcd, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
696"0f 38 cd 84 01 78 56 34 12 \tsha256msg2 0x12345678(%rcx,%rax,1),%xmm0",},
697{{0x0f, 0x38, 0xcd, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
698"0f 38 cd 84 05 78 56 34 12 \tsha256msg2 0x12345678(%rbp,%rax,1),%xmm0",},
699{{0x0f, 0x38, 0xcd, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
700"0f 38 cd 84 08 78 56 34 12 \tsha256msg2 0x12345678(%rax,%rcx,1),%xmm0",},
701{{0x0f, 0x38, 0xcd, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
702"0f 38 cd 84 c8 78 56 34 12 \tsha256msg2 0x12345678(%rax,%rcx,8),%xmm0",},
703{{0x44, 0x0f, 0x38, 0xcd, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
704"44 0f 38 cd bc c8 78 56 34 12 \tsha256msg2 0x12345678(%rax,%rcx,8),%xmm15",},
705{{0x66, 0x0f, 0xae, 0x38, }, 4, 0, "", "",
706"66 0f ae 38 \tclflushopt (%rax)",},
707{{0x66, 0x41, 0x0f, 0xae, 0x38, }, 5, 0, "", "",
708"66 41 0f ae 38 \tclflushopt (%r8)",},
709{{0x66, 0x0f, 0xae, 0x3c, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
710"66 0f ae 3c 25 78 56 34 12 \tclflushopt 0x12345678",},
711{{0x66, 0x0f, 0xae, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
712"66 0f ae bc c8 78 56 34 12 \tclflushopt 0x12345678(%rax,%rcx,8)",},
713{{0x66, 0x41, 0x0f, 0xae, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
714"66 41 0f ae bc c8 78 56 34 12 \tclflushopt 0x12345678(%r8,%rcx,8)",},
715{{0x0f, 0xae, 0x38, }, 3, 0, "", "",
716"0f ae 38 \tclflush (%rax)",},
717{{0x41, 0x0f, 0xae, 0x38, }, 4, 0, "", "",
718"41 0f ae 38 \tclflush (%r8)",},
719{{0x0f, 0xae, 0xf8, }, 3, 0, "", "",
720"0f ae f8 \tsfence ",},
721{{0x66, 0x0f, 0xae, 0x30, }, 4, 0, "", "",
722"66 0f ae 30 \tclwb (%rax)",},
723{{0x66, 0x41, 0x0f, 0xae, 0x30, }, 5, 0, "", "",
724"66 41 0f ae 30 \tclwb (%r8)",},
725{{0x66, 0x0f, 0xae, 0x34, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
726"66 0f ae 34 25 78 56 34 12 \tclwb 0x12345678",},
727{{0x66, 0x0f, 0xae, 0xb4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
728"66 0f ae b4 c8 78 56 34 12 \tclwb 0x12345678(%rax,%rcx,8)",},
729{{0x66, 0x41, 0x0f, 0xae, 0xb4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
730"66 41 0f ae b4 c8 78 56 34 12 \tclwb 0x12345678(%r8,%rcx,8)",},
731{{0x0f, 0xae, 0x30, }, 3, 0, "", "",
732"0f ae 30 \txsaveopt (%rax)",},
733{{0x41, 0x0f, 0xae, 0x30, }, 4, 0, "", "",
734"41 0f ae 30 \txsaveopt (%r8)",},
735{{0x0f, 0xae, 0xf0, }, 3, 0, "", "",
736"0f ae f0 \tmfence ",},
737{{0x0f, 0xc7, 0x20, }, 3, 0, "", "",
738"0f c7 20 \txsavec (%rax)",},
739{{0x41, 0x0f, 0xc7, 0x20, }, 4, 0, "", "",
740"41 0f c7 20 \txsavec (%r8)",},
741{{0x0f, 0xc7, 0x24, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
742"0f c7 24 25 78 56 34 12 \txsavec 0x12345678",},
743{{0x0f, 0xc7, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
744"0f c7 a4 c8 78 56 34 12 \txsavec 0x12345678(%rax,%rcx,8)",},
745{{0x41, 0x0f, 0xc7, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
746"41 0f c7 a4 c8 78 56 34 12 \txsavec 0x12345678(%r8,%rcx,8)",},
747{{0x0f, 0xc7, 0x28, }, 3, 0, "", "",
748"0f c7 28 \txsaves (%rax)",},
749{{0x41, 0x0f, 0xc7, 0x28, }, 4, 0, "", "",
750"41 0f c7 28 \txsaves (%r8)",},
751{{0x0f, 0xc7, 0x2c, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
752"0f c7 2c 25 78 56 34 12 \txsaves 0x12345678",},
753{{0x0f, 0xc7, 0xac, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
754"0f c7 ac c8 78 56 34 12 \txsaves 0x12345678(%rax,%rcx,8)",},
755{{0x41, 0x0f, 0xc7, 0xac, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
756"41 0f c7 ac c8 78 56 34 12 \txsaves 0x12345678(%r8,%rcx,8)",},
757{{0x0f, 0xc7, 0x18, }, 3, 0, "", "",
758"0f c7 18 \txrstors (%rax)",},
759{{0x41, 0x0f, 0xc7, 0x18, }, 4, 0, "", "",
760"41 0f c7 18 \txrstors (%r8)",},
761{{0x0f, 0xc7, 0x1c, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
762"0f c7 1c 25 78 56 34 12 \txrstors 0x12345678",},
763{{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
764"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",},
765{{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
766"41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",},
767{{0x66, 0x0f, 0xae, 0xf8, }, 4, 0, "", "",
768"66 0f ae f8 \tpcommit ",},
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-src.c b/tools/perf/arch/x86/tests/insn-x86-dat-src.c
new file mode 100644
index 000000000000..41b1b1c62660
--- /dev/null
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-src.c
@@ -0,0 +1,877 @@
1/*
2 * This file contains instructions for testing by the test titled:
3 *
4 * "Test x86 instruction decoder - new instructions"
5 *
6 * Note that the 'Expecting' comment lines are consumed by the
7 * gen-insn-x86-dat.awk script and have the format:
8 *
9 * Expecting: <op> <branch> <rel>
10 *
11 * If this file is changed, remember to run the gen-insn-x86-dat.sh
12 * script and commit the result.
13 *
14 * Refer to insn-x86.c for more details.
15 */
16
17int main(void)
18{
19 /* Following line is a marker for the awk script - do not change */
20 asm volatile("rdtsc"); /* Start here */
21
22#ifdef __x86_64__
23
24 /* bndmk m64, bnd */
25
26 asm volatile("bndmk (%rax), %bnd0");
27 asm volatile("bndmk (%r8), %bnd0");
28 asm volatile("bndmk (0x12345678), %bnd0");
29 asm volatile("bndmk (%rax), %bnd3");
30 asm volatile("bndmk (%rcx,%rax,1), %bnd0");
31 asm volatile("bndmk 0x12345678(,%rax,1), %bnd0");
32 asm volatile("bndmk (%rax,%rcx,1), %bnd0");
33 asm volatile("bndmk (%rax,%rcx,8), %bnd0");
34 asm volatile("bndmk 0x12(%rax), %bnd0");
35 asm volatile("bndmk 0x12(%rbp), %bnd0");
36 asm volatile("bndmk 0x12(%rcx,%rax,1), %bnd0");
37 asm volatile("bndmk 0x12(%rbp,%rax,1), %bnd0");
38 asm volatile("bndmk 0x12(%rax,%rcx,1), %bnd0");
39 asm volatile("bndmk 0x12(%rax,%rcx,8), %bnd0");
40 asm volatile("bndmk 0x12345678(%rax), %bnd0");
41 asm volatile("bndmk 0x12345678(%rbp), %bnd0");
42 asm volatile("bndmk 0x12345678(%rcx,%rax,1), %bnd0");
43 asm volatile("bndmk 0x12345678(%rbp,%rax,1), %bnd0");
44 asm volatile("bndmk 0x12345678(%rax,%rcx,1), %bnd0");
45 asm volatile("bndmk 0x12345678(%rax,%rcx,8), %bnd0");
46
47 /* bndcl r/m64, bnd */
48
49 asm volatile("bndcl (%rax), %bnd0");
50 asm volatile("bndcl (%r8), %bnd0");
51 asm volatile("bndcl (0x12345678), %bnd0");
52 asm volatile("bndcl (%rax), %bnd3");
53 asm volatile("bndcl (%rcx,%rax,1), %bnd0");
54 asm volatile("bndcl 0x12345678(,%rax,1), %bnd0");
55 asm volatile("bndcl (%rax,%rcx,1), %bnd0");
56 asm volatile("bndcl (%rax,%rcx,8), %bnd0");
57 asm volatile("bndcl 0x12(%rax), %bnd0");
58 asm volatile("bndcl 0x12(%rbp), %bnd0");
59 asm volatile("bndcl 0x12(%rcx,%rax,1), %bnd0");
60 asm volatile("bndcl 0x12(%rbp,%rax,1), %bnd0");
61 asm volatile("bndcl 0x12(%rax,%rcx,1), %bnd0");
62 asm volatile("bndcl 0x12(%rax,%rcx,8), %bnd0");
63 asm volatile("bndcl 0x12345678(%rax), %bnd0");
64 asm volatile("bndcl 0x12345678(%rbp), %bnd0");
65 asm volatile("bndcl 0x12345678(%rcx,%rax,1), %bnd0");
66 asm volatile("bndcl 0x12345678(%rbp,%rax,1), %bnd0");
67 asm volatile("bndcl 0x12345678(%rax,%rcx,1), %bnd0");
68 asm volatile("bndcl 0x12345678(%rax,%rcx,8), %bnd0");
69 asm volatile("bndcl %rax, %bnd0");
70
71 /* bndcu r/m64, bnd */
72
73 asm volatile("bndcu (%rax), %bnd0");
74 asm volatile("bndcu (%r8), %bnd0");
75 asm volatile("bndcu (0x12345678), %bnd0");
76 asm volatile("bndcu (%rax), %bnd3");
77 asm volatile("bndcu (%rcx,%rax,1), %bnd0");
78 asm volatile("bndcu 0x12345678(,%rax,1), %bnd0");
79 asm volatile("bndcu (%rax,%rcx,1), %bnd0");
80 asm volatile("bndcu (%rax,%rcx,8), %bnd0");
81 asm volatile("bndcu 0x12(%rax), %bnd0");
82 asm volatile("bndcu 0x12(%rbp), %bnd0");
83 asm volatile("bndcu 0x12(%rcx,%rax,1), %bnd0");
84 asm volatile("bndcu 0x12(%rbp,%rax,1), %bnd0");
85 asm volatile("bndcu 0x12(%rax,%rcx,1), %bnd0");
86 asm volatile("bndcu 0x12(%rax,%rcx,8), %bnd0");
87 asm volatile("bndcu 0x12345678(%rax), %bnd0");
88 asm volatile("bndcu 0x12345678(%rbp), %bnd0");
89 asm volatile("bndcu 0x12345678(%rcx,%rax,1), %bnd0");
90 asm volatile("bndcu 0x12345678(%rbp,%rax,1), %bnd0");
91 asm volatile("bndcu 0x12345678(%rax,%rcx,1), %bnd0");
92 asm volatile("bndcu 0x12345678(%rax,%rcx,8), %bnd0");
93 asm volatile("bndcu %rax, %bnd0");
94
95 /* bndcn r/m64, bnd */
96
97 asm volatile("bndcn (%rax), %bnd0");
98 asm volatile("bndcn (%r8), %bnd0");
99 asm volatile("bndcn (0x12345678), %bnd0");
100 asm volatile("bndcn (%rax), %bnd3");
101 asm volatile("bndcn (%rcx,%rax,1), %bnd0");
102 asm volatile("bndcn 0x12345678(,%rax,1), %bnd0");
103 asm volatile("bndcn (%rax,%rcx,1), %bnd0");
104 asm volatile("bndcn (%rax,%rcx,8), %bnd0");
105 asm volatile("bndcn 0x12(%rax), %bnd0");
106 asm volatile("bndcn 0x12(%rbp), %bnd0");
107 asm volatile("bndcn 0x12(%rcx,%rax,1), %bnd0");
108 asm volatile("bndcn 0x12(%rbp,%rax,1), %bnd0");
109 asm volatile("bndcn 0x12(%rax,%rcx,1), %bnd0");
110 asm volatile("bndcn 0x12(%rax,%rcx,8), %bnd0");
111 asm volatile("bndcn 0x12345678(%rax), %bnd0");
112 asm volatile("bndcn 0x12345678(%rbp), %bnd0");
113 asm volatile("bndcn 0x12345678(%rcx,%rax,1), %bnd0");
114 asm volatile("bndcn 0x12345678(%rbp,%rax,1), %bnd0");
115 asm volatile("bndcn 0x12345678(%rax,%rcx,1), %bnd0");
116 asm volatile("bndcn 0x12345678(%rax,%rcx,8), %bnd0");
117 asm volatile("bndcn %rax, %bnd0");
118
119 /* bndmov m128, bnd */
120
121 asm volatile("bndmov (%rax), %bnd0");
122 asm volatile("bndmov (%r8), %bnd0");
123 asm volatile("bndmov (0x12345678), %bnd0");
124 asm volatile("bndmov (%rax), %bnd3");
125 asm volatile("bndmov (%rcx,%rax,1), %bnd0");
126 asm volatile("bndmov 0x12345678(,%rax,1), %bnd0");
127 asm volatile("bndmov (%rax,%rcx,1), %bnd0");
128 asm volatile("bndmov (%rax,%rcx,8), %bnd0");
129 asm volatile("bndmov 0x12(%rax), %bnd0");
130 asm volatile("bndmov 0x12(%rbp), %bnd0");
131 asm volatile("bndmov 0x12(%rcx,%rax,1), %bnd0");
132 asm volatile("bndmov 0x12(%rbp,%rax,1), %bnd0");
133 asm volatile("bndmov 0x12(%rax,%rcx,1), %bnd0");
134 asm volatile("bndmov 0x12(%rax,%rcx,8), %bnd0");
135 asm volatile("bndmov 0x12345678(%rax), %bnd0");
136 asm volatile("bndmov 0x12345678(%rbp), %bnd0");
137 asm volatile("bndmov 0x12345678(%rcx,%rax,1), %bnd0");
138 asm volatile("bndmov 0x12345678(%rbp,%rax,1), %bnd0");
139 asm volatile("bndmov 0x12345678(%rax,%rcx,1), %bnd0");
140 asm volatile("bndmov 0x12345678(%rax,%rcx,8), %bnd0");
141
142 /* bndmov bnd, m128 */
143
144 asm volatile("bndmov %bnd0, (%rax)");
145 asm volatile("bndmov %bnd0, (%r8)");
146 asm volatile("bndmov %bnd0, (0x12345678)");
147 asm volatile("bndmov %bnd3, (%rax)");
148 asm volatile("bndmov %bnd0, (%rcx,%rax,1)");
149 asm volatile("bndmov %bnd0, 0x12345678(,%rax,1)");
150 asm volatile("bndmov %bnd0, (%rax,%rcx,1)");
151 asm volatile("bndmov %bnd0, (%rax,%rcx,8)");
152 asm volatile("bndmov %bnd0, 0x12(%rax)");
153 asm volatile("bndmov %bnd0, 0x12(%rbp)");
154 asm volatile("bndmov %bnd0, 0x12(%rcx,%rax,1)");
155 asm volatile("bndmov %bnd0, 0x12(%rbp,%rax,1)");
156 asm volatile("bndmov %bnd0, 0x12(%rax,%rcx,1)");
157 asm volatile("bndmov %bnd0, 0x12(%rax,%rcx,8)");
158 asm volatile("bndmov %bnd0, 0x12345678(%rax)");
159 asm volatile("bndmov %bnd0, 0x12345678(%rbp)");
160 asm volatile("bndmov %bnd0, 0x12345678(%rcx,%rax,1)");
161 asm volatile("bndmov %bnd0, 0x12345678(%rbp,%rax,1)");
162 asm volatile("bndmov %bnd0, 0x12345678(%rax,%rcx,1)");
163 asm volatile("bndmov %bnd0, 0x12345678(%rax,%rcx,8)");
164
165 /* bndmov bnd2, bnd1 */
166
167 asm volatile("bndmov %bnd0, %bnd1");
168 asm volatile("bndmov %bnd1, %bnd0");
169
170 /* bndldx mib, bnd */
171
172 asm volatile("bndldx (%rax), %bnd0");
173 asm volatile("bndldx (%r8), %bnd0");
174 asm volatile("bndldx (0x12345678), %bnd0");
175 asm volatile("bndldx (%rax), %bnd3");
176 asm volatile("bndldx (%rcx,%rax,1), %bnd0");
177 asm volatile("bndldx 0x12345678(,%rax,1), %bnd0");
178 asm volatile("bndldx (%rax,%rcx,1), %bnd0");
179 asm volatile("bndldx 0x12(%rax), %bnd0");
180 asm volatile("bndldx 0x12(%rbp), %bnd0");
181 asm volatile("bndldx 0x12(%rcx,%rax,1), %bnd0");
182 asm volatile("bndldx 0x12(%rbp,%rax,1), %bnd0");
183 asm volatile("bndldx 0x12(%rax,%rcx,1), %bnd0");
184 asm volatile("bndldx 0x12345678(%rax), %bnd0");
185 asm volatile("bndldx 0x12345678(%rbp), %bnd0");
186 asm volatile("bndldx 0x12345678(%rcx,%rax,1), %bnd0");
187 asm volatile("bndldx 0x12345678(%rbp,%rax,1), %bnd0");
188 asm volatile("bndldx 0x12345678(%rax,%rcx,1), %bnd0");
189
190 /* bndstx bnd, mib */
191
192 asm volatile("bndstx %bnd0, (%rax)");
193 asm volatile("bndstx %bnd0, (%r8)");
194 asm volatile("bndstx %bnd0, (0x12345678)");
195 asm volatile("bndstx %bnd3, (%rax)");
196 asm volatile("bndstx %bnd0, (%rcx,%rax,1)");
197 asm volatile("bndstx %bnd0, 0x12345678(,%rax,1)");
198 asm volatile("bndstx %bnd0, (%rax,%rcx,1)");
199 asm volatile("bndstx %bnd0, 0x12(%rax)");
200 asm volatile("bndstx %bnd0, 0x12(%rbp)");
201 asm volatile("bndstx %bnd0, 0x12(%rcx,%rax,1)");
202 asm volatile("bndstx %bnd0, 0x12(%rbp,%rax,1)");
203 asm volatile("bndstx %bnd0, 0x12(%rax,%rcx,1)");
204 asm volatile("bndstx %bnd0, 0x12345678(%rax)");
205 asm volatile("bndstx %bnd0, 0x12345678(%rbp)");
206 asm volatile("bndstx %bnd0, 0x12345678(%rcx,%rax,1)");
207 asm volatile("bndstx %bnd0, 0x12345678(%rbp,%rax,1)");
208 asm volatile("bndstx %bnd0, 0x12345678(%rax,%rcx,1)");
209
210 /* bnd prefix on call, ret, jmp and all jcc */
211
212 asm volatile("bnd call label1"); /* Expecting: call unconditional 0 */
213 asm volatile("bnd call *(%eax)"); /* Expecting: call indirect 0 */
214 asm volatile("bnd ret"); /* Expecting: ret indirect 0 */
215 asm volatile("bnd jmp label1"); /* Expecting: jmp unconditional 0 */
216 asm volatile("bnd jmp label1"); /* Expecting: jmp unconditional 0 */
217 asm volatile("bnd jmp *(%ecx)"); /* Expecting: jmp indirect 0 */
218 asm volatile("bnd jne label1"); /* Expecting: jcc conditional 0 */
219
220 /* sha1rnds4 imm8, xmm2/m128, xmm1 */
221
222 asm volatile("sha1rnds4 $0x0, %xmm1, %xmm0");
223 asm volatile("sha1rnds4 $0x91, %xmm7, %xmm2");
224 asm volatile("sha1rnds4 $0x91, %xmm8, %xmm0");
225 asm volatile("sha1rnds4 $0x91, %xmm7, %xmm8");
226 asm volatile("sha1rnds4 $0x91, %xmm15, %xmm8");
227 asm volatile("sha1rnds4 $0x91, (%rax), %xmm0");
228 asm volatile("sha1rnds4 $0x91, (%r8), %xmm0");
229 asm volatile("sha1rnds4 $0x91, (0x12345678), %xmm0");
230 asm volatile("sha1rnds4 $0x91, (%rax), %xmm3");
231 asm volatile("sha1rnds4 $0x91, (%rcx,%rax,1), %xmm0");
232 asm volatile("sha1rnds4 $0x91, 0x12345678(,%rax,1), %xmm0");
233 asm volatile("sha1rnds4 $0x91, (%rax,%rcx,1), %xmm0");
234 asm volatile("sha1rnds4 $0x91, (%rax,%rcx,8), %xmm0");
235 asm volatile("sha1rnds4 $0x91, 0x12(%rax), %xmm0");
236 asm volatile("sha1rnds4 $0x91, 0x12(%rbp), %xmm0");
237 asm volatile("sha1rnds4 $0x91, 0x12(%rcx,%rax,1), %xmm0");
238 asm volatile("sha1rnds4 $0x91, 0x12(%rbp,%rax,1), %xmm0");
239 asm volatile("sha1rnds4 $0x91, 0x12(%rax,%rcx,1), %xmm0");
240 asm volatile("sha1rnds4 $0x91, 0x12(%rax,%rcx,8), %xmm0");
241 asm volatile("sha1rnds4 $0x91, 0x12345678(%rax), %xmm0");
242 asm volatile("sha1rnds4 $0x91, 0x12345678(%rbp), %xmm0");
243 asm volatile("sha1rnds4 $0x91, 0x12345678(%rcx,%rax,1), %xmm0");
244 asm volatile("sha1rnds4 $0x91, 0x12345678(%rbp,%rax,1), %xmm0");
245 asm volatile("sha1rnds4 $0x91, 0x12345678(%rax,%rcx,1), %xmm0");
246 asm volatile("sha1rnds4 $0x91, 0x12345678(%rax,%rcx,8), %xmm0");
247 asm volatile("sha1rnds4 $0x91, 0x12345678(%rax,%rcx,8), %xmm15");
248
249 /* sha1nexte xmm2/m128, xmm1 */
250
251 asm volatile("sha1nexte %xmm1, %xmm0");
252 asm volatile("sha1nexte %xmm7, %xmm2");
253 asm volatile("sha1nexte %xmm8, %xmm0");
254 asm volatile("sha1nexte %xmm7, %xmm8");
255 asm volatile("sha1nexte %xmm15, %xmm8");
256 asm volatile("sha1nexte (%rax), %xmm0");
257 asm volatile("sha1nexte (%r8), %xmm0");
258 asm volatile("sha1nexte (0x12345678), %xmm0");
259 asm volatile("sha1nexte (%rax), %xmm3");
260 asm volatile("sha1nexte (%rcx,%rax,1), %xmm0");
261 asm volatile("sha1nexte 0x12345678(,%rax,1), %xmm0");
262 asm volatile("sha1nexte (%rax,%rcx,1), %xmm0");
263 asm volatile("sha1nexte (%rax,%rcx,8), %xmm0");
264 asm volatile("sha1nexte 0x12(%rax), %xmm0");
265 asm volatile("sha1nexte 0x12(%rbp), %xmm0");
266 asm volatile("sha1nexte 0x12(%rcx,%rax,1), %xmm0");
267 asm volatile("sha1nexte 0x12(%rbp,%rax,1), %xmm0");
268 asm volatile("sha1nexte 0x12(%rax,%rcx,1), %xmm0");
269 asm volatile("sha1nexte 0x12(%rax,%rcx,8), %xmm0");
270 asm volatile("sha1nexte 0x12345678(%rax), %xmm0");
271 asm volatile("sha1nexte 0x12345678(%rbp), %xmm0");
272 asm volatile("sha1nexte 0x12345678(%rcx,%rax,1), %xmm0");
273 asm volatile("sha1nexte 0x12345678(%rbp,%rax,1), %xmm0");
274 asm volatile("sha1nexte 0x12345678(%rax,%rcx,1), %xmm0");
275 asm volatile("sha1nexte 0x12345678(%rax,%rcx,8), %xmm0");
276 asm volatile("sha1nexte 0x12345678(%rax,%rcx,8), %xmm15");
277
278 /* sha1msg1 xmm2/m128, xmm1 */
279
280 asm volatile("sha1msg1 %xmm1, %xmm0");
281 asm volatile("sha1msg1 %xmm7, %xmm2");
282 asm volatile("sha1msg1 %xmm8, %xmm0");
283 asm volatile("sha1msg1 %xmm7, %xmm8");
284 asm volatile("sha1msg1 %xmm15, %xmm8");
285 asm volatile("sha1msg1 (%rax), %xmm0");
286 asm volatile("sha1msg1 (%r8), %xmm0");
287 asm volatile("sha1msg1 (0x12345678), %xmm0");
288 asm volatile("sha1msg1 (%rax), %xmm3");
289 asm volatile("sha1msg1 (%rcx,%rax,1), %xmm0");
290 asm volatile("sha1msg1 0x12345678(,%rax,1), %xmm0");
291 asm volatile("sha1msg1 (%rax,%rcx,1), %xmm0");
292 asm volatile("sha1msg1 (%rax,%rcx,8), %xmm0");
293 asm volatile("sha1msg1 0x12(%rax), %xmm0");
294 asm volatile("sha1msg1 0x12(%rbp), %xmm0");
295 asm volatile("sha1msg1 0x12(%rcx,%rax,1), %xmm0");
296 asm volatile("sha1msg1 0x12(%rbp,%rax,1), %xmm0");
297 asm volatile("sha1msg1 0x12(%rax,%rcx,1), %xmm0");
298 asm volatile("sha1msg1 0x12(%rax,%rcx,8), %xmm0");
299 asm volatile("sha1msg1 0x12345678(%rax), %xmm0");
300 asm volatile("sha1msg1 0x12345678(%rbp), %xmm0");
301 asm volatile("sha1msg1 0x12345678(%rcx,%rax,1), %xmm0");
302 asm volatile("sha1msg1 0x12345678(%rbp,%rax,1), %xmm0");
303 asm volatile("sha1msg1 0x12345678(%rax,%rcx,1), %xmm0");
304 asm volatile("sha1msg1 0x12345678(%rax,%rcx,8), %xmm0");
305 asm volatile("sha1msg1 0x12345678(%rax,%rcx,8), %xmm15");
306
307 /* sha1msg2 xmm2/m128, xmm1 */
308
309 asm volatile("sha1msg2 %xmm1, %xmm0");
310 asm volatile("sha1msg2 %xmm7, %xmm2");
311 asm volatile("sha1msg2 %xmm8, %xmm0");
312 asm volatile("sha1msg2 %xmm7, %xmm8");
313 asm volatile("sha1msg2 %xmm15, %xmm8");
314 asm volatile("sha1msg2 (%rax), %xmm0");
315 asm volatile("sha1msg2 (%r8), %xmm0");
316 asm volatile("sha1msg2 (0x12345678), %xmm0");
317 asm volatile("sha1msg2 (%rax), %xmm3");
318 asm volatile("sha1msg2 (%rcx,%rax,1), %xmm0");
319 asm volatile("sha1msg2 0x12345678(,%rax,1), %xmm0");
320 asm volatile("sha1msg2 (%rax,%rcx,1), %xmm0");
321 asm volatile("sha1msg2 (%rax,%rcx,8), %xmm0");
322 asm volatile("sha1msg2 0x12(%rax), %xmm0");
323 asm volatile("sha1msg2 0x12(%rbp), %xmm0");
324 asm volatile("sha1msg2 0x12(%rcx,%rax,1), %xmm0");
325 asm volatile("sha1msg2 0x12(%rbp,%rax,1), %xmm0");
326 asm volatile("sha1msg2 0x12(%rax,%rcx,1), %xmm0");
327 asm volatile("sha1msg2 0x12(%rax,%rcx,8), %xmm0");
328 asm volatile("sha1msg2 0x12345678(%rax), %xmm0");
329 asm volatile("sha1msg2 0x12345678(%rbp), %xmm0");
330 asm volatile("sha1msg2 0x12345678(%rcx,%rax,1), %xmm0");
331 asm volatile("sha1msg2 0x12345678(%rbp,%rax,1), %xmm0");
332 asm volatile("sha1msg2 0x12345678(%rax,%rcx,1), %xmm0");
333 asm volatile("sha1msg2 0x12345678(%rax,%rcx,8), %xmm0");
334 asm volatile("sha1msg2 0x12345678(%rax,%rcx,8), %xmm15");
335
336 /* sha256rnds2 <XMM0>, xmm2/m128, xmm1 */
337 /* Note sha256rnds2 has an implicit operand 'xmm0' */
338
339 asm volatile("sha256rnds2 %xmm4, %xmm1");
340 asm volatile("sha256rnds2 %xmm7, %xmm2");
341 asm volatile("sha256rnds2 %xmm8, %xmm1");
342 asm volatile("sha256rnds2 %xmm7, %xmm8");
343 asm volatile("sha256rnds2 %xmm15, %xmm8");
344 asm volatile("sha256rnds2 (%rax), %xmm1");
345 asm volatile("sha256rnds2 (%r8), %xmm1");
346 asm volatile("sha256rnds2 (0x12345678), %xmm1");
347 asm volatile("sha256rnds2 (%rax), %xmm3");
348 asm volatile("sha256rnds2 (%rcx,%rax,1), %xmm1");
349 asm volatile("sha256rnds2 0x12345678(,%rax,1), %xmm1");
350 asm volatile("sha256rnds2 (%rax,%rcx,1), %xmm1");
351 asm volatile("sha256rnds2 (%rax,%rcx,8), %xmm1");
352 asm volatile("sha256rnds2 0x12(%rax), %xmm1");
353 asm volatile("sha256rnds2 0x12(%rbp), %xmm1");
354 asm volatile("sha256rnds2 0x12(%rcx,%rax,1), %xmm1");
355 asm volatile("sha256rnds2 0x12(%rbp,%rax,1), %xmm1");
356 asm volatile("sha256rnds2 0x12(%rax,%rcx,1), %xmm1");
357 asm volatile("sha256rnds2 0x12(%rax,%rcx,8), %xmm1");
358 asm volatile("sha256rnds2 0x12345678(%rax), %xmm1");
359 asm volatile("sha256rnds2 0x12345678(%rbp), %xmm1");
360 asm volatile("sha256rnds2 0x12345678(%rcx,%rax,1), %xmm1");
361 asm volatile("sha256rnds2 0x12345678(%rbp,%rax,1), %xmm1");
362 asm volatile("sha256rnds2 0x12345678(%rax,%rcx,1), %xmm1");
363 asm volatile("sha256rnds2 0x12345678(%rax,%rcx,8), %xmm1");
364 asm volatile("sha256rnds2 0x12345678(%rax,%rcx,8), %xmm15");
365
366 /* sha256msg1 xmm2/m128, xmm1 */
367
368 asm volatile("sha256msg1 %xmm1, %xmm0");
369 asm volatile("sha256msg1 %xmm7, %xmm2");
370 asm volatile("sha256msg1 %xmm8, %xmm0");
371 asm volatile("sha256msg1 %xmm7, %xmm8");
372 asm volatile("sha256msg1 %xmm15, %xmm8");
373 asm volatile("sha256msg1 (%rax), %xmm0");
374 asm volatile("sha256msg1 (%r8), %xmm0");
375 asm volatile("sha256msg1 (0x12345678), %xmm0");
376 asm volatile("sha256msg1 (%rax), %xmm3");
377 asm volatile("sha256msg1 (%rcx,%rax,1), %xmm0");
378 asm volatile("sha256msg1 0x12345678(,%rax,1), %xmm0");
379 asm volatile("sha256msg1 (%rax,%rcx,1), %xmm0");
380 asm volatile("sha256msg1 (%rax,%rcx,8), %xmm0");
381 asm volatile("sha256msg1 0x12(%rax), %xmm0");
382 asm volatile("sha256msg1 0x12(%rbp), %xmm0");
383 asm volatile("sha256msg1 0x12(%rcx,%rax,1), %xmm0");
384 asm volatile("sha256msg1 0x12(%rbp,%rax,1), %xmm0");
385 asm volatile("sha256msg1 0x12(%rax,%rcx,1), %xmm0");
386 asm volatile("sha256msg1 0x12(%rax,%rcx,8), %xmm0");
387 asm volatile("sha256msg1 0x12345678(%rax), %xmm0");
388 asm volatile("sha256msg1 0x12345678(%rbp), %xmm0");
389 asm volatile("sha256msg1 0x12345678(%rcx,%rax,1), %xmm0");
390 asm volatile("sha256msg1 0x12345678(%rbp,%rax,1), %xmm0");
391 asm volatile("sha256msg1 0x12345678(%rax,%rcx,1), %xmm0");
392 asm volatile("sha256msg1 0x12345678(%rax,%rcx,8), %xmm0");
393 asm volatile("sha256msg1 0x12345678(%rax,%rcx,8), %xmm15");
394
395 /* sha256msg2 xmm2/m128, xmm1 */
396
397 asm volatile("sha256msg2 %xmm1, %xmm0");
398 asm volatile("sha256msg2 %xmm7, %xmm2");
399 asm volatile("sha256msg2 %xmm8, %xmm0");
400 asm volatile("sha256msg2 %xmm7, %xmm8");
401 asm volatile("sha256msg2 %xmm15, %xmm8");
402 asm volatile("sha256msg2 (%rax), %xmm0");
403 asm volatile("sha256msg2 (%r8), %xmm0");
404 asm volatile("sha256msg2 (0x12345678), %xmm0");
405 asm volatile("sha256msg2 (%rax), %xmm3");
406 asm volatile("sha256msg2 (%rcx,%rax,1), %xmm0");
407 asm volatile("sha256msg2 0x12345678(,%rax,1), %xmm0");
408 asm volatile("sha256msg2 (%rax,%rcx,1), %xmm0");
409 asm volatile("sha256msg2 (%rax,%rcx,8), %xmm0");
410 asm volatile("sha256msg2 0x12(%rax), %xmm0");
411 asm volatile("sha256msg2 0x12(%rbp), %xmm0");
412 asm volatile("sha256msg2 0x12(%rcx,%rax,1), %xmm0");
413 asm volatile("sha256msg2 0x12(%rbp,%rax,1), %xmm0");
414 asm volatile("sha256msg2 0x12(%rax,%rcx,1), %xmm0");
415 asm volatile("sha256msg2 0x12(%rax,%rcx,8), %xmm0");
416 asm volatile("sha256msg2 0x12345678(%rax), %xmm0");
417 asm volatile("sha256msg2 0x12345678(%rbp), %xmm0");
418 asm volatile("sha256msg2 0x12345678(%rcx,%rax,1), %xmm0");
419 asm volatile("sha256msg2 0x12345678(%rbp,%rax,1), %xmm0");
420 asm volatile("sha256msg2 0x12345678(%rax,%rcx,1), %xmm0");
421 asm volatile("sha256msg2 0x12345678(%rax,%rcx,8), %xmm0");
422 asm volatile("sha256msg2 0x12345678(%rax,%rcx,8), %xmm15");
423
424 /* clflushopt m8 */
425
426 asm volatile("clflushopt (%rax)");
427 asm volatile("clflushopt (%r8)");
428 asm volatile("clflushopt (0x12345678)");
429 asm volatile("clflushopt 0x12345678(%rax,%rcx,8)");
430 asm volatile("clflushopt 0x12345678(%r8,%rcx,8)");
431 /* Also check instructions in the same group encoding as clflushopt */
432 asm volatile("clflush (%rax)");
433 asm volatile("clflush (%r8)");
434 asm volatile("sfence");
435
436 /* clwb m8 */
437
438 asm volatile("clwb (%rax)");
439 asm volatile("clwb (%r8)");
440 asm volatile("clwb (0x12345678)");
441 asm volatile("clwb 0x12345678(%rax,%rcx,8)");
442 asm volatile("clwb 0x12345678(%r8,%rcx,8)");
443 /* Also check instructions in the same group encoding as clwb */
444 asm volatile("xsaveopt (%rax)");
445 asm volatile("xsaveopt (%r8)");
446 asm volatile("mfence");
447
448 /* xsavec mem */
449
450 asm volatile("xsavec (%rax)");
451 asm volatile("xsavec (%r8)");
452 asm volatile("xsavec (0x12345678)");
453 asm volatile("xsavec 0x12345678(%rax,%rcx,8)");
454 asm volatile("xsavec 0x12345678(%r8,%rcx,8)");
455
456 /* xsaves mem */
457
458 asm volatile("xsaves (%rax)");
459 asm volatile("xsaves (%r8)");
460 asm volatile("xsaves (0x12345678)");
461 asm volatile("xsaves 0x12345678(%rax,%rcx,8)");
462 asm volatile("xsaves 0x12345678(%r8,%rcx,8)");
463
464 /* xrstors mem */
465
466 asm volatile("xrstors (%rax)");
467 asm volatile("xrstors (%r8)");
468 asm volatile("xrstors (0x12345678)");
469 asm volatile("xrstors 0x12345678(%rax,%rcx,8)");
470 asm volatile("xrstors 0x12345678(%r8,%rcx,8)");
471
472#else /* #ifdef __x86_64__ */
473
474 /* bndmk m32, bnd */
475
476 asm volatile("bndmk (%eax), %bnd0");
477 asm volatile("bndmk (0x12345678), %bnd0");
478 asm volatile("bndmk (%eax), %bnd3");
479 asm volatile("bndmk (%ecx,%eax,1), %bnd0");
480 asm volatile("bndmk 0x12345678(,%eax,1), %bnd0");
481 asm volatile("bndmk (%eax,%ecx,1), %bnd0");
482 asm volatile("bndmk (%eax,%ecx,8), %bnd0");
483 asm volatile("bndmk 0x12(%eax), %bnd0");
484 asm volatile("bndmk 0x12(%ebp), %bnd0");
485 asm volatile("bndmk 0x12(%ecx,%eax,1), %bnd0");
486 asm volatile("bndmk 0x12(%ebp,%eax,1), %bnd0");
487 asm volatile("bndmk 0x12(%eax,%ecx,1), %bnd0");
488 asm volatile("bndmk 0x12(%eax,%ecx,8), %bnd0");
489 asm volatile("bndmk 0x12345678(%eax), %bnd0");
490 asm volatile("bndmk 0x12345678(%ebp), %bnd0");
491 asm volatile("bndmk 0x12345678(%ecx,%eax,1), %bnd0");
492 asm volatile("bndmk 0x12345678(%ebp,%eax,1), %bnd0");
493 asm volatile("bndmk 0x12345678(%eax,%ecx,1), %bnd0");
494 asm volatile("bndmk 0x12345678(%eax,%ecx,8), %bnd0");
495
496 /* bndcl r/m32, bnd */
497
498 asm volatile("bndcl (%eax), %bnd0");
499 asm volatile("bndcl (0x12345678), %bnd0");
500 asm volatile("bndcl (%eax), %bnd3");
501 asm volatile("bndcl (%ecx,%eax,1), %bnd0");
502 asm volatile("bndcl 0x12345678(,%eax,1), %bnd0");
503 asm volatile("bndcl (%eax,%ecx,1), %bnd0");
504 asm volatile("bndcl (%eax,%ecx,8), %bnd0");
505 asm volatile("bndcl 0x12(%eax), %bnd0");
506 asm volatile("bndcl 0x12(%ebp), %bnd0");
507 asm volatile("bndcl 0x12(%ecx,%eax,1), %bnd0");
508 asm volatile("bndcl 0x12(%ebp,%eax,1), %bnd0");
509 asm volatile("bndcl 0x12(%eax,%ecx,1), %bnd0");
510 asm volatile("bndcl 0x12(%eax,%ecx,8), %bnd0");
511 asm volatile("bndcl 0x12345678(%eax), %bnd0");
512 asm volatile("bndcl 0x12345678(%ebp), %bnd0");
513 asm volatile("bndcl 0x12345678(%ecx,%eax,1), %bnd0");
514 asm volatile("bndcl 0x12345678(%ebp,%eax,1), %bnd0");
515 asm volatile("bndcl 0x12345678(%eax,%ecx,1), %bnd0");
516 asm volatile("bndcl 0x12345678(%eax,%ecx,8), %bnd0");
517 asm volatile("bndcl %eax, %bnd0");
518
519 /* bndcu r/m32, bnd */
520
521 asm volatile("bndcu (%eax), %bnd0");
522 asm volatile("bndcu (0x12345678), %bnd0");
523 asm volatile("bndcu (%eax), %bnd3");
524 asm volatile("bndcu (%ecx,%eax,1), %bnd0");
525 asm volatile("bndcu 0x12345678(,%eax,1), %bnd0");
526 asm volatile("bndcu (%eax,%ecx,1), %bnd0");
527 asm volatile("bndcu (%eax,%ecx,8), %bnd0");
528 asm volatile("bndcu 0x12(%eax), %bnd0");
529 asm volatile("bndcu 0x12(%ebp), %bnd0");
530 asm volatile("bndcu 0x12(%ecx,%eax,1), %bnd0");
531 asm volatile("bndcu 0x12(%ebp,%eax,1), %bnd0");
532 asm volatile("bndcu 0x12(%eax,%ecx,1), %bnd0");
533 asm volatile("bndcu 0x12(%eax,%ecx,8), %bnd0");
534 asm volatile("bndcu 0x12345678(%eax), %bnd0");
535 asm volatile("bndcu 0x12345678(%ebp), %bnd0");
536 asm volatile("bndcu 0x12345678(%ecx,%eax,1), %bnd0");
537 asm volatile("bndcu 0x12345678(%ebp,%eax,1), %bnd0");
538 asm volatile("bndcu 0x12345678(%eax,%ecx,1), %bnd0");
539 asm volatile("bndcu 0x12345678(%eax,%ecx,8), %bnd0");
540 asm volatile("bndcu %eax, %bnd0");
541
542 /* bndcn r/m32, bnd */
543
544 asm volatile("bndcn (%eax), %bnd0");
545 asm volatile("bndcn (0x12345678), %bnd0");
546 asm volatile("bndcn (%eax), %bnd3");
547 asm volatile("bndcn (%ecx,%eax,1), %bnd0");
548 asm volatile("bndcn 0x12345678(,%eax,1), %bnd0");
549 asm volatile("bndcn (%eax,%ecx,1), %bnd0");
550 asm volatile("bndcn (%eax,%ecx,8), %bnd0");
551 asm volatile("bndcn 0x12(%eax), %bnd0");
552 asm volatile("bndcn 0x12(%ebp), %bnd0");
553 asm volatile("bndcn 0x12(%ecx,%eax,1), %bnd0");
554 asm volatile("bndcn 0x12(%ebp,%eax,1), %bnd0");
555 asm volatile("bndcn 0x12(%eax,%ecx,1), %bnd0");
556 asm volatile("bndcn 0x12(%eax,%ecx,8), %bnd0");
557 asm volatile("bndcn 0x12345678(%eax), %bnd0");
558 asm volatile("bndcn 0x12345678(%ebp), %bnd0");
559 asm volatile("bndcn 0x12345678(%ecx,%eax,1), %bnd0");
560 asm volatile("bndcn 0x12345678(%ebp,%eax,1), %bnd0");
561 asm volatile("bndcn 0x12345678(%eax,%ecx,1), %bnd0");
562 asm volatile("bndcn 0x12345678(%eax,%ecx,8), %bnd0");
563 asm volatile("bndcn %eax, %bnd0");
564
565 /* bndmov m64, bnd */
566
567 asm volatile("bndmov (%eax), %bnd0");
568 asm volatile("bndmov (0x12345678), %bnd0");
569 asm volatile("bndmov (%eax), %bnd3");
570 asm volatile("bndmov (%ecx,%eax,1), %bnd0");
571 asm volatile("bndmov 0x12345678(,%eax,1), %bnd0");
572 asm volatile("bndmov (%eax,%ecx,1), %bnd0");
573 asm volatile("bndmov (%eax,%ecx,8), %bnd0");
574 asm volatile("bndmov 0x12(%eax), %bnd0");
575 asm volatile("bndmov 0x12(%ebp), %bnd0");
576 asm volatile("bndmov 0x12(%ecx,%eax,1), %bnd0");
577 asm volatile("bndmov 0x12(%ebp,%eax,1), %bnd0");
578 asm volatile("bndmov 0x12(%eax,%ecx,1), %bnd0");
579 asm volatile("bndmov 0x12(%eax,%ecx,8), %bnd0");
580 asm volatile("bndmov 0x12345678(%eax), %bnd0");
581 asm volatile("bndmov 0x12345678(%ebp), %bnd0");
582 asm volatile("bndmov 0x12345678(%ecx,%eax,1), %bnd0");
583 asm volatile("bndmov 0x12345678(%ebp,%eax,1), %bnd0");
584 asm volatile("bndmov 0x12345678(%eax,%ecx,1), %bnd0");
585 asm volatile("bndmov 0x12345678(%eax,%ecx,8), %bnd0");
586
587 /* bndmov bnd, m64 */
588
589 asm volatile("bndmov %bnd0, (%eax)");
590 asm volatile("bndmov %bnd0, (0x12345678)");
591 asm volatile("bndmov %bnd3, (%eax)");
592 asm volatile("bndmov %bnd0, (%ecx,%eax,1)");
593 asm volatile("bndmov %bnd0, 0x12345678(,%eax,1)");
594 asm volatile("bndmov %bnd0, (%eax,%ecx,1)");
595 asm volatile("bndmov %bnd0, (%eax,%ecx,8)");
596 asm volatile("bndmov %bnd0, 0x12(%eax)");
597 asm volatile("bndmov %bnd0, 0x12(%ebp)");
598 asm volatile("bndmov %bnd0, 0x12(%ecx,%eax,1)");
599 asm volatile("bndmov %bnd0, 0x12(%ebp,%eax,1)");
600 asm volatile("bndmov %bnd0, 0x12(%eax,%ecx,1)");
601 asm volatile("bndmov %bnd0, 0x12(%eax,%ecx,8)");
602 asm volatile("bndmov %bnd0, 0x12345678(%eax)");
603 asm volatile("bndmov %bnd0, 0x12345678(%ebp)");
604 asm volatile("bndmov %bnd0, 0x12345678(%ecx,%eax,1)");
605 asm volatile("bndmov %bnd0, 0x12345678(%ebp,%eax,1)");
606 asm volatile("bndmov %bnd0, 0x12345678(%eax,%ecx,1)");
607 asm volatile("bndmov %bnd0, 0x12345678(%eax,%ecx,8)");
608
609 /* bndmov bnd2, bnd1 */
610
611 asm volatile("bndmov %bnd0, %bnd1");
612 asm volatile("bndmov %bnd1, %bnd0");
613
614 /* bndldx mib, bnd */
615
616 asm volatile("bndldx (%eax), %bnd0");
617 asm volatile("bndldx (0x12345678), %bnd0");
618 asm volatile("bndldx (%eax), %bnd3");
619 asm volatile("bndldx (%ecx,%eax,1), %bnd0");
620 asm volatile("bndldx 0x12345678(,%eax,1), %bnd0");
621 asm volatile("bndldx (%eax,%ecx,1), %bnd0");
622 asm volatile("bndldx 0x12(%eax), %bnd0");
623 asm volatile("bndldx 0x12(%ebp), %bnd0");
624 asm volatile("bndldx 0x12(%ecx,%eax,1), %bnd0");
625 asm volatile("bndldx 0x12(%ebp,%eax,1), %bnd0");
626 asm volatile("bndldx 0x12(%eax,%ecx,1), %bnd0");
627 asm volatile("bndldx 0x12345678(%eax), %bnd0");
628 asm volatile("bndldx 0x12345678(%ebp), %bnd0");
629 asm volatile("bndldx 0x12345678(%ecx,%eax,1), %bnd0");
630 asm volatile("bndldx 0x12345678(%ebp,%eax,1), %bnd0");
631 asm volatile("bndldx 0x12345678(%eax,%ecx,1), %bnd0");
632
633 /* bndstx bnd, mib */
634
635 asm volatile("bndstx %bnd0, (%eax)");
636 asm volatile("bndstx %bnd0, (0x12345678)");
637 asm volatile("bndstx %bnd3, (%eax)");
638 asm volatile("bndstx %bnd0, (%ecx,%eax,1)");
639 asm volatile("bndstx %bnd0, 0x12345678(,%eax,1)");
640 asm volatile("bndstx %bnd0, (%eax,%ecx,1)");
641 asm volatile("bndstx %bnd0, 0x12(%eax)");
642 asm volatile("bndstx %bnd0, 0x12(%ebp)");
643 asm volatile("bndstx %bnd0, 0x12(%ecx,%eax,1)");
644 asm volatile("bndstx %bnd0, 0x12(%ebp,%eax,1)");
645 asm volatile("bndstx %bnd0, 0x12(%eax,%ecx,1)");
646 asm volatile("bndstx %bnd0, 0x12345678(%eax)");
647 asm volatile("bndstx %bnd0, 0x12345678(%ebp)");
648 asm volatile("bndstx %bnd0, 0x12345678(%ecx,%eax,1)");
649 asm volatile("bndstx %bnd0, 0x12345678(%ebp,%eax,1)");
650 asm volatile("bndstx %bnd0, 0x12345678(%eax,%ecx,1)");
651
652 /* bnd prefix on call, ret, jmp and all jcc */
653
654 asm volatile("bnd call label1"); /* Expecting: call unconditional 0xfffffffc */
655 asm volatile("bnd call *(%eax)"); /* Expecting: call indirect 0 */
656 asm volatile("bnd ret"); /* Expecting: ret indirect 0 */
657 asm volatile("bnd jmp label1"); /* Expecting: jmp unconditional 0xfffffffc */
658 asm volatile("bnd jmp label1"); /* Expecting: jmp unconditional 0xfffffffc */
659 asm volatile("bnd jmp *(%ecx)"); /* Expecting: jmp indirect 0 */
660 asm volatile("bnd jne label1"); /* Expecting: jcc conditional 0xfffffffc */
661
662 /* sha1rnds4 imm8, xmm2/m128, xmm1 */
663
664 asm volatile("sha1rnds4 $0x0, %xmm1, %xmm0");
665 asm volatile("sha1rnds4 $0x91, %xmm7, %xmm2");
666 asm volatile("sha1rnds4 $0x91, (%eax), %xmm0");
667 asm volatile("sha1rnds4 $0x91, (0x12345678), %xmm0");
668 asm volatile("sha1rnds4 $0x91, (%eax), %xmm3");
669 asm volatile("sha1rnds4 $0x91, (%ecx,%eax,1), %xmm0");
670 asm volatile("sha1rnds4 $0x91, 0x12345678(,%eax,1), %xmm0");
671 asm volatile("sha1rnds4 $0x91, (%eax,%ecx,1), %xmm0");
672 asm volatile("sha1rnds4 $0x91, (%eax,%ecx,8), %xmm0");
673 asm volatile("sha1rnds4 $0x91, 0x12(%eax), %xmm0");
674 asm volatile("sha1rnds4 $0x91, 0x12(%ebp), %xmm0");
675 asm volatile("sha1rnds4 $0x91, 0x12(%ecx,%eax,1), %xmm0");
676 asm volatile("sha1rnds4 $0x91, 0x12(%ebp,%eax,1), %xmm0");
677 asm volatile("sha1rnds4 $0x91, 0x12(%eax,%ecx,1), %xmm0");
678 asm volatile("sha1rnds4 $0x91, 0x12(%eax,%ecx,8), %xmm0");
679 asm volatile("sha1rnds4 $0x91, 0x12345678(%eax), %xmm0");
680 asm volatile("sha1rnds4 $0x91, 0x12345678(%ebp), %xmm0");
681 asm volatile("sha1rnds4 $0x91, 0x12345678(%ecx,%eax,1), %xmm0");
682 asm volatile("sha1rnds4 $0x91, 0x12345678(%ebp,%eax,1), %xmm0");
683 asm volatile("sha1rnds4 $0x91, 0x12345678(%eax,%ecx,1), %xmm0");
684 asm volatile("sha1rnds4 $0x91, 0x12345678(%eax,%ecx,8), %xmm0");
685
686 /* sha1nexte xmm2/m128, xmm1 */
687
688 asm volatile("sha1nexte %xmm1, %xmm0");
689 asm volatile("sha1nexte %xmm7, %xmm2");
690 asm volatile("sha1nexte (%eax), %xmm0");
691 asm volatile("sha1nexte (0x12345678), %xmm0");
692 asm volatile("sha1nexte (%eax), %xmm3");
693 asm volatile("sha1nexte (%ecx,%eax,1), %xmm0");
694 asm volatile("sha1nexte 0x12345678(,%eax,1), %xmm0");
695 asm volatile("sha1nexte (%eax,%ecx,1), %xmm0");
696 asm volatile("sha1nexte (%eax,%ecx,8), %xmm0");
697 asm volatile("sha1nexte 0x12(%eax), %xmm0");
698 asm volatile("sha1nexte 0x12(%ebp), %xmm0");
699 asm volatile("sha1nexte 0x12(%ecx,%eax,1), %xmm0");
700 asm volatile("sha1nexte 0x12(%ebp,%eax,1), %xmm0");
701 asm volatile("sha1nexte 0x12(%eax,%ecx,1), %xmm0");
702 asm volatile("sha1nexte 0x12(%eax,%ecx,8), %xmm0");
703 asm volatile("sha1nexte 0x12345678(%eax), %xmm0");
704 asm volatile("sha1nexte 0x12345678(%ebp), %xmm0");
705 asm volatile("sha1nexte 0x12345678(%ecx,%eax,1), %xmm0");
706 asm volatile("sha1nexte 0x12345678(%ebp,%eax,1), %xmm0");
707 asm volatile("sha1nexte 0x12345678(%eax,%ecx,1), %xmm0");
708 asm volatile("sha1nexte 0x12345678(%eax,%ecx,8), %xmm0");
709
710 /* sha1msg1 xmm2/m128, xmm1 */
711
712 asm volatile("sha1msg1 %xmm1, %xmm0");
713 asm volatile("sha1msg1 %xmm7, %xmm2");
714 asm volatile("sha1msg1 (%eax), %xmm0");
715 asm volatile("sha1msg1 (0x12345678), %xmm0");
716 asm volatile("sha1msg1 (%eax), %xmm3");
717 asm volatile("sha1msg1 (%ecx,%eax,1), %xmm0");
718 asm volatile("sha1msg1 0x12345678(,%eax,1), %xmm0");
719 asm volatile("sha1msg1 (%eax,%ecx,1), %xmm0");
720 asm volatile("sha1msg1 (%eax,%ecx,8), %xmm0");
721 asm volatile("sha1msg1 0x12(%eax), %xmm0");
722 asm volatile("sha1msg1 0x12(%ebp), %xmm0");
723 asm volatile("sha1msg1 0x12(%ecx,%eax,1), %xmm0");
724 asm volatile("sha1msg1 0x12(%ebp,%eax,1), %xmm0");
725 asm volatile("sha1msg1 0x12(%eax,%ecx,1), %xmm0");
726 asm volatile("sha1msg1 0x12(%eax,%ecx,8), %xmm0");
727 asm volatile("sha1msg1 0x12345678(%eax), %xmm0");
728 asm volatile("sha1msg1 0x12345678(%ebp), %xmm0");
729 asm volatile("sha1msg1 0x12345678(%ecx,%eax,1), %xmm0");
730 asm volatile("sha1msg1 0x12345678(%ebp,%eax,1), %xmm0");
731 asm volatile("sha1msg1 0x12345678(%eax,%ecx,1), %xmm0");
732 asm volatile("sha1msg1 0x12345678(%eax,%ecx,8), %xmm0");
733
734 /* sha1msg2 xmm2/m128, xmm1 */
735
736 asm volatile("sha1msg2 %xmm1, %xmm0");
737 asm volatile("sha1msg2 %xmm7, %xmm2");
738 asm volatile("sha1msg2 (%eax), %xmm0");
739 asm volatile("sha1msg2 (0x12345678), %xmm0");
740 asm volatile("sha1msg2 (%eax), %xmm3");
741 asm volatile("sha1msg2 (%ecx,%eax,1), %xmm0");
742 asm volatile("sha1msg2 0x12345678(,%eax,1), %xmm0");
743 asm volatile("sha1msg2 (%eax,%ecx,1), %xmm0");
744 asm volatile("sha1msg2 (%eax,%ecx,8), %xmm0");
745 asm volatile("sha1msg2 0x12(%eax), %xmm0");
746 asm volatile("sha1msg2 0x12(%ebp), %xmm0");
747 asm volatile("sha1msg2 0x12(%ecx,%eax,1), %xmm0");
748 asm volatile("sha1msg2 0x12(%ebp,%eax,1), %xmm0");
749 asm volatile("sha1msg2 0x12(%eax,%ecx,1), %xmm0");
750 asm volatile("sha1msg2 0x12(%eax,%ecx,8), %xmm0");
751 asm volatile("sha1msg2 0x12345678(%eax), %xmm0");
752 asm volatile("sha1msg2 0x12345678(%ebp), %xmm0");
753 asm volatile("sha1msg2 0x12345678(%ecx,%eax,1), %xmm0");
754 asm volatile("sha1msg2 0x12345678(%ebp,%eax,1), %xmm0");
755 asm volatile("sha1msg2 0x12345678(%eax,%ecx,1), %xmm0");
756 asm volatile("sha1msg2 0x12345678(%eax,%ecx,8), %xmm0");
757
758 /* sha256rnds2 <XMM0>, xmm2/m128, xmm1 */
759 /* Note sha256rnds2 has an implicit operand 'xmm0' */
760
761 asm volatile("sha256rnds2 %xmm4, %xmm1");
762 asm volatile("sha256rnds2 %xmm7, %xmm2");
763 asm volatile("sha256rnds2 (%eax), %xmm1");
764 asm volatile("sha256rnds2 (0x12345678), %xmm1");
765 asm volatile("sha256rnds2 (%eax), %xmm3");
766 asm volatile("sha256rnds2 (%ecx,%eax,1), %xmm1");
767 asm volatile("sha256rnds2 0x12345678(,%eax,1), %xmm1");
768 asm volatile("sha256rnds2 (%eax,%ecx,1), %xmm1");
769 asm volatile("sha256rnds2 (%eax,%ecx,8), %xmm1");
770 asm volatile("sha256rnds2 0x12(%eax), %xmm1");
771 asm volatile("sha256rnds2 0x12(%ebp), %xmm1");
772 asm volatile("sha256rnds2 0x12(%ecx,%eax,1), %xmm1");
773 asm volatile("sha256rnds2 0x12(%ebp,%eax,1), %xmm1");
774 asm volatile("sha256rnds2 0x12(%eax,%ecx,1), %xmm1");
775 asm volatile("sha256rnds2 0x12(%eax,%ecx,8), %xmm1");
776 asm volatile("sha256rnds2 0x12345678(%eax), %xmm1");
777 asm volatile("sha256rnds2 0x12345678(%ebp), %xmm1");
778 asm volatile("sha256rnds2 0x12345678(%ecx,%eax,1), %xmm1");
779 asm volatile("sha256rnds2 0x12345678(%ebp,%eax,1), %xmm1");
780 asm volatile("sha256rnds2 0x12345678(%eax,%ecx,1), %xmm1");
781 asm volatile("sha256rnds2 0x12345678(%eax,%ecx,8), %xmm1");
782
783 /* sha256msg1 xmm2/m128, xmm1 */
784
785 asm volatile("sha256msg1 %xmm1, %xmm0");
786 asm volatile("sha256msg1 %xmm7, %xmm2");
787 asm volatile("sha256msg1 (%eax), %xmm0");
788 asm volatile("sha256msg1 (0x12345678), %xmm0");
789 asm volatile("sha256msg1 (%eax), %xmm3");
790 asm volatile("sha256msg1 (%ecx,%eax,1), %xmm0");
791 asm volatile("sha256msg1 0x12345678(,%eax,1), %xmm0");
792 asm volatile("sha256msg1 (%eax,%ecx,1), %xmm0");
793 asm volatile("sha256msg1 (%eax,%ecx,8), %xmm0");
794 asm volatile("sha256msg1 0x12(%eax), %xmm0");
795 asm volatile("sha256msg1 0x12(%ebp), %xmm0");
796 asm volatile("sha256msg1 0x12(%ecx,%eax,1), %xmm0");
797 asm volatile("sha256msg1 0x12(%ebp,%eax,1), %xmm0");
798 asm volatile("sha256msg1 0x12(%eax,%ecx,1), %xmm0");
799 asm volatile("sha256msg1 0x12(%eax,%ecx,8), %xmm0");
800 asm volatile("sha256msg1 0x12345678(%eax), %xmm0");
801 asm volatile("sha256msg1 0x12345678(%ebp), %xmm0");
802 asm volatile("sha256msg1 0x12345678(%ecx,%eax,1), %xmm0");
803 asm volatile("sha256msg1 0x12345678(%ebp,%eax,1), %xmm0");
804 asm volatile("sha256msg1 0x12345678(%eax,%ecx,1), %xmm0");
805 asm volatile("sha256msg1 0x12345678(%eax,%ecx,8), %xmm0");
806
807 /* sha256msg2 xmm2/m128, xmm1 */
808
809 asm volatile("sha256msg2 %xmm1, %xmm0");
810 asm volatile("sha256msg2 %xmm7, %xmm2");
811 asm volatile("sha256msg2 (%eax), %xmm0");
812 asm volatile("sha256msg2 (0x12345678), %xmm0");
813 asm volatile("sha256msg2 (%eax), %xmm3");
814 asm volatile("sha256msg2 (%ecx,%eax,1), %xmm0");
815 asm volatile("sha256msg2 0x12345678(,%eax,1), %xmm0");
816 asm volatile("sha256msg2 (%eax,%ecx,1), %xmm0");
817 asm volatile("sha256msg2 (%eax,%ecx,8), %xmm0");
818 asm volatile("sha256msg2 0x12(%eax), %xmm0");
819 asm volatile("sha256msg2 0x12(%ebp), %xmm0");
820 asm volatile("sha256msg2 0x12(%ecx,%eax,1), %xmm0");
821 asm volatile("sha256msg2 0x12(%ebp,%eax,1), %xmm0");
822 asm volatile("sha256msg2 0x12(%eax,%ecx,1), %xmm0");
823 asm volatile("sha256msg2 0x12(%eax,%ecx,8), %xmm0");
824 asm volatile("sha256msg2 0x12345678(%eax), %xmm0");
825 asm volatile("sha256msg2 0x12345678(%ebp), %xmm0");
826 asm volatile("sha256msg2 0x12345678(%ecx,%eax,1), %xmm0");
827 asm volatile("sha256msg2 0x12345678(%ebp,%eax,1), %xmm0");
828 asm volatile("sha256msg2 0x12345678(%eax,%ecx,1), %xmm0");
829 asm volatile("sha256msg2 0x12345678(%eax,%ecx,8), %xmm0");
830
831 /* clflushopt m8 */
832
833 asm volatile("clflushopt (%eax)");
834 asm volatile("clflushopt (0x12345678)");
835 asm volatile("clflushopt 0x12345678(%eax,%ecx,8)");
836 /* Also check instructions in the same group encoding as clflushopt */
837 asm volatile("clflush (%eax)");
838 asm volatile("sfence");
839
840 /* clwb m8 */
841
842 asm volatile("clwb (%eax)");
843 asm volatile("clwb (0x12345678)");
844 asm volatile("clwb 0x12345678(%eax,%ecx,8)");
845 /* Also check instructions in the same group encoding as clwb */
846 asm volatile("xsaveopt (%eax)");
847 asm volatile("mfence");
848
849 /* xsavec mem */
850
851 asm volatile("xsavec (%eax)");
852 asm volatile("xsavec (0x12345678)");
853 asm volatile("xsavec 0x12345678(%eax,%ecx,8)");
854
855 /* xsaves mem */
856
857 asm volatile("xsaves (%eax)");
858 asm volatile("xsaves (0x12345678)");
859 asm volatile("xsaves 0x12345678(%eax,%ecx,8)");
860
861 /* xrstors mem */
862
863 asm volatile("xrstors (%eax)");
864 asm volatile("xrstors (0x12345678)");
865 asm volatile("xrstors 0x12345678(%eax,%ecx,8)");
866
867#endif /* #ifndef __x86_64__ */
868
869 /* pcommit */
870
871 asm volatile("pcommit");
872
873 /* Following line is a marker for the awk script - do not change */
874 asm volatile("rdtsc"); /* Stop here */
875
876 return 0;
877}
diff --git a/tools/perf/arch/x86/tests/insn-x86.c b/tools/perf/arch/x86/tests/insn-x86.c
new file mode 100644
index 000000000000..b6115dfd28f0
--- /dev/null
+++ b/tools/perf/arch/x86/tests/insn-x86.c
@@ -0,0 +1,185 @@
1#include <linux/types.h>
2
3#include "debug.h"
4#include "tests/tests.h"
5#include "arch-tests.h"
6
7#include "intel-pt-decoder/insn.h"
8#include "intel-pt-decoder/intel-pt-insn-decoder.h"
9
10struct test_data {
11 u8 data[MAX_INSN_SIZE];
12 int expected_length;
13 int expected_rel;
14 const char *expected_op_str;
15 const char *expected_branch_str;
16 const char *asm_rep;
17};
18
19struct test_data test_data_32[] = {
20#include "insn-x86-dat-32.c"
21 {{0x0f, 0x01, 0xee}, 3, 0, NULL, NULL, "0f 01 ee \trdpkru"},
22 {{0x0f, 0x01, 0xef}, 3, 0, NULL, NULL, "0f 01 ef \twrpkru"},
23 {{0}, 0, 0, NULL, NULL, NULL},
24};
25
26struct test_data test_data_64[] = {
27#include "insn-x86-dat-64.c"
28 {{0x0f, 0x01, 0xee}, 3, 0, NULL, NULL, "0f 01 ee \trdpkru"},
29 {{0x0f, 0x01, 0xef}, 3, 0, NULL, NULL, "0f 01 ef \twrpkru"},
30 {{0}, 0, 0, NULL, NULL, NULL},
31};
32
33static int get_op(const char *op_str)
34{
35 struct val_data {
36 const char *name;
37 int val;
38 } vals[] = {
39 {"other", INTEL_PT_OP_OTHER},
40 {"call", INTEL_PT_OP_CALL},
41 {"ret", INTEL_PT_OP_RET},
42 {"jcc", INTEL_PT_OP_JCC},
43 {"jmp", INTEL_PT_OP_JMP},
44 {"loop", INTEL_PT_OP_LOOP},
45 {"iret", INTEL_PT_OP_IRET},
46 {"int", INTEL_PT_OP_INT},
47 {"syscall", INTEL_PT_OP_SYSCALL},
48 {"sysret", INTEL_PT_OP_SYSRET},
49 {NULL, 0},
50 };
51 struct val_data *val;
52
53 if (!op_str || !strlen(op_str))
54 return 0;
55
56 for (val = vals; val->name; val++) {
57 if (!strcmp(val->name, op_str))
58 return val->val;
59 }
60
61 pr_debug("Failed to get op\n");
62
63 return -1;
64}
65
66static int get_branch(const char *branch_str)
67{
68 struct val_data {
69 const char *name;
70 int val;
71 } vals[] = {
72 {"no_branch", INTEL_PT_BR_NO_BRANCH},
73 {"indirect", INTEL_PT_BR_INDIRECT},
74 {"conditional", INTEL_PT_BR_CONDITIONAL},
75 {"unconditional", INTEL_PT_BR_UNCONDITIONAL},
76 {NULL, 0},
77 };
78 struct val_data *val;
79
80 if (!branch_str || !strlen(branch_str))
81 return 0;
82
83 for (val = vals; val->name; val++) {
84 if (!strcmp(val->name, branch_str))
85 return val->val;
86 }
87
88 pr_debug("Failed to get branch\n");
89
90 return -1;
91}
92
93static int test_data_item(struct test_data *dat, int x86_64)
94{
95 struct intel_pt_insn intel_pt_insn;
96 struct insn insn;
97 int op, branch;
98
99 insn_init(&insn, dat->data, MAX_INSN_SIZE, x86_64);
100 insn_get_length(&insn);
101
102 if (!insn_complete(&insn)) {
103 pr_debug("Failed to decode: %s\n", dat->asm_rep);
104 return -1;
105 }
106
107 if (insn.length != dat->expected_length) {
108 pr_debug("Failed to decode length (%d vs expected %d): %s\n",
109 insn.length, dat->expected_length, dat->asm_rep);
110 return -1;
111 }
112
113 op = get_op(dat->expected_op_str);
114 branch = get_branch(dat->expected_branch_str);
115
116 if (intel_pt_get_insn(dat->data, MAX_INSN_SIZE, x86_64, &intel_pt_insn)) {
117 pr_debug("Intel PT failed to decode: %s\n", dat->asm_rep);
118 return -1;
119 }
120
121 if ((int)intel_pt_insn.op != op) {
122 pr_debug("Failed to decode 'op' value (%d vs expected %d): %s\n",
123 intel_pt_insn.op, op, dat->asm_rep);
124 return -1;
125 }
126
127 if ((int)intel_pt_insn.branch != branch) {
128 pr_debug("Failed to decode 'branch' value (%d vs expected %d): %s\n",
129 intel_pt_insn.branch, branch, dat->asm_rep);
130 return -1;
131 }
132
133 if (intel_pt_insn.rel != dat->expected_rel) {
134 pr_debug("Failed to decode 'rel' value (%#x vs expected %#x): %s\n",
135 intel_pt_insn.rel, dat->expected_rel, dat->asm_rep);
136 return -1;
137 }
138
139 pr_debug("Decoded ok: %s\n", dat->asm_rep);
140
141 return 0;
142}
143
144static int test_data_set(struct test_data *dat_set, int x86_64)
145{
146 struct test_data *dat;
147 int ret = 0;
148
149 for (dat = dat_set; dat->expected_length; dat++) {
150 if (test_data_item(dat, x86_64))
151 ret = -1;
152 }
153
154 return ret;
155}
156
157/**
158 * test__insn_x86 - test x86 instruction decoder - new instructions.
159 *
160 * This function implements a test that decodes a selection of instructions and
161 * checks the results. The Intel PT function that further categorizes
162 * instructions (i.e. intel_pt_get_insn()) is also checked.
163 *
164 * The instructions are originally in insn-x86-dat-src.c which has been
165 * processed by scripts gen-insn-x86-dat.sh and gen-insn-x86-dat.awk to produce
166 * insn-x86-dat-32.c and insn-x86-dat-64.c which are included into this program.
167 * i.e. to add new instructions to the test, edit insn-x86-dat-src.c, run the
168 * gen-insn-x86-dat.sh script, make perf, and then run the test.
169 *
170 * If the test passes %0 is returned, otherwise %-1 is returned. Use the
171 * verbose (-v) option to see all the instructions and whether or not they
172 * decoded successfuly.
173 */
174int test__insn_x86(void)
175{
176 int ret = 0;
177
178 if (test_data_set(test_data_32, 0))
179 ret = -1;
180
181 if (test_data_set(test_data_64, 1))
182 ret = -1;
183
184 return ret;
185}
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c
new file mode 100644
index 000000000000..d28c1b6a3b54
--- /dev/null
+++ b/tools/perf/arch/x86/tests/intel-cqm.c
@@ -0,0 +1,124 @@
1#include "tests/tests.h"
2#include "perf.h"
3#include "cloexec.h"
4#include "debug.h"
5#include "evlist.h"
6#include "evsel.h"
7#include "arch-tests.h"
8
9#include <sys/mman.h>
10#include <string.h>
11
12static pid_t spawn(void)
13{
14 pid_t pid;
15
16 pid = fork();
17 if (pid)
18 return pid;
19
20 while(1);
21 sleep(5);
22 return 0;
23}
24
25/*
26 * Create an event group that contains both a sampled hardware
27 * (cpu-cycles) and software (intel_cqm/llc_occupancy/) event. We then
28 * wait for the hardware perf counter to overflow and generate a PMI,
29 * which triggers an event read for both of the events in the group.
30 *
31 * Since reading Intel CQM event counters requires sending SMP IPIs, the
32 * CQM pmu needs to handle the above situation gracefully, and return
33 * the last read counter value to avoid triggering a WARN_ON_ONCE() in
34 * smp_call_function_many() caused by sending IPIs from NMI context.
35 */
36int test__intel_cqm_count_nmi_context(void)
37{
38 struct perf_evlist *evlist = NULL;
39 struct perf_evsel *evsel = NULL;
40 struct perf_event_attr pe;
41 int i, fd[2], flag, ret;
42 size_t mmap_len;
43 void *event;
44 pid_t pid;
45 int err = TEST_FAIL;
46
47 flag = perf_event_open_cloexec_flag();
48
49 evlist = perf_evlist__new();
50 if (!evlist) {
51 pr_debug("perf_evlist__new failed\n");
52 return TEST_FAIL;
53 }
54
55 ret = parse_events(evlist, "intel_cqm/llc_occupancy/", NULL);
56 if (ret) {
57 pr_debug("parse_events failed\n");
58 err = TEST_SKIP;
59 goto out;
60 }
61
62 evsel = perf_evlist__first(evlist);
63 if (!evsel) {
64 pr_debug("perf_evlist__first failed\n");
65 goto out;
66 }
67
68 memset(&pe, 0, sizeof(pe));
69 pe.size = sizeof(pe);
70
71 pe.type = PERF_TYPE_HARDWARE;
72 pe.config = PERF_COUNT_HW_CPU_CYCLES;
73 pe.read_format = PERF_FORMAT_GROUP;
74
75 pe.sample_period = 128;
76 pe.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_READ;
77
78 pid = spawn();
79
80 fd[0] = sys_perf_event_open(&pe, pid, -1, -1, flag);
81 if (fd[0] < 0) {
82 pr_debug("failed to open event\n");
83 goto out;
84 }
85
86 memset(&pe, 0, sizeof(pe));
87 pe.size = sizeof(pe);
88
89 pe.type = evsel->attr.type;
90 pe.config = evsel->attr.config;
91
92 fd[1] = sys_perf_event_open(&pe, pid, -1, fd[0], flag);
93 if (fd[1] < 0) {
94 pr_debug("failed to open event\n");
95 goto out;
96 }
97
98 /*
99 * Pick a power-of-two number of pages + 1 for the meta-data
100 * page (struct perf_event_mmap_page). See tools/perf/design.txt.
101 */
102 mmap_len = page_size * 65;
103
104 event = mmap(NULL, mmap_len, PROT_READ, MAP_SHARED, fd[0], 0);
105 if (event == (void *)(-1)) {
106 pr_debug("failed to mmap %d\n", errno);
107 goto out;
108 }
109
110 sleep(1);
111
112 err = TEST_OK;
113
114 munmap(event, mmap_len);
115
116 for (i = 0; i < 2; i++)
117 close(fd[i]);
118
119 kill(pid, SIGKILL);
120 wait(NULL);
121out:
122 perf_evlist__delete(evlist);
123 return err;
124}
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index 5f49484f1abc..658cd200af74 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -9,7 +9,9 @@
9#include "thread_map.h" 9#include "thread_map.h"
10#include "cpumap.h" 10#include "cpumap.h"
11#include "tsc.h" 11#include "tsc.h"
12#include "tests.h" 12#include "tests/tests.h"
13
14#include "arch-tests.h"
13 15
14#define CHECK__(x) { \ 16#define CHECK__(x) { \
15 while ((x) < 0) { \ 17 while ((x) < 0) { \
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/arch/x86/tests/rdpmc.c
index d31f2c4d9f64..e7688214c7cf 100644
--- a/tools/perf/tests/rdpmc.c
+++ b/tools/perf/arch/x86/tests/rdpmc.c
@@ -5,10 +5,9 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include "perf.h" 6#include "perf.h"
7#include "debug.h" 7#include "debug.h"
8#include "tests.h" 8#include "tests/tests.h"
9#include "cloexec.h" 9#include "cloexec.h"
10 10#include "arch-tests.h"
11#if defined(__x86_64__) || defined(__i386__)
12 11
13static u64 rdpmc(unsigned int counter) 12static u64 rdpmc(unsigned int counter)
14{ 13{
@@ -173,5 +172,3 @@ int test__rdpmc(void)
173 172
174 return 0; 173 return 0;
175} 174}
176
177#endif
diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c
index a08de0a35b83..9223c164e545 100644
--- a/tools/perf/arch/x86/util/dwarf-regs.c
+++ b/tools/perf/arch/x86/util/dwarf-regs.c
@@ -21,55 +21,109 @@
21 */ 21 */
22 22
23#include <stddef.h> 23#include <stddef.h>
24#include <errno.h> /* for EINVAL */
25#include <string.h> /* for strcmp */
26#include <linux/ptrace.h> /* for struct pt_regs */
27#include <linux/kernel.h> /* for offsetof */
24#include <dwarf-regs.h> 28#include <dwarf-regs.h>
25 29
26/* 30/*
27 * Generic dwarf analysis helpers 31 * See arch/x86/kernel/ptrace.c.
32 * Different from it:
33 *
34 * - Since struct pt_regs is defined differently for user and kernel,
35 * but we want to use 'ax, bx' instead of 'rax, rbx' (which is struct
36 * field name of user's pt_regs), we make REG_OFFSET_NAME to accept
37 * both string name and reg field name.
38 *
39 * - Since accessing x86_32's pt_regs from x86_64 building is difficult
40 * and vise versa, we simply fill offset with -1, so
41 * get_arch_regstr() still works but regs_query_register_offset()
42 * returns error.
43 * The only inconvenience caused by it now is that we are not allowed
44 * to generate BPF prologue for a x86_64 kernel if perf is built for
45 * x86_32. This is really a rare usecase.
46 *
47 * - Order is different from kernel's ptrace.c for get_arch_regstr(). Use
48 * the order defined by dwarf.
28 */ 49 */
29 50
30#define X86_32_MAX_REGS 8 51struct pt_regs_offset {
31const char *x86_32_regs_table[X86_32_MAX_REGS] = { 52 const char *name;
32 "%ax", 53 int offset;
33 "%cx", 54};
34 "%dx", 55
35 "%bx", 56#define REG_OFFSET_END {.name = NULL, .offset = 0}
36 "$stack", /* Stack address instead of %sp */ 57
37 "%bp", 58#ifdef __x86_64__
38 "%si", 59# define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)}
39 "%di", 60# define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = -1}
61#else
62# define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = -1}
63# define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)}
64#endif
65
66static const struct pt_regs_offset x86_32_regoffset_table[] = {
67 REG_OFFSET_NAME_32("%ax", eax),
68 REG_OFFSET_NAME_32("%cx", ecx),
69 REG_OFFSET_NAME_32("%dx", edx),
70 REG_OFFSET_NAME_32("%bx", ebx),
71 REG_OFFSET_NAME_32("$stack", esp), /* Stack address instead of %sp */
72 REG_OFFSET_NAME_32("%bp", ebp),
73 REG_OFFSET_NAME_32("%si", esi),
74 REG_OFFSET_NAME_32("%di", edi),
75 REG_OFFSET_END,
40}; 76};
41 77
42#define X86_64_MAX_REGS 16 78static const struct pt_regs_offset x86_64_regoffset_table[] = {
43const char *x86_64_regs_table[X86_64_MAX_REGS] = { 79 REG_OFFSET_NAME_64("%ax", rax),
44 "%ax", 80 REG_OFFSET_NAME_64("%dx", rdx),
45 "%dx", 81 REG_OFFSET_NAME_64("%cx", rcx),
46 "%cx", 82 REG_OFFSET_NAME_64("%bx", rbx),
47 "%bx", 83 REG_OFFSET_NAME_64("%si", rsi),
48 "%si", 84 REG_OFFSET_NAME_64("%di", rdi),
49 "%di", 85 REG_OFFSET_NAME_64("%bp", rbp),
50 "%bp", 86 REG_OFFSET_NAME_64("%sp", rsp),
51 "%sp", 87 REG_OFFSET_NAME_64("%r8", r8),
52 "%r8", 88 REG_OFFSET_NAME_64("%r9", r9),
53 "%r9", 89 REG_OFFSET_NAME_64("%r10", r10),
54 "%r10", 90 REG_OFFSET_NAME_64("%r11", r11),
55 "%r11", 91 REG_OFFSET_NAME_64("%r12", r12),
56 "%r12", 92 REG_OFFSET_NAME_64("%r13", r13),
57 "%r13", 93 REG_OFFSET_NAME_64("%r14", r14),
58 "%r14", 94 REG_OFFSET_NAME_64("%r15", r15),
59 "%r15", 95 REG_OFFSET_END,
60}; 96};
61 97
62/* TODO: switching by dwarf address size */ 98/* TODO: switching by dwarf address size */
63#ifdef __x86_64__ 99#ifdef __x86_64__
64#define ARCH_MAX_REGS X86_64_MAX_REGS 100#define regoffset_table x86_64_regoffset_table
65#define arch_regs_table x86_64_regs_table
66#else 101#else
67#define ARCH_MAX_REGS X86_32_MAX_REGS 102#define regoffset_table x86_32_regoffset_table
68#define arch_regs_table x86_32_regs_table
69#endif 103#endif
70 104
105/* Minus 1 for the ending REG_OFFSET_END */
106#define ARCH_MAX_REGS ((sizeof(regoffset_table) / sizeof(regoffset_table[0])) - 1)
107
71/* Return architecture dependent register string (for kprobe-tracer) */ 108/* Return architecture dependent register string (for kprobe-tracer) */
72const char *get_arch_regstr(unsigned int n) 109const char *get_arch_regstr(unsigned int n)
73{ 110{
74 return (n < ARCH_MAX_REGS) ? arch_regs_table[n] : NULL; 111 return (n < ARCH_MAX_REGS) ? regoffset_table[n].name : NULL;
112}
113
114/* Reuse code from arch/x86/kernel/ptrace.c */
115/**
116 * regs_query_register_offset() - query register offset from its name
117 * @name: the name of a register
118 *
119 * regs_query_register_offset() returns the offset of a register in struct
120 * pt_regs from its name. If the name is invalid, this returns -EINVAL;
121 */
122int regs_query_register_offset(const char *name)
123{
124 const struct pt_regs_offset *roff;
125 for (roff = regoffset_table; roff->name != NULL; roff++)
126 if (!strcmp(roff->name, name))
127 return roff->offset;
128 return -EINVAL;
75} 129}
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index 2ca10d796c0b..b02af064f0f9 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -624,13 +624,49 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
624 * threads. 624 * threads.
625 */ 625 */
626 if (have_timing_info && !cpu_map__empty(cpus)) { 626 if (have_timing_info && !cpu_map__empty(cpus)) {
627 err = intel_pt_track_switches(evlist); 627 if (perf_can_record_switch_events()) {
628 if (err == -EPERM) 628 bool cpu_wide = !target__none(&opts->target) &&
629 pr_debug2("Unable to select sched:sched_switch\n"); 629 !target__has_task(&opts->target);
630 else if (err) 630
631 return err; 631 if (!cpu_wide && perf_can_record_cpu_wide()) {
632 else 632 struct perf_evsel *switch_evsel;
633 ptr->have_sched_switch = 1; 633
634 err = parse_events(evlist, "dummy:u", NULL);
635 if (err)
636 return err;
637
638 switch_evsel = perf_evlist__last(evlist);
639
640 switch_evsel->attr.freq = 0;
641 switch_evsel->attr.sample_period = 1;
642 switch_evsel->attr.context_switch = 1;
643
644 switch_evsel->system_wide = true;
645 switch_evsel->no_aux_samples = true;
646 switch_evsel->immediate = true;
647
648 perf_evsel__set_sample_bit(switch_evsel, TID);
649 perf_evsel__set_sample_bit(switch_evsel, TIME);
650 perf_evsel__set_sample_bit(switch_evsel, CPU);
651
652 opts->record_switch_events = false;
653 ptr->have_sched_switch = 3;
654 } else {
655 opts->record_switch_events = true;
656 if (cpu_wide)
657 ptr->have_sched_switch = 3;
658 else
659 ptr->have_sched_switch = 2;
660 }
661 } else {
662 err = intel_pt_track_switches(evlist);
663 if (err == -EPERM)
664 pr_debug2("Unable to select sched:sched_switch\n");
665 else if (err)
666 return err;
667 else
668 ptr->have_sched_switch = 1;
669 }
634 } 670 }
635 671
636 if (intel_pt_evsel) { 672 if (intel_pt_evsel) {
@@ -663,8 +699,11 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
663 tracking_evsel->attr.sample_period = 1; 699 tracking_evsel->attr.sample_period = 1;
664 700
665 /* In per-cpu case, always need the time of mmap events etc */ 701 /* In per-cpu case, always need the time of mmap events etc */
666 if (!cpu_map__empty(cpus)) 702 if (!cpu_map__empty(cpus)) {
667 perf_evsel__set_sample_bit(tracking_evsel, TIME); 703 perf_evsel__set_sample_bit(tracking_evsel, TIME);
704 /* And the CPU for switch events */
705 perf_evsel__set_sample_bit(tracking_evsel, CPU);
706 }
668 } 707 }
669 708
670 /* 709 /*
diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build
index 573e28896038..60bf11943047 100644
--- a/tools/perf/bench/Build
+++ b/tools/perf/bench/Build
@@ -1,6 +1,6 @@
1perf-y += sched-messaging.o 1perf-y += sched-messaging.o
2perf-y += sched-pipe.o 2perf-y += sched-pipe.o
3perf-y += mem-memcpy.o 3perf-y += mem-functions.o
4perf-y += futex-hash.o 4perf-y += futex-hash.o
5perf-y += futex-wake.o 5perf-y += futex-wake.o
6perf-y += futex-wake-parallel.o 6perf-y += futex-wake-parallel.o
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
new file mode 100644
index 000000000000..9419b944220f
--- /dev/null
+++ b/tools/perf/bench/mem-functions.c
@@ -0,0 +1,379 @@
1/*
2 * mem-memcpy.c
3 *
4 * Simple memcpy() and memset() benchmarks
5 *
6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
7 */
8
9#include "../perf.h"
10#include "../util/util.h"
11#include "../util/parse-options.h"
12#include "../util/header.h"
13#include "../util/cloexec.h"
14#include "bench.h"
15#include "mem-memcpy-arch.h"
16#include "mem-memset-arch.h"
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <sys/time.h>
22#include <errno.h>
23
24#define K 1024
25
26static const char *size_str = "1MB";
27static const char *function_str = "all";
28static int nr_loops = 1;
29static bool use_cycles;
30static int cycles_fd;
31
32static const struct option options[] = {
33 OPT_STRING('s', "size", &size_str, "1MB",
34 "Specify the size of the memory buffers. "
35 "Available units: B, KB, MB, GB and TB (case insensitive)"),
36
37 OPT_STRING('f', "function", &function_str, "all",
38 "Specify the function to run, \"all\" runs all available functions, \"help\" lists them"),
39
40 OPT_INTEGER('l', "nr_loops", &nr_loops,
41 "Specify the number of loops to run. (default: 1)"),
42
43 OPT_BOOLEAN('c', "cycles", &use_cycles,
44 "Use a cycles event instead of gettimeofday() to measure performance"),
45
46 OPT_END()
47};
48
49typedef void *(*memcpy_t)(void *, const void *, size_t);
50typedef void *(*memset_t)(void *, int, size_t);
51
52struct function {
53 const char *name;
54 const char *desc;
55 union {
56 memcpy_t memcpy;
57 memset_t memset;
58 } fn;
59};
60
61static struct perf_event_attr cycle_attr = {
62 .type = PERF_TYPE_HARDWARE,
63 .config = PERF_COUNT_HW_CPU_CYCLES
64};
65
66static void init_cycles(void)
67{
68 cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag());
69
70 if (cycles_fd < 0 && errno == ENOSYS)
71 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
72 else
73 BUG_ON(cycles_fd < 0);
74}
75
76static u64 get_cycles(void)
77{
78 int ret;
79 u64 clk;
80
81 ret = read(cycles_fd, &clk, sizeof(u64));
82 BUG_ON(ret != sizeof(u64));
83
84 return clk;
85}
86
87static double timeval2double(struct timeval *ts)
88{
89 return (double)ts->tv_sec + (double)ts->tv_usec / (double)1000000;
90}
91
92#define print_bps(x) do { \
93 if (x < K) \
94 printf(" %14lf bytes/sec\n", x); \
95 else if (x < K * K) \
96 printf(" %14lfd KB/sec\n", x / K); \
97 else if (x < K * K * K) \
98 printf(" %14lf MB/sec\n", x / K / K); \
99 else \
100 printf(" %14lf GB/sec\n", x / K / K / K); \
101 } while (0)
102
103struct bench_mem_info {
104 const struct function *functions;
105 u64 (*do_cycles)(const struct function *r, size_t size);
106 double (*do_gettimeofday)(const struct function *r, size_t size);
107 const char *const *usage;
108};
109
110static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t size, double size_total)
111{
112 const struct function *r = &info->functions[r_idx];
113 double result_bps = 0.0;
114 u64 result_cycles = 0;
115
116 printf("# function '%s' (%s)\n", r->name, r->desc);
117
118 if (bench_format == BENCH_FORMAT_DEFAULT)
119 printf("# Copying %s bytes ...\n\n", size_str);
120
121 if (use_cycles) {
122 result_cycles = info->do_cycles(r, size);
123 } else {
124 result_bps = info->do_gettimeofday(r, size);
125 }
126
127 switch (bench_format) {
128 case BENCH_FORMAT_DEFAULT:
129 if (use_cycles) {
130 printf(" %14lf cycles/byte\n", (double)result_cycles/size_total);
131 } else {
132 print_bps(result_bps);
133 }
134 break;
135
136 case BENCH_FORMAT_SIMPLE:
137 if (use_cycles) {
138 printf("%lf\n", (double)result_cycles/size_total);
139 } else {
140 printf("%lf\n", result_bps);
141 }
142 break;
143
144 default:
145 BUG_ON(1);
146 break;
147 }
148}
149
150static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *info)
151{
152 int i;
153 size_t size;
154 double size_total;
155
156 argc = parse_options(argc, argv, options, info->usage, 0);
157
158 if (use_cycles)
159 init_cycles();
160
161 size = (size_t)perf_atoll((char *)size_str);
162 size_total = (double)size * nr_loops;
163
164 if ((s64)size <= 0) {
165 fprintf(stderr, "Invalid size:%s\n", size_str);
166 return 1;
167 }
168
169 if (!strncmp(function_str, "all", 3)) {
170 for (i = 0; info->functions[i].name; i++)
171 __bench_mem_function(info, i, size, size_total);
172 return 0;
173 }
174
175 for (i = 0; info->functions[i].name; i++) {
176 if (!strcmp(info->functions[i].name, function_str))
177 break;
178 }
179 if (!info->functions[i].name) {
180 if (strcmp(function_str, "help") && strcmp(function_str, "h"))
181 printf("Unknown function: %s\n", function_str);
182 printf("Available functions:\n");
183 for (i = 0; info->functions[i].name; i++) {
184 printf("\t%s ... %s\n",
185 info->functions[i].name, info->functions[i].desc);
186 }
187 return 1;
188 }
189
190 __bench_mem_function(info, i, size, size_total);
191
192 return 0;
193}
194
195static void memcpy_alloc_mem(void **dst, void **src, size_t size)
196{
197 *dst = zalloc(size);
198 if (!*dst)
199 die("memory allocation failed - maybe size is too large?\n");
200
201 *src = zalloc(size);
202 if (!*src)
203 die("memory allocation failed - maybe size is too large?\n");
204
205 /* Make sure to always prefault zero pages even if MMAP_THRESH is crossed: */
206 memset(*src, 0, size);
207}
208
209static u64 do_memcpy_cycles(const struct function *r, size_t size)
210{
211 u64 cycle_start = 0ULL, cycle_end = 0ULL;
212 void *src = NULL, *dst = NULL;
213 memcpy_t fn = r->fn.memcpy;
214 int i;
215
216 memcpy_alloc_mem(&dst, &src, size);
217
218 /*
219 * We prefault the freshly allocated memory range here,
220 * to not measure page fault overhead:
221 */
222 fn(dst, src, size);
223
224 cycle_start = get_cycles();
225 for (i = 0; i < nr_loops; ++i)
226 fn(dst, src, size);
227 cycle_end = get_cycles();
228
229 free(src);
230 free(dst);
231 return cycle_end - cycle_start;
232}
233
234static double do_memcpy_gettimeofday(const struct function *r, size_t size)
235{
236 struct timeval tv_start, tv_end, tv_diff;
237 memcpy_t fn = r->fn.memcpy;
238 void *src = NULL, *dst = NULL;
239 int i;
240
241 memcpy_alloc_mem(&dst, &src, size);
242
243 /*
244 * We prefault the freshly allocated memory range here,
245 * to not measure page fault overhead:
246 */
247 fn(dst, src, size);
248
249 BUG_ON(gettimeofday(&tv_start, NULL));
250 for (i = 0; i < nr_loops; ++i)
251 fn(dst, src, size);
252 BUG_ON(gettimeofday(&tv_end, NULL));
253
254 timersub(&tv_end, &tv_start, &tv_diff);
255
256 free(src);
257 free(dst);
258
259 return (double)(((double)size * nr_loops) / timeval2double(&tv_diff));
260}
261
262struct function memcpy_functions[] = {
263 { .name = "default",
264 .desc = "Default memcpy() provided by glibc",
265 .fn.memcpy = memcpy },
266
267#ifdef HAVE_ARCH_X86_64_SUPPORT
268# define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn},
269# include "mem-memcpy-x86-64-asm-def.h"
270# undef MEMCPY_FN
271#endif
272
273 { .name = NULL, }
274};
275
276static const char * const bench_mem_memcpy_usage[] = {
277 "perf bench mem memcpy <options>",
278 NULL
279};
280
281int bench_mem_memcpy(int argc, const char **argv, const char *prefix __maybe_unused)
282{
283 struct bench_mem_info info = {
284 .functions = memcpy_functions,
285 .do_cycles = do_memcpy_cycles,
286 .do_gettimeofday = do_memcpy_gettimeofday,
287 .usage = bench_mem_memcpy_usage,
288 };
289
290 return bench_mem_common(argc, argv, &info);
291}
292
293static void memset_alloc_mem(void **dst, size_t size)
294{
295 *dst = zalloc(size);
296 if (!*dst)
297 die("memory allocation failed - maybe size is too large?\n");
298}
299
300static u64 do_memset_cycles(const struct function *r, size_t size)
301{
302 u64 cycle_start = 0ULL, cycle_end = 0ULL;
303 memset_t fn = r->fn.memset;
304 void *dst = NULL;
305 int i;
306
307 memset_alloc_mem(&dst, size);
308
309 /*
310 * We prefault the freshly allocated memory range here,
311 * to not measure page fault overhead:
312 */
313 fn(dst, -1, size);
314
315 cycle_start = get_cycles();
316 for (i = 0; i < nr_loops; ++i)
317 fn(dst, i, size);
318 cycle_end = get_cycles();
319
320 free(dst);
321 return cycle_end - cycle_start;
322}
323
324static double do_memset_gettimeofday(const struct function *r, size_t size)
325{
326 struct timeval tv_start, tv_end, tv_diff;
327 memset_t fn = r->fn.memset;
328 void *dst = NULL;
329 int i;
330
331 memset_alloc_mem(&dst, size);
332
333 /*
334 * We prefault the freshly allocated memory range here,
335 * to not measure page fault overhead:
336 */
337 fn(dst, -1, size);
338
339 BUG_ON(gettimeofday(&tv_start, NULL));
340 for (i = 0; i < nr_loops; ++i)
341 fn(dst, i, size);
342 BUG_ON(gettimeofday(&tv_end, NULL));
343
344 timersub(&tv_end, &tv_start, &tv_diff);
345
346 free(dst);
347 return (double)(((double)size * nr_loops) / timeval2double(&tv_diff));
348}
349
350static const char * const bench_mem_memset_usage[] = {
351 "perf bench mem memset <options>",
352 NULL
353};
354
355static const struct function memset_functions[] = {
356 { .name = "default",
357 .desc = "Default memset() provided by glibc",
358 .fn.memset = memset },
359
360#ifdef HAVE_ARCH_X86_64_SUPPORT
361# define MEMSET_FN(_fn, _name, _desc) { .name = _name, .desc = _desc, .fn.memset = _fn },
362# include "mem-memset-x86-64-asm-def.h"
363# undef MEMSET_FN
364#endif
365
366 { .name = NULL, }
367};
368
369int bench_mem_memset(int argc, const char **argv, const char *prefix __maybe_unused)
370{
371 struct bench_mem_info info = {
372 .functions = memset_functions,
373 .do_cycles = do_memset_cycles,
374 .do_gettimeofday = do_memset_gettimeofday,
375 .usage = bench_mem_memset_usage,
376 };
377
378 return bench_mem_common(argc, argv, &info);
379}
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
deleted file mode 100644
index d3dfb7936dcd..000000000000
--- a/tools/perf/bench/mem-memcpy.c
+++ /dev/null
@@ -1,434 +0,0 @@
1/*
2 * mem-memcpy.c
3 *
4 * memcpy: Simple memory copy in various ways
5 *
6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
7 */
8
9#include "../perf.h"
10#include "../util/util.h"
11#include "../util/parse-options.h"
12#include "../util/header.h"
13#include "../util/cloexec.h"
14#include "bench.h"
15#include "mem-memcpy-arch.h"
16#include "mem-memset-arch.h"
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <sys/time.h>
22#include <errno.h>
23
24#define K 1024
25
26static const char *length_str = "1MB";
27static const char *routine = "default";
28static int iterations = 1;
29static bool use_cycle;
30static int cycle_fd;
31static bool only_prefault;
32static bool no_prefault;
33
34static const struct option options[] = {
35 OPT_STRING('l', "length", &length_str, "1MB",
36 "Specify length of memory to copy. "
37 "Available units: B, KB, MB, GB and TB (upper and lower)"),
38 OPT_STRING('r', "routine", &routine, "default",
39 "Specify routine to copy, \"all\" runs all available routines"),
40 OPT_INTEGER('i', "iterations", &iterations,
41 "repeat memcpy() invocation this number of times"),
42 OPT_BOOLEAN('c', "cycle", &use_cycle,
43 "Use cycles event instead of gettimeofday() for measuring"),
44 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
45 "Show only the result with page faults before memcpy()"),
46 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
47 "Show only the result without page faults before memcpy()"),
48 OPT_END()
49};
50
51typedef void *(*memcpy_t)(void *, const void *, size_t);
52typedef void *(*memset_t)(void *, int, size_t);
53
54struct routine {
55 const char *name;
56 const char *desc;
57 union {
58 memcpy_t memcpy;
59 memset_t memset;
60 } fn;
61};
62
63struct routine memcpy_routines[] = {
64 { .name = "default",
65 .desc = "Default memcpy() provided by glibc",
66 .fn.memcpy = memcpy },
67#ifdef HAVE_ARCH_X86_64_SUPPORT
68
69#define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn},
70#include "mem-memcpy-x86-64-asm-def.h"
71#undef MEMCPY_FN
72
73#endif
74
75 { NULL,
76 NULL,
77 {NULL} }
78};
79
80static const char * const bench_mem_memcpy_usage[] = {
81 "perf bench mem memcpy <options>",
82 NULL
83};
84
85static struct perf_event_attr cycle_attr = {
86 .type = PERF_TYPE_HARDWARE,
87 .config = PERF_COUNT_HW_CPU_CYCLES
88};
89
90static void init_cycle(void)
91{
92 cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1,
93 perf_event_open_cloexec_flag());
94
95 if (cycle_fd < 0 && errno == ENOSYS)
96 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
97 else
98 BUG_ON(cycle_fd < 0);
99}
100
101static u64 get_cycle(void)
102{
103 int ret;
104 u64 clk;
105
106 ret = read(cycle_fd, &clk, sizeof(u64));
107 BUG_ON(ret != sizeof(u64));
108
109 return clk;
110}
111
112static double timeval2double(struct timeval *ts)
113{
114 return (double)ts->tv_sec +
115 (double)ts->tv_usec / (double)1000000;
116}
117
118#define pf (no_prefault ? 0 : 1)
119
120#define print_bps(x) do { \
121 if (x < K) \
122 printf(" %14lf B/Sec", x); \
123 else if (x < K * K) \
124 printf(" %14lfd KB/Sec", x / K); \
125 else if (x < K * K * K) \
126 printf(" %14lf MB/Sec", x / K / K); \
127 else \
128 printf(" %14lf GB/Sec", x / K / K / K); \
129 } while (0)
130
131struct bench_mem_info {
132 const struct routine *routines;
133 u64 (*do_cycle)(const struct routine *r, size_t len, bool prefault);
134 double (*do_gettimeofday)(const struct routine *r, size_t len, bool prefault);
135 const char *const *usage;
136};
137
138static void __bench_mem_routine(struct bench_mem_info *info, int r_idx, size_t len, double totallen)
139{
140 const struct routine *r = &info->routines[r_idx];
141 double result_bps[2];
142 u64 result_cycle[2];
143
144 result_cycle[0] = result_cycle[1] = 0ULL;
145 result_bps[0] = result_bps[1] = 0.0;
146
147 printf("Routine %s (%s)\n", r->name, r->desc);
148
149 if (bench_format == BENCH_FORMAT_DEFAULT)
150 printf("# Copying %s Bytes ...\n\n", length_str);
151
152 if (!only_prefault && !no_prefault) {
153 /* show both of results */
154 if (use_cycle) {
155 result_cycle[0] = info->do_cycle(r, len, false);
156 result_cycle[1] = info->do_cycle(r, len, true);
157 } else {
158 result_bps[0] = info->do_gettimeofday(r, len, false);
159 result_bps[1] = info->do_gettimeofday(r, len, true);
160 }
161 } else {
162 if (use_cycle)
163 result_cycle[pf] = info->do_cycle(r, len, only_prefault);
164 else
165 result_bps[pf] = info->do_gettimeofday(r, len, only_prefault);
166 }
167
168 switch (bench_format) {
169 case BENCH_FORMAT_DEFAULT:
170 if (!only_prefault && !no_prefault) {
171 if (use_cycle) {
172 printf(" %14lf Cycle/Byte\n",
173 (double)result_cycle[0]
174 / totallen);
175 printf(" %14lf Cycle/Byte (with prefault)\n",
176 (double)result_cycle[1]
177 / totallen);
178 } else {
179 print_bps(result_bps[0]);
180 printf("\n");
181 print_bps(result_bps[1]);
182 printf(" (with prefault)\n");
183 }
184 } else {
185 if (use_cycle) {
186 printf(" %14lf Cycle/Byte",
187 (double)result_cycle[pf]
188 / totallen);
189 } else
190 print_bps(result_bps[pf]);
191
192 printf("%s\n", only_prefault ? " (with prefault)" : "");
193 }
194 break;
195 case BENCH_FORMAT_SIMPLE:
196 if (!only_prefault && !no_prefault) {
197 if (use_cycle) {
198 printf("%lf %lf\n",
199 (double)result_cycle[0] / totallen,
200 (double)result_cycle[1] / totallen);
201 } else {
202 printf("%lf %lf\n",
203 result_bps[0], result_bps[1]);
204 }
205 } else {
206 if (use_cycle) {
207 printf("%lf\n", (double)result_cycle[pf]
208 / totallen);
209 } else
210 printf("%lf\n", result_bps[pf]);
211 }
212 break;
213 default:
214 /* reaching this means there's some disaster: */
215 die("unknown format: %d\n", bench_format);
216 break;
217 }
218}
219
220static int bench_mem_common(int argc, const char **argv,
221 const char *prefix __maybe_unused,
222 struct bench_mem_info *info)
223{
224 int i;
225 size_t len;
226 double totallen;
227
228 argc = parse_options(argc, argv, options,
229 info->usage, 0);
230
231 if (no_prefault && only_prefault) {
232 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
233 return 1;
234 }
235
236 if (use_cycle)
237 init_cycle();
238
239 len = (size_t)perf_atoll((char *)length_str);
240 totallen = (double)len * iterations;
241
242 if ((s64)len <= 0) {
243 fprintf(stderr, "Invalid length:%s\n", length_str);
244 return 1;
245 }
246
247 /* same to without specifying either of prefault and no-prefault */
248 if (only_prefault && no_prefault)
249 only_prefault = no_prefault = false;
250
251 if (!strncmp(routine, "all", 3)) {
252 for (i = 0; info->routines[i].name; i++)
253 __bench_mem_routine(info, i, len, totallen);
254 return 0;
255 }
256
257 for (i = 0; info->routines[i].name; i++) {
258 if (!strcmp(info->routines[i].name, routine))
259 break;
260 }
261 if (!info->routines[i].name) {
262 printf("Unknown routine:%s\n", routine);
263 printf("Available routines...\n");
264 for (i = 0; info->routines[i].name; i++) {
265 printf("\t%s ... %s\n",
266 info->routines[i].name, info->routines[i].desc);
267 }
268 return 1;
269 }
270
271 __bench_mem_routine(info, i, len, totallen);
272
273 return 0;
274}
275
276static void memcpy_alloc_mem(void **dst, void **src, size_t length)
277{
278 *dst = zalloc(length);
279 if (!*dst)
280 die("memory allocation failed - maybe length is too large?\n");
281
282 *src = zalloc(length);
283 if (!*src)
284 die("memory allocation failed - maybe length is too large?\n");
285 /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */
286 memset(*src, 0, length);
287}
288
289static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault)
290{
291 u64 cycle_start = 0ULL, cycle_end = 0ULL;
292 void *src = NULL, *dst = NULL;
293 memcpy_t fn = r->fn.memcpy;
294 int i;
295
296 memcpy_alloc_mem(&dst, &src, len);
297
298 if (prefault)
299 fn(dst, src, len);
300
301 cycle_start = get_cycle();
302 for (i = 0; i < iterations; ++i)
303 fn(dst, src, len);
304 cycle_end = get_cycle();
305
306 free(src);
307 free(dst);
308 return cycle_end - cycle_start;
309}
310
311static double do_memcpy_gettimeofday(const struct routine *r, size_t len,
312 bool prefault)
313{
314 struct timeval tv_start, tv_end, tv_diff;
315 memcpy_t fn = r->fn.memcpy;
316 void *src = NULL, *dst = NULL;
317 int i;
318
319 memcpy_alloc_mem(&dst, &src, len);
320
321 if (prefault)
322 fn(dst, src, len);
323
324 BUG_ON(gettimeofday(&tv_start, NULL));
325 for (i = 0; i < iterations; ++i)
326 fn(dst, src, len);
327 BUG_ON(gettimeofday(&tv_end, NULL));
328
329 timersub(&tv_end, &tv_start, &tv_diff);
330
331 free(src);
332 free(dst);
333 return (double)(((double)len * iterations) / timeval2double(&tv_diff));
334}
335
336int bench_mem_memcpy(int argc, const char **argv,
337 const char *prefix __maybe_unused)
338{
339 struct bench_mem_info info = {
340 .routines = memcpy_routines,
341 .do_cycle = do_memcpy_cycle,
342 .do_gettimeofday = do_memcpy_gettimeofday,
343 .usage = bench_mem_memcpy_usage,
344 };
345
346 return bench_mem_common(argc, argv, prefix, &info);
347}
348
349static void memset_alloc_mem(void **dst, size_t length)
350{
351 *dst = zalloc(length);
352 if (!*dst)
353 die("memory allocation failed - maybe length is too large?\n");
354}
355
356static u64 do_memset_cycle(const struct routine *r, size_t len, bool prefault)
357{
358 u64 cycle_start = 0ULL, cycle_end = 0ULL;
359 memset_t fn = r->fn.memset;
360 void *dst = NULL;
361 int i;
362
363 memset_alloc_mem(&dst, len);
364
365 if (prefault)
366 fn(dst, -1, len);
367
368 cycle_start = get_cycle();
369 for (i = 0; i < iterations; ++i)
370 fn(dst, i, len);
371 cycle_end = get_cycle();
372
373 free(dst);
374 return cycle_end - cycle_start;
375}
376
377static double do_memset_gettimeofday(const struct routine *r, size_t len,
378 bool prefault)
379{
380 struct timeval tv_start, tv_end, tv_diff;
381 memset_t fn = r->fn.memset;
382 void *dst = NULL;
383 int i;
384
385 memset_alloc_mem(&dst, len);
386
387 if (prefault)
388 fn(dst, -1, len);
389
390 BUG_ON(gettimeofday(&tv_start, NULL));
391 for (i = 0; i < iterations; ++i)
392 fn(dst, i, len);
393 BUG_ON(gettimeofday(&tv_end, NULL));
394
395 timersub(&tv_end, &tv_start, &tv_diff);
396
397 free(dst);
398 return (double)(((double)len * iterations) / timeval2double(&tv_diff));
399}
400
401static const char * const bench_mem_memset_usage[] = {
402 "perf bench mem memset <options>",
403 NULL
404};
405
406static const struct routine memset_routines[] = {
407 { .name ="default",
408 .desc = "Default memset() provided by glibc",
409 .fn.memset = memset },
410#ifdef HAVE_ARCH_X86_64_SUPPORT
411
412#define MEMSET_FN(_fn, _name, _desc) { .name = _name, .desc = _desc, .fn.memset = _fn },
413#include "mem-memset-x86-64-asm-def.h"
414#undef MEMSET_FN
415
416#endif
417
418 { .name = NULL,
419 .desc = NULL,
420 .fn.memset = NULL }
421};
422
423int bench_mem_memset(int argc, const char **argv,
424 const char *prefix __maybe_unused)
425{
426 struct bench_mem_info info = {
427 .routines = memset_routines,
428 .do_cycle = do_memset_cycle,
429 .do_gettimeofday = do_memset_gettimeofday,
430 .usage = bench_mem_memset_usage,
431 };
432
433 return bench_mem_common(argc, argv, prefix, &info);
434}
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 870b7e665a20..492df2752a2d 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -164,8 +164,8 @@ static const struct option options[] = {
164 OPT_STRING('L', "mb_proc_locked", &p0.mb_proc_locked_str,"MB", "process serialized/locked memory access (MBs), <= process_memory"), 164 OPT_STRING('L', "mb_proc_locked", &p0.mb_proc_locked_str,"MB", "process serialized/locked memory access (MBs), <= process_memory"),
165 OPT_STRING('T', "mb_thread" , &p0.mb_thread_str, "MB", "thread memory (MBs)"), 165 OPT_STRING('T', "mb_thread" , &p0.mb_thread_str, "MB", "thread memory (MBs)"),
166 166
167 OPT_UINTEGER('l', "nr_loops" , &p0.nr_loops, "max number of loops to run"), 167 OPT_UINTEGER('l', "nr_loops" , &p0.nr_loops, "max number of loops to run (default: unlimited)"),
168 OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run"), 168 OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run (default: 5 secs)"),
169 OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"), 169 OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"),
170 170
171 OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via writes (can be mixed with -W)"), 171 OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via writes (can be mixed with -W)"),
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index d7f281c2828d..d4ff1b539cfd 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -33,7 +33,7 @@
33#define DATASIZE 100 33#define DATASIZE 100
34 34
35static bool use_pipes = false; 35static bool use_pipes = false;
36static unsigned int loops = 100; 36static unsigned int nr_loops = 100;
37static bool thread_mode = false; 37static bool thread_mode = false;
38static unsigned int num_groups = 10; 38static unsigned int num_groups = 10;
39 39
@@ -79,7 +79,7 @@ static void ready(int ready_out, int wakefd)
79 err(EXIT_FAILURE, "poll"); 79 err(EXIT_FAILURE, "poll");
80} 80}
81 81
82/* Sender sprays loops messages down each file descriptor */ 82/* Sender sprays nr_loops messages down each file descriptor */
83static void *sender(struct sender_context *ctx) 83static void *sender(struct sender_context *ctx)
84{ 84{
85 char data[DATASIZE]; 85 char data[DATASIZE];
@@ -88,7 +88,7 @@ static void *sender(struct sender_context *ctx)
88 ready(ctx->ready_out, ctx->wakefd); 88 ready(ctx->ready_out, ctx->wakefd);
89 89
90 /* Now pump to every receiver. */ 90 /* Now pump to every receiver. */
91 for (i = 0; i < loops; i++) { 91 for (i = 0; i < nr_loops; i++) {
92 for (j = 0; j < ctx->num_fds; j++) { 92 for (j = 0; j < ctx->num_fds; j++) {
93 int ret, done = 0; 93 int ret, done = 0;
94 94
@@ -213,7 +213,7 @@ static unsigned int group(pthread_t *pth,
213 /* Create the pipe between client and server */ 213 /* Create the pipe between client and server */
214 fdpair(fds); 214 fdpair(fds);
215 215
216 ctx->num_packets = num_fds * loops; 216 ctx->num_packets = num_fds * nr_loops;
217 ctx->in_fds[0] = fds[0]; 217 ctx->in_fds[0] = fds[0];
218 ctx->in_fds[1] = fds[1]; 218 ctx->in_fds[1] = fds[1];
219 ctx->ready_out = ready_out; 219 ctx->ready_out = ready_out;
@@ -250,7 +250,7 @@ static const struct option options[] = {
250 OPT_BOOLEAN('t', "thread", &thread_mode, 250 OPT_BOOLEAN('t', "thread", &thread_mode,
251 "Be multi thread instead of multi process"), 251 "Be multi thread instead of multi process"),
252 OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"), 252 OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"),
253 OPT_UINTEGER('l', "loop", &loops, "Specify number of loops"), 253 OPT_UINTEGER('l', "nr_loops", &nr_loops, "Specify the number of loops to run (default: 100)"),
254 OPT_END() 254 OPT_END()
255}; 255};
256 256
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 8edc205ff9a7..2bf9b3fd9e61 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -211,7 +211,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
211 } 211 }
212 212
213 if (!objdump_path) { 213 if (!objdump_path) {
214 ret = perf_session_env__lookup_objdump(&session->header.env); 214 ret = perf_env__lookup_objdump(&session->header.env);
215 if (ret) 215 if (ret)
216 goto out; 216 goto out;
217 } 217 }
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index f67934d46d40..b17aed36ca16 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -36,7 +36,7 @@ struct bench {
36#ifdef HAVE_LIBNUMA_SUPPORT 36#ifdef HAVE_LIBNUMA_SUPPORT
37static struct bench numa_benchmarks[] = { 37static struct bench numa_benchmarks[] = {
38 { "mem", "Benchmark for NUMA workloads", bench_numa }, 38 { "mem", "Benchmark for NUMA workloads", bench_numa },
39 { "all", "Test all NUMA benchmarks", NULL }, 39 { "all", "Run all NUMA benchmarks", NULL },
40 { NULL, NULL, NULL } 40 { NULL, NULL, NULL }
41}; 41};
42#endif 42#endif
@@ -44,14 +44,14 @@ static struct bench numa_benchmarks[] = {
44static struct bench sched_benchmarks[] = { 44static struct bench sched_benchmarks[] = {
45 { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging }, 45 { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging },
46 { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe }, 46 { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe },
47 { "all", "Test all scheduler benchmarks", NULL }, 47 { "all", "Run all scheduler benchmarks", NULL },
48 { NULL, NULL, NULL } 48 { NULL, NULL, NULL }
49}; 49};
50 50
51static struct bench mem_benchmarks[] = { 51static struct bench mem_benchmarks[] = {
52 { "memcpy", "Benchmark for memcpy()", bench_mem_memcpy }, 52 { "memcpy", "Benchmark for memcpy() functions", bench_mem_memcpy },
53 { "memset", "Benchmark for memset() tests", bench_mem_memset }, 53 { "memset", "Benchmark for memset() functions", bench_mem_memset },
54 { "all", "Test all memory benchmarks", NULL }, 54 { "all", "Run all memory access benchmarks", NULL },
55 { NULL, NULL, NULL } 55 { NULL, NULL, NULL }
56}; 56};
57 57
@@ -62,7 +62,7 @@ static struct bench futex_benchmarks[] = {
62 { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue }, 62 { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue },
63 /* pi-futexes */ 63 /* pi-futexes */
64 { "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi }, 64 { "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi },
65 { "all", "Test all futex benchmarks", NULL }, 65 { "all", "Run all futex benchmarks", NULL },
66 { NULL, NULL, NULL } 66 { NULL, NULL, NULL }
67}; 67};
68 68
@@ -110,7 +110,7 @@ int bench_format = BENCH_FORMAT_DEFAULT;
110unsigned int bench_repeat = 10; /* default number of times to repeat the run */ 110unsigned int bench_repeat = 10; /* default number of times to repeat the run */
111 111
112static const struct option bench_options[] = { 112static const struct option bench_options[] = {
113 OPT_STRING('f', "format", &bench_format_str, "default", "Specify format style"), 113 OPT_STRING('f', "format", &bench_format_str, "default|simple", "Specify the output formatting style"),
114 OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify amount of times to repeat the run"), 114 OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify amount of times to repeat the run"),
115 OPT_END() 115 OPT_END()
116}; 116};
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 695ec5a50cf2..f4d62510acbb 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -61,8 +61,8 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
61 usage_with_options(evlist_usage, options); 61 usage_with_options(evlist_usage, options);
62 62
63 if (details.event_group && (details.verbose || details.freq)) { 63 if (details.event_group && (details.verbose || details.freq)) {
64 pr_err("--group option is not compatible with other options\n"); 64 usage_with_options_msg(evlist_usage, options,
65 usage_with_options(evlist_usage, options); 65 "--group option is not compatible with other options\n");
66 } 66 }
67 67
68 return __cmd_evlist(input_name, &details); 68 return __cmd_evlist(input_name, &details);
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 36486eade1ef..a7d588bf3cdd 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -463,7 +463,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
463 builtin_help_subcommands, builtin_help_usage, 0); 463 builtin_help_subcommands, builtin_help_usage, 0);
464 464
465 if (show_all) { 465 if (show_all) {
466 printf("\n usage: %s\n\n", perf_usage_string); 466 printf("\n Usage: %s\n\n", perf_usage_string);
467 list_commands("perf commands", &main_cmds, &other_cmds); 467 list_commands("perf commands", &main_cmds, &other_cmds);
468 printf(" %s\n\n", perf_more_info_string); 468 printf(" %s\n\n", perf_more_info_string);
469 return 0; 469 return 0;
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index f62c49b35be0..99d127fe9c35 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -28,9 +28,11 @@ struct perf_inject {
28 bool build_ids; 28 bool build_ids;
29 bool sched_stat; 29 bool sched_stat;
30 bool have_auxtrace; 30 bool have_auxtrace;
31 bool strip;
31 const char *input_name; 32 const char *input_name;
32 struct perf_data_file output; 33 struct perf_data_file output;
33 u64 bytes_written; 34 u64 bytes_written;
35 u64 aux_id;
34 struct list_head samples; 36 struct list_head samples;
35 struct itrace_synth_opts itrace_synth_opts; 37 struct itrace_synth_opts itrace_synth_opts;
36}; 38};
@@ -176,6 +178,27 @@ static int perf_event__repipe(struct perf_tool *tool,
176 return perf_event__repipe_synth(tool, event); 178 return perf_event__repipe_synth(tool, event);
177} 179}
178 180
181static int perf_event__drop(struct perf_tool *tool __maybe_unused,
182 union perf_event *event __maybe_unused,
183 struct perf_sample *sample __maybe_unused,
184 struct machine *machine __maybe_unused)
185{
186 return 0;
187}
188
189static int perf_event__drop_aux(struct perf_tool *tool,
190 union perf_event *event __maybe_unused,
191 struct perf_sample *sample,
192 struct machine *machine __maybe_unused)
193{
194 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
195
196 if (!inject->aux_id)
197 inject->aux_id = sample->id;
198
199 return 0;
200}
201
179typedef int (*inject_handler)(struct perf_tool *tool, 202typedef int (*inject_handler)(struct perf_tool *tool,
180 union perf_event *event, 203 union perf_event *event,
181 struct perf_sample *sample, 204 struct perf_sample *sample,
@@ -466,6 +489,78 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
466 return 0; 489 return 0;
467} 490}
468 491
492static int drop_sample(struct perf_tool *tool __maybe_unused,
493 union perf_event *event __maybe_unused,
494 struct perf_sample *sample __maybe_unused,
495 struct perf_evsel *evsel __maybe_unused,
496 struct machine *machine __maybe_unused)
497{
498 return 0;
499}
500
501static void strip_init(struct perf_inject *inject)
502{
503 struct perf_evlist *evlist = inject->session->evlist;
504 struct perf_evsel *evsel;
505
506 inject->tool.context_switch = perf_event__drop;
507
508 evlist__for_each(evlist, evsel)
509 evsel->handler = drop_sample;
510}
511
512static bool has_tracking(struct perf_evsel *evsel)
513{
514 return evsel->attr.mmap || evsel->attr.mmap2 || evsel->attr.comm ||
515 evsel->attr.task;
516}
517
518#define COMPAT_MASK (PERF_SAMPLE_ID | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | \
519 PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER)
520
521/*
522 * In order that the perf.data file is parsable, tracking events like MMAP need
523 * their selected event to exist, except if there is only 1 selected event left
524 * and it has a compatible sample type.
525 */
526static bool ok_to_remove(struct perf_evlist *evlist,
527 struct perf_evsel *evsel_to_remove)
528{
529 struct perf_evsel *evsel;
530 int cnt = 0;
531 bool ok = false;
532
533 if (!has_tracking(evsel_to_remove))
534 return true;
535
536 evlist__for_each(evlist, evsel) {
537 if (evsel->handler != drop_sample) {
538 cnt += 1;
539 if ((evsel->attr.sample_type & COMPAT_MASK) ==
540 (evsel_to_remove->attr.sample_type & COMPAT_MASK))
541 ok = true;
542 }
543 }
544
545 return ok && cnt == 1;
546}
547
548static void strip_fini(struct perf_inject *inject)
549{
550 struct perf_evlist *evlist = inject->session->evlist;
551 struct perf_evsel *evsel, *tmp;
552
553 /* Remove non-synthesized evsels if possible */
554 evlist__for_each_safe(evlist, tmp, evsel) {
555 if (evsel->handler == drop_sample &&
556 ok_to_remove(evlist, evsel)) {
557 pr_debug("Deleting %s\n", perf_evsel__name(evsel));
558 perf_evlist__remove(evlist, evsel);
559 perf_evsel__delete(evsel);
560 }
561 }
562}
563
469static int __cmd_inject(struct perf_inject *inject) 564static int __cmd_inject(struct perf_inject *inject)
470{ 565{
471 int ret = -EINVAL; 566 int ret = -EINVAL;
@@ -512,10 +607,14 @@ static int __cmd_inject(struct perf_inject *inject)
512 inject->tool.id_index = perf_event__repipe_id_index; 607 inject->tool.id_index = perf_event__repipe_id_index;
513 inject->tool.auxtrace_info = perf_event__process_auxtrace_info; 608 inject->tool.auxtrace_info = perf_event__process_auxtrace_info;
514 inject->tool.auxtrace = perf_event__process_auxtrace; 609 inject->tool.auxtrace = perf_event__process_auxtrace;
610 inject->tool.aux = perf_event__drop_aux;
611 inject->tool.itrace_start = perf_event__drop_aux,
515 inject->tool.ordered_events = true; 612 inject->tool.ordered_events = true;
516 inject->tool.ordering_requires_timestamps = true; 613 inject->tool.ordering_requires_timestamps = true;
517 /* Allow space in the header for new attributes */ 614 /* Allow space in the header for new attributes */
518 output_data_offset = 4096; 615 output_data_offset = 4096;
616 if (inject->strip)
617 strip_init(inject);
519 } 618 }
520 619
521 if (!inject->itrace_synth_opts.set) 620 if (!inject->itrace_synth_opts.set)
@@ -535,11 +634,28 @@ static int __cmd_inject(struct perf_inject *inject)
535 } 634 }
536 /* 635 /*
537 * The AUX areas have been removed and replaced with 636 * The AUX areas have been removed and replaced with
538 * synthesized hardware events, so clear the feature flag. 637 * synthesized hardware events, so clear the feature flag and
638 * remove the evsel.
539 */ 639 */
540 if (inject->itrace_synth_opts.set) 640 if (inject->itrace_synth_opts.set) {
641 struct perf_evsel *evsel;
642
541 perf_header__clear_feat(&session->header, 643 perf_header__clear_feat(&session->header,
542 HEADER_AUXTRACE); 644 HEADER_AUXTRACE);
645 if (inject->itrace_synth_opts.last_branch)
646 perf_header__set_feat(&session->header,
647 HEADER_BRANCH_STACK);
648 evsel = perf_evlist__id2evsel_strict(session->evlist,
649 inject->aux_id);
650 if (evsel) {
651 pr_debug("Deleting %s\n",
652 perf_evsel__name(evsel));
653 perf_evlist__remove(session->evlist, evsel);
654 perf_evsel__delete(evsel);
655 }
656 if (inject->strip)
657 strip_fini(inject);
658 }
543 session->header.data_offset = output_data_offset; 659 session->header.data_offset = output_data_offset;
544 session->header.data_size = inject->bytes_written; 660 session->header.data_size = inject->bytes_written;
545 perf_session__write_header(session, session->evlist, fd, true); 661 perf_session__write_header(session, session->evlist, fd, true);
@@ -559,6 +675,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
559 .fork = perf_event__repipe, 675 .fork = perf_event__repipe,
560 .exit = perf_event__repipe, 676 .exit = perf_event__repipe,
561 .lost = perf_event__repipe, 677 .lost = perf_event__repipe,
678 .lost_samples = perf_event__repipe,
562 .aux = perf_event__repipe, 679 .aux = perf_event__repipe,
563 .itrace_start = perf_event__repipe, 680 .itrace_start = perf_event__repipe,
564 .context_switch = perf_event__repipe, 681 .context_switch = perf_event__repipe,
@@ -604,6 +721,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
604 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, 721 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
605 NULL, "opts", "Instruction Tracing options", 722 NULL, "opts", "Instruction Tracing options",
606 itrace_parse_synth_opts), 723 itrace_parse_synth_opts),
724 OPT_BOOLEAN(0, "strip", &inject.strip,
725 "strip non-synthesized events (use with --itrace)"),
607 OPT_END() 726 OPT_END()
608 }; 727 };
609 const char * const inject_usage[] = { 728 const char * const inject_usage[] = {
@@ -619,6 +738,11 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
619 if (argc) 738 if (argc)
620 usage_with_options(inject_usage, options); 739 usage_with_options(inject_usage, options);
621 740
741 if (inject.strip && !inject.itrace_synth_opts.set) {
742 pr_err("--strip option requires --itrace option\n");
743 return -1;
744 }
745
622 if (perf_data_file__open(&inject.output)) { 746 if (perf_data_file__open(&inject.output)) {
623 perror("failed to create output file"); 747 perror("failed to create output file");
624 return -1; 748 return -1;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 23b1faaaa4cc..93ce665f976f 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -329,7 +329,7 @@ static int build_alloc_func_list(void)
329 return -EINVAL; 329 return -EINVAL;
330 } 330 }
331 331
332 kernel_map = machine->vmlinux_maps[MAP__FUNCTION]; 332 kernel_map = machine__kernel_map(machine);
333 if (map__load(kernel_map, NULL) < 0) { 333 if (map__load(kernel_map, NULL) < 0) {
334 pr_err("cannot load kernel map\n"); 334 pr_err("cannot load kernel map\n");
335 return -ENOENT; 335 return -ENOENT;
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index fc1cffb1b7a2..dd94b4ca2213 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -13,7 +13,6 @@
13#include "util/parse-options.h" 13#include "util/parse-options.h"
14#include "util/trace-event.h" 14#include "util/trace-event.h"
15#include "util/debug.h" 15#include "util/debug.h"
16#include <api/fs/debugfs.h>
17#include "util/tool.h" 16#include "util/tool.h"
18#include "util/stat.h" 17#include "util/stat.h"
19#include "util/top.h" 18#include "util/top.h"
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index af5bd0514108..bf679e2c978b 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -36,7 +36,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
36 36
37 setup_pager(); 37 setup_pager();
38 38
39 if (!raw_dump) 39 if (!raw_dump && pager_in_use())
40 printf("\nList of pre-defined events (to be used in -e):\n\n"); 40 printf("\nList of pre-defined events (to be used in -e):\n\n");
41 41
42 if (argc == 0) { 42 if (argc == 0) {
@@ -45,6 +45,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
45 } 45 }
46 46
47 for (i = 0; i < argc; ++i) { 47 for (i = 0; i < argc; ++i) {
48 char *sep, *s;
49
48 if (strcmp(argv[i], "tracepoint") == 0) 50 if (strcmp(argv[i], "tracepoint") == 0)
49 print_tracepoint_events(NULL, NULL, raw_dump); 51 print_tracepoint_events(NULL, NULL, raw_dump);
50 else if (strcmp(argv[i], "hw") == 0 || 52 else if (strcmp(argv[i], "hw") == 0 ||
@@ -60,8 +62,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
60 print_hwcache_events(NULL, raw_dump); 62 print_hwcache_events(NULL, raw_dump);
61 else if (strcmp(argv[i], "pmu") == 0) 63 else if (strcmp(argv[i], "pmu") == 0)
62 print_pmu_events(NULL, raw_dump); 64 print_pmu_events(NULL, raw_dump);
63 else { 65 else if ((sep = strchr(argv[i], ':')) != NULL) {
64 char *sep = strchr(argv[i], ':'), *s;
65 int sep_idx; 66 int sep_idx;
66 67
67 if (sep == NULL) { 68 if (sep == NULL) {
@@ -76,6 +77,19 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
76 s[sep_idx] = '\0'; 77 s[sep_idx] = '\0';
77 print_tracepoint_events(s, s + sep_idx + 1, raw_dump); 78 print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
78 free(s); 79 free(s);
80 } else {
81 if (asprintf(&s, "*%s*", argv[i]) < 0) {
82 printf("Critical: Not enough memory! Trying to continue...\n");
83 continue;
84 }
85 print_symbol_events(s, PERF_TYPE_HARDWARE,
86 event_symbols_hw, PERF_COUNT_HW_MAX, raw_dump);
87 print_symbol_events(s, PERF_TYPE_SOFTWARE,
88 event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump);
89 print_hwcache_events(s, raw_dump);
90 print_pmu_events(s, raw_dump);
91 print_tracepoint_events(NULL, s, raw_dump);
92 free(s);
79 } 93 }
80 } 94 }
81 return 0; 95 return 0;
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index b81cec33b4b2..132afc97676c 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -37,10 +37,10 @@
37#include "util/strfilter.h" 37#include "util/strfilter.h"
38#include "util/symbol.h" 38#include "util/symbol.h"
39#include "util/debug.h" 39#include "util/debug.h"
40#include <api/fs/debugfs.h>
41#include "util/parse-options.h" 40#include "util/parse-options.h"
42#include "util/probe-finder.h" 41#include "util/probe-finder.h"
43#include "util/probe-event.h" 42#include "util/probe-event.h"
43#include "util/probe-file.h"
44 44
45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" 45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
46#define DEFAULT_FUNC_FILTER "!_*" 46#define DEFAULT_FUNC_FILTER "!_*"
@@ -182,10 +182,8 @@ static int opt_set_target(const struct option *opt, const char *str,
182 if (str) { 182 if (str) {
183 if (!strcmp(opt->long_name, "exec")) 183 if (!strcmp(opt->long_name, "exec"))
184 params.uprobes = true; 184 params.uprobes = true;
185#ifdef HAVE_DWARF_SUPPORT
186 else if (!strcmp(opt->long_name, "module")) 185 else if (!strcmp(opt->long_name, "module"))
187 params.uprobes = false; 186 params.uprobes = false;
188#endif
189 else 187 else
190 return ret; 188 return ret;
191 189
@@ -311,6 +309,119 @@ static void pr_err_with_code(const char *msg, int err)
311 pr_err("\n"); 309 pr_err("\n");
312} 310}
313 311
312static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
313{
314 int ret;
315 int i, k;
316 const char *event = NULL, *group = NULL;
317
318 ret = init_probe_symbol_maps(pevs->uprobes);
319 if (ret < 0)
320 return ret;
321
322 ret = convert_perf_probe_events(pevs, npevs);
323 if (ret < 0)
324 goto out_cleanup;
325
326 ret = apply_perf_probe_events(pevs, npevs);
327 if (ret < 0)
328 goto out_cleanup;
329
330 for (i = k = 0; i < npevs; i++)
331 k += pevs[i].ntevs;
332
333 pr_info("Added new event%s\n", (k > 1) ? "s:" : ":");
334 for (i = 0; i < npevs; i++) {
335 struct perf_probe_event *pev = &pevs[i];
336
337 for (k = 0; k < pev->ntevs; k++) {
338 struct probe_trace_event *tev = &pev->tevs[k];
339
340 /* We use tev's name for showing new events */
341 show_perf_probe_event(tev->group, tev->event, pev,
342 tev->point.module, false);
343
344 /* Save the last valid name */
345 event = tev->event;
346 group = tev->group;
347 }
348 }
349
350 /* Note that it is possible to skip all events because of blacklist */
351 if (event) {
352 /* Show how to use the event. */
353 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
354 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
355 }
356
357out_cleanup:
358 cleanup_perf_probe_events(pevs, npevs);
359 exit_probe_symbol_maps();
360 return ret;
361}
362
363static int perf_del_probe_events(struct strfilter *filter)
364{
365 int ret, ret2, ufd = -1, kfd = -1;
366 char *str = strfilter__string(filter);
367 struct strlist *klist = NULL, *ulist = NULL;
368 struct str_node *ent;
369
370 if (!str)
371 return -EINVAL;
372
373 pr_debug("Delete filter: \'%s\'\n", str);
374
375 /* Get current event names */
376 ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW);
377 if (ret < 0)
378 goto out;
379
380 klist = strlist__new(NULL, NULL);
381 ulist = strlist__new(NULL, NULL);
382 if (!klist || !ulist) {
383 ret = -ENOMEM;
384 goto out;
385 }
386
387 ret = probe_file__get_events(kfd, filter, klist);
388 if (ret == 0) {
389 strlist__for_each(ent, klist)
390 pr_info("Removed event: %s\n", ent->s);
391
392 ret = probe_file__del_strlist(kfd, klist);
393 if (ret < 0)
394 goto error;
395 }
396
397 ret2 = probe_file__get_events(ufd, filter, ulist);
398 if (ret2 == 0) {
399 strlist__for_each(ent, ulist)
400 pr_info("Removed event: %s\n", ent->s);
401
402 ret2 = probe_file__del_strlist(ufd, ulist);
403 if (ret2 < 0)
404 goto error;
405 }
406
407 if (ret == -ENOENT && ret2 == -ENOENT)
408 pr_debug("\"%s\" does not hit any event.\n", str);
409 /* Note that this is silently ignored */
410 ret = 0;
411
412error:
413 if (kfd >= 0)
414 close(kfd);
415 if (ufd >= 0)
416 close(ufd);
417out:
418 strlist__delete(klist);
419 strlist__delete(ulist);
420 free(str);
421
422 return ret;
423}
424
314static int 425static int
315__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) 426__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
316{ 427{
@@ -377,9 +488,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
377 "file", "vmlinux pathname"), 488 "file", "vmlinux pathname"),
378 OPT_STRING('s', "source", &symbol_conf.source_prefix, 489 OPT_STRING('s', "source", &symbol_conf.source_prefix,
379 "directory", "path to kernel source"), 490 "directory", "path to kernel source"),
380 OPT_CALLBACK('m', "module", NULL, "modname|path",
381 "target module name (for online) or path (for offline)",
382 opt_set_target),
383 OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines, 491 OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
384 "Don't search inlined functions"), 492 "Don't search inlined functions"),
385#endif 493#endif
@@ -396,6 +504,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
396 opt_set_filter), 504 opt_set_filter),
397 OPT_CALLBACK('x', "exec", NULL, "executable|path", 505 OPT_CALLBACK('x', "exec", NULL, "executable|path",
398 "target executable name or path", opt_set_target), 506 "target executable name or path", opt_set_target),
507 OPT_CALLBACK('m', "module", NULL, "modname|path",
508 "target module name (for online) or path (for offline)",
509 opt_set_target),
399 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 510 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
400 "Enable symbol demangling"), 511 "Enable symbol demangling"),
401 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 512 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
@@ -417,12 +528,12 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
417 PARSE_OPT_STOP_AT_NON_OPTION); 528 PARSE_OPT_STOP_AT_NON_OPTION);
418 if (argc > 0) { 529 if (argc > 0) {
419 if (strcmp(argv[0], "-") == 0) { 530 if (strcmp(argv[0], "-") == 0) {
420 pr_warning(" Error: '-' is not supported.\n"); 531 usage_with_options_msg(probe_usage, options,
421 usage_with_options(probe_usage, options); 532 "'-' is not supported.\n");
422 } 533 }
423 if (params.command && params.command != 'a') { 534 if (params.command && params.command != 'a') {
424 pr_warning(" Error: another command except --add is set.\n"); 535 usage_with_options_msg(probe_usage, options,
425 usage_with_options(probe_usage, options); 536 "another command except --add is set.\n");
426 } 537 }
427 ret = parse_probe_event_argv(argc, argv); 538 ret = parse_probe_event_argv(argc, argv);
428 if (ret < 0) { 539 if (ret < 0) {
@@ -451,8 +562,10 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
451 switch (params.command) { 562 switch (params.command) {
452 case 'l': 563 case 'l':
453 if (params.uprobes) { 564 if (params.uprobes) {
454 pr_warning(" Error: Don't use --list with --exec.\n"); 565 pr_err(" Error: Don't use --list with --exec.\n");
455 usage_with_options(probe_usage, options); 566 parse_options_usage(probe_usage, options, "l", true);
567 parse_options_usage(NULL, options, "x", true);
568 return -EINVAL;
456 } 569 }
457 ret = show_perf_probe_events(params.filter); 570 ret = show_perf_probe_events(params.filter);
458 if (ret < 0) 571 if (ret < 0)
@@ -483,7 +596,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
483 return ret; 596 return ret;
484#endif 597#endif
485 case 'd': 598 case 'd':
486 ret = del_perf_probe_events(params.filter); 599 ret = perf_del_probe_events(params.filter);
487 if (ret < 0) { 600 if (ret < 0) {
488 pr_err_with_code(" Error: Failed to delete events.", ret); 601 pr_err_with_code(" Error: Failed to delete events.", ret);
489 return ret; 602 return ret;
@@ -492,11 +605,13 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
492 case 'a': 605 case 'a':
493 /* Ensure the last given target is used */ 606 /* Ensure the last given target is used */
494 if (params.target && !params.target_used) { 607 if (params.target && !params.target_used) {
495 pr_warning(" Error: -x/-m must follow the probe definitions.\n"); 608 pr_err(" Error: -x/-m must follow the probe definitions.\n");
496 usage_with_options(probe_usage, options); 609 parse_options_usage(probe_usage, options, "m", true);
610 parse_options_usage(NULL, options, "x", true);
611 return -EINVAL;
497 } 612 }
498 613
499 ret = add_perf_probe_events(params.events, params.nevents); 614 ret = perf_add_probe_events(params.events, params.nevents);
500 if (ret < 0) { 615 if (ret < 0) {
501 pr_err_with_code(" Error: Failed to add events.", ret); 616 pr_err_with_code(" Error: Failed to add events.", ret);
502 return ret; 617 return ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 142eeb341b29..199fc31e3919 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,6 +31,7 @@
31#include "util/auxtrace.h" 31#include "util/auxtrace.h"
32#include "util/parse-branch-options.h" 32#include "util/parse-branch-options.h"
33#include "util/parse-regs-options.h" 33#include "util/parse-regs-options.h"
34#include "util/llvm-utils.h"
34 35
35#include <unistd.h> 36#include <unistd.h>
36#include <sched.h> 37#include <sched.h>
@@ -49,7 +50,7 @@ struct record {
49 int realtime_prio; 50 int realtime_prio;
50 bool no_buildid; 51 bool no_buildid;
51 bool no_buildid_cache; 52 bool no_buildid_cache;
52 long samples; 53 unsigned long long samples;
53}; 54};
54 55
55static int record__write(struct record *rec, void *bf, size_t size) 56static int record__write(struct record *rec, void *bf, size_t size)
@@ -636,8 +637,29 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
636 /* 637 /*
637 * Let the child rip 638 * Let the child rip
638 */ 639 */
639 if (forks) 640 if (forks) {
641 union perf_event *event;
642
643 event = malloc(sizeof(event->comm) + machine->id_hdr_size);
644 if (event == NULL) {
645 err = -ENOMEM;
646 goto out_child;
647 }
648
649 /*
650 * Some H/W events are generated before COMM event
651 * which is emitted during exec(), so perf script
652 * cannot see a correct process name for those events.
653 * Synthesize COMM event to prevent it.
654 */
655 perf_event__synthesize_comm(tool, event,
656 rec->evlist->workload.pid,
657 process_synthesized_event,
658 machine);
659 free(event);
660
640 perf_evlist__start_workload(rec->evlist); 661 perf_evlist__start_workload(rec->evlist);
662 }
641 663
642 if (opts->initial_delay) { 664 if (opts->initial_delay) {
643 usleep(opts->initial_delay * 1000); 665 usleep(opts->initial_delay * 1000);
@@ -646,7 +668,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
646 668
647 auxtrace_snapshot_enabled = 1; 669 auxtrace_snapshot_enabled = 1;
648 for (;;) { 670 for (;;) {
649 int hits = rec->samples; 671 unsigned long long hits = rec->samples;
650 672
651 if (record__mmap_read_all(rec) < 0) { 673 if (record__mmap_read_all(rec) < 0) {
652 auxtrace_snapshot_enabled = 0; 674 auxtrace_snapshot_enabled = 0;
@@ -989,13 +1011,8 @@ static struct record record = {
989 }, 1011 },
990}; 1012};
991 1013
992#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 1014const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
993 1015 "\n\t\t\t\tDefault: fp";
994#ifdef HAVE_DWARF_UNWIND_SUPPORT
995const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
996#else
997const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
998#endif
999 1016
1000/* 1017/*
1001 * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1018 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
@@ -1043,7 +1060,7 @@ struct option __record_options[] = {
1043 NULL, "enables call-graph recording" , 1060 NULL, "enables call-graph recording" ,
1044 &record_callchain_opt), 1061 &record_callchain_opt),
1045 OPT_CALLBACK(0, "call-graph", &record.opts, 1062 OPT_CALLBACK(0, "call-graph", &record.opts,
1046 "mode[,dump_size]", record_callchain_help, 1063 "record_mode[,record_size]", record_callchain_help,
1047 &record_parse_callchain_opt), 1064 &record_parse_callchain_opt),
1048 OPT_INCR('v', "verbose", &verbose, 1065 OPT_INCR('v', "verbose", &verbose,
1049 "be more verbose (show counter open errors, etc)"), 1066 "be more verbose (show counter open errors, etc)"),
@@ -1096,6 +1113,12 @@ struct option __record_options[] = {
1096 "per thread proc mmap processing timeout in ms"), 1113 "per thread proc mmap processing timeout in ms"),
1097 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1114 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1098 "Record context switch events"), 1115 "Record context switch events"),
1116#ifdef HAVE_LIBBPF_SUPPORT
1117 OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
1118 "clang binary to use for compiling BPF scriptlets"),
1119 OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
1120 "options passed to clang when compiling BPF scriptlets"),
1121#endif
1099 OPT_END() 1122 OPT_END()
1100}; 1123};
1101 1124
@@ -1119,14 +1142,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1119 usage_with_options(record_usage, record_options); 1142 usage_with_options(record_usage, record_options);
1120 1143
1121 if (nr_cgroups && !rec->opts.target.system_wide) { 1144 if (nr_cgroups && !rec->opts.target.system_wide) {
1122 ui__error("cgroup monitoring only available in" 1145 usage_with_options_msg(record_usage, record_options,
1123 " system-wide mode\n"); 1146 "cgroup monitoring only available in system-wide mode");
1124 usage_with_options(record_usage, record_options); 1147
1125 } 1148 }
1126 if (rec->opts.record_switch_events && 1149 if (rec->opts.record_switch_events &&
1127 !perf_can_record_switch_events()) { 1150 !perf_can_record_switch_events()) {
1128 ui__error("kernel does not support recording context switch events (--switch-events option)\n"); 1151 ui__error("kernel does not support recording context switch events\n");
1129 usage_with_options(record_usage, record_options); 1152 parse_options_usage(record_usage, record_options, "switch-events", 0);
1153 return -EINVAL;
1130 } 1154 }
1131 1155
1132 if (!rec->itr) { 1156 if (!rec->itr) {
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 62b285e32aa5..f256fac1e722 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -44,7 +44,7 @@
44struct report { 44struct report {
45 struct perf_tool tool; 45 struct perf_tool tool;
46 struct perf_session *session; 46 struct perf_session *session;
47 bool force, use_tui, use_gtk, use_stdio; 47 bool use_tui, use_gtk, use_stdio;
48 bool hide_unresolved; 48 bool hide_unresolved;
49 bool dont_use_callchains; 49 bool dont_use_callchains;
50 bool show_full_info; 50 bool show_full_info;
@@ -62,6 +62,7 @@ struct report {
62 float min_percent; 62 float min_percent;
63 u64 nr_entries; 63 u64 nr_entries;
64 u64 queue_size; 64 u64 queue_size;
65 int socket_filter;
65 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 66 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
66}; 67};
67 68
@@ -162,14 +163,21 @@ static int process_sample_event(struct perf_tool *tool,
162 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) 163 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
163 goto out_put; 164 goto out_put;
164 165
165 if (sort__mode == SORT_MODE__BRANCH) 166 if (sort__mode == SORT_MODE__BRANCH) {
167 /*
168 * A non-synthesized event might not have a branch stack if
169 * branch stacks have been synthesized (using itrace options).
170 */
171 if (!sample->branch_stack)
172 goto out_put;
166 iter.ops = &hist_iter_branch; 173 iter.ops = &hist_iter_branch;
167 else if (rep->mem_mode) 174 } else if (rep->mem_mode) {
168 iter.ops = &hist_iter_mem; 175 iter.ops = &hist_iter_mem;
169 else if (symbol_conf.cumulate_callchain) 176 } else if (symbol_conf.cumulate_callchain) {
170 iter.ops = &hist_iter_cumulative; 177 iter.ops = &hist_iter_cumulative;
171 else 178 } else {
172 iter.ops = &hist_iter_normal; 179 iter.ops = &hist_iter_normal;
180 }
173 181
174 if (al.map != NULL) 182 if (al.map != NULL)
175 al.map->dso->hit = 1; 183 al.map->dso->hit = 1;
@@ -213,6 +221,15 @@ static int report__setup_sample_type(struct report *rep)
213 u64 sample_type = perf_evlist__combined_sample_type(session->evlist); 221 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
214 bool is_pipe = perf_data_file__is_pipe(session->file); 222 bool is_pipe = perf_data_file__is_pipe(session->file);
215 223
224 if (session->itrace_synth_opts->callchain ||
225 (!is_pipe &&
226 perf_header__has_feat(&session->header, HEADER_AUXTRACE) &&
227 !session->itrace_synth_opts->set))
228 sample_type |= PERF_SAMPLE_CALLCHAIN;
229
230 if (session->itrace_synth_opts->last_branch)
231 sample_type |= PERF_SAMPLE_BRANCH_STACK;
232
216 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { 233 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
217 if (sort__has_parent) { 234 if (sort__has_parent) {
218 ui__error("Selected --sort parent, but no " 235 ui__error("Selected --sort parent, but no "
@@ -286,6 +303,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
286 struct perf_evsel *evsel = hists_to_evsel(hists); 303 struct perf_evsel *evsel = hists_to_evsel(hists);
287 char buf[512]; 304 char buf[512];
288 size_t size = sizeof(buf); 305 size_t size = sizeof(buf);
306 int socked_id = hists->socket_filter;
289 307
290 if (symbol_conf.filter_relative) { 308 if (symbol_conf.filter_relative) {
291 nr_samples = hists->stats.nr_non_filtered_samples; 309 nr_samples = hists->stats.nr_non_filtered_samples;
@@ -326,6 +344,10 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
326 ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order); 344 ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order);
327 } else 345 } else
328 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events); 346 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
347
348 if (socked_id > -1)
349 ret += fprintf(fp, "\n# Processor Socket: %d", socked_id);
350
329 return ret + fprintf(fp, "\n#\n"); 351 return ret + fprintf(fp, "\n#\n");
330} 352}
331 353
@@ -365,7 +387,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
365 387
366static void report__warn_kptr_restrict(const struct report *rep) 388static void report__warn_kptr_restrict(const struct report *rep)
367{ 389{
368 struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION]; 390 struct map *kernel_map = machine__kernel_map(&rep->session->machines.host);
369 struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL; 391 struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
370 392
371 if (kernel_map == NULL || 393 if (kernel_map == NULL ||
@@ -450,6 +472,8 @@ static void report__collapse_hists(struct report *rep)
450 if (pos->idx == 0) 472 if (pos->idx == 0)
451 hists->symbol_filter_str = rep->symbol_filter_str; 473 hists->symbol_filter_str = rep->symbol_filter_str;
452 474
475 hists->socket_filter = rep->socket_filter;
476
453 hists__collapse_resort(hists, &prog); 477 hists__collapse_resort(hists, &prog);
454 478
455 /* Non-group events are considered as leader */ 479 /* Non-group events are considered as leader */
@@ -601,6 +625,12 @@ parse_percent_limit(const struct option *opt, const char *str,
601 return 0; 625 return 0;
602} 626}
603 627
628#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function"
629
630const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
631 CALLCHAIN_REPORT_HELP
632 "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
633
604int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) 634int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
605{ 635{
606 struct perf_session *session; 636 struct perf_session *session;
@@ -609,7 +639,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
609 bool has_br_stack = false; 639 bool has_br_stack = false;
610 int branch_mode = -1; 640 int branch_mode = -1;
611 bool branch_call_mode = false; 641 bool branch_call_mode = false;
612 char callchain_default_opt[] = "fractal,0.5,callee"; 642 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
613 const char * const report_usage[] = { 643 const char * const report_usage[] = {
614 "perf report [<options>]", 644 "perf report [<options>]",
615 NULL 645 NULL
@@ -635,6 +665,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
635 }, 665 },
636 .max_stack = PERF_MAX_STACK_DEPTH, 666 .max_stack = PERF_MAX_STACK_DEPTH,
637 .pretty_printing_style = "normal", 667 .pretty_printing_style = "normal",
668 .socket_filter = -1,
638 }; 669 };
639 const struct option options[] = { 670 const struct option options[] = {
640 OPT_STRING('i', "input", &input_name, "file", 671 OPT_STRING('i', "input", &input_name, "file",
@@ -647,7 +678,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
647 "file", "vmlinux pathname"), 678 "file", "vmlinux pathname"),
648 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 679 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
649 "file", "kallsyms pathname"), 680 "file", "kallsyms pathname"),
650 OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"), 681 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
651 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 682 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
652 "load module symbols - WARNING: use only with -k and LIVE kernel"), 683 "load module symbols - WARNING: use only with -k and LIVE kernel"),
653 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 684 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
@@ -668,15 +699,18 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
668 " Please refer the man page for the complete list."), 699 " Please refer the man page for the complete list."),
669 OPT_STRING('F', "fields", &field_order, "key[,keys...]", 700 OPT_STRING('F', "fields", &field_order, "key[,keys...]",
670 "output field(s): overhead, period, sample plus all of sort keys"), 701 "output field(s): overhead, period, sample plus all of sort keys"),
671 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 702 OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization,
672 "Show sample percentage for different cpu modes"), 703 "Show sample percentage for different cpu modes"),
704 OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
705 "Show sample percentage for different cpu modes", PARSE_OPT_HIDDEN),
673 OPT_STRING('p', "parent", &parent_pattern, "regex", 706 OPT_STRING('p', "parent", &parent_pattern, "regex",
674 "regex filter to identify parent, see: '--sort parent'"), 707 "regex filter to identify parent, see: '--sort parent'"),
675 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 708 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
676 "Only display entries with parent-match"), 709 "Only display entries with parent-match"),
677 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]", 710 OPT_CALLBACK_DEFAULT('g', "call-graph", &report,
678 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. " 711 "print_type,threshold[,print_limit],order,sort_key[,branch]",
679 "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt), 712 report_callchain_help, &report_parse_callchain_opt,
713 callchain_default_opt),
680 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 714 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
681 "Accumulate callchains of children and show total overhead as well"), 715 "Accumulate callchains of children and show total overhead as well"),
682 OPT_INTEGER(0, "max-stack", &report.max_stack, 716 OPT_INTEGER(0, "max-stack", &report.max_stack,
@@ -747,6 +781,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
747 "Show full source file name path for source lines"), 781 "Show full source file name path for source lines"),
748 OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph, 782 OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph,
749 "Show callgraph from reference event"), 783 "Show callgraph from reference event"),
784 OPT_INTEGER(0, "socket-filter", &report.socket_filter,
785 "only show processor socket that match with this filter"),
750 OPT_END() 786 OPT_END()
751 }; 787 };
752 struct perf_data_file file = { 788 struct perf_data_file file = {
@@ -781,6 +817,12 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
781 817
782 if (report.inverted_callchain) 818 if (report.inverted_callchain)
783 callchain_param.order = ORDER_CALLER; 819 callchain_param.order = ORDER_CALLER;
820 if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
821 callchain_param.order = ORDER_CALLER;
822
823 if (itrace_synth_opts.callchain &&
824 (int)itrace_synth_opts.callchain_sz > report.max_stack)
825 report.max_stack = itrace_synth_opts.callchain_sz;
784 826
785 if (!input_name || !strlen(input_name)) { 827 if (!input_name || !strlen(input_name)) {
786 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 828 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
@@ -790,7 +832,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
790 } 832 }
791 833
792 file.path = input_name; 834 file.path = input_name;
793 file.force = report.force; 835 file.force = symbol_conf.force;
794 836
795repeat: 837repeat:
796 session = perf_session__new(&file, false, &report.tool); 838 session = perf_session__new(&file, false, &report.tool);
@@ -809,6 +851,9 @@ repeat:
809 has_br_stack = perf_header__has_feat(&session->header, 851 has_br_stack = perf_header__has_feat(&session->header,
810 HEADER_BRANCH_STACK); 852 HEADER_BRANCH_STACK);
811 853
854 if (itrace_synth_opts.last_branch)
855 has_br_stack = true;
856
812 /* 857 /*
813 * Branch mode is a tristate: 858 * Branch mode is a tristate:
814 * -1 means default, so decide based on the file having branch data. 859 * -1 means default, so decide based on the file having branch data.
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 33962612a5e9..e3d3e32c0a93 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1203,12 +1203,13 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1203 1203
1204static int pid_cmp(struct work_atoms *l, struct work_atoms *r) 1204static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
1205{ 1205{
1206 if (l->thread == r->thread)
1207 return 0;
1206 if (l->thread->tid < r->thread->tid) 1208 if (l->thread->tid < r->thread->tid)
1207 return -1; 1209 return -1;
1208 if (l->thread->tid > r->thread->tid) 1210 if (l->thread->tid > r->thread->tid)
1209 return 1; 1211 return 1;
1210 1212 return (int)(l->thread - r->thread);
1211 return 0;
1212} 1213}
1213 1214
1214static int avg_cmp(struct work_atoms *l, struct work_atoms *r) 1215static int avg_cmp(struct work_atoms *l, struct work_atoms *r)
@@ -1728,8 +1729,8 @@ static void setup_sorting(struct perf_sched *sched, const struct option *options
1728 for (tok = strtok_r(str, ", ", &tmp); 1729 for (tok = strtok_r(str, ", ", &tmp);
1729 tok; tok = strtok_r(NULL, ", ", &tmp)) { 1730 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1730 if (sort_dimension__add(tok, &sched->sort_list) < 0) { 1731 if (sort_dimension__add(tok, &sched->sort_list) < 0) {
1731 error("Unknown --sort key: `%s'", tok); 1732 usage_with_options_msg(usage_msg, options,
1732 usage_with_options(usage_msg, options); 1733 "Unknown --sort key: `%s'", tok);
1733 } 1734 }
1734 } 1735 }
1735 1736
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 284a76e04628..72b5deb4bd79 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -29,9 +29,12 @@ static bool no_callchain;
29static bool latency_format; 29static bool latency_format;
30static bool system_wide; 30static bool system_wide;
31static bool print_flags; 31static bool print_flags;
32static bool nanosecs;
32static const char *cpu_list; 33static const char *cpu_list;
33static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 34static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
34 35
36unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
37
35enum perf_output_field { 38enum perf_output_field {
36 PERF_OUTPUT_COMM = 1U << 0, 39 PERF_OUTPUT_COMM = 1U << 0,
37 PERF_OUTPUT_TID = 1U << 1, 40 PERF_OUTPUT_TID = 1U << 1,
@@ -48,6 +51,8 @@ enum perf_output_field {
48 PERF_OUTPUT_SRCLINE = 1U << 12, 51 PERF_OUTPUT_SRCLINE = 1U << 12,
49 PERF_OUTPUT_PERIOD = 1U << 13, 52 PERF_OUTPUT_PERIOD = 1U << 13,
50 PERF_OUTPUT_IREGS = 1U << 14, 53 PERF_OUTPUT_IREGS = 1U << 14,
54 PERF_OUTPUT_BRSTACK = 1U << 15,
55 PERF_OUTPUT_BRSTACKSYM = 1U << 16,
51}; 56};
52 57
53struct output_option { 58struct output_option {
@@ -69,6 +74,8 @@ struct output_option {
69 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 74 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
70 {.str = "period", .field = PERF_OUTPUT_PERIOD}, 75 {.str = "period", .field = PERF_OUTPUT_PERIOD},
71 {.str = "iregs", .field = PERF_OUTPUT_IREGS}, 76 {.str = "iregs", .field = PERF_OUTPUT_IREGS},
77 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
78 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
72}; 79};
73 80
74/* default set to maintain compatibility with current format */ 81/* default set to maintain compatibility with current format */
@@ -415,10 +422,84 @@ static void print_sample_start(struct perf_sample *sample,
415 secs = nsecs / NSECS_PER_SEC; 422 secs = nsecs / NSECS_PER_SEC;
416 nsecs -= secs * NSECS_PER_SEC; 423 nsecs -= secs * NSECS_PER_SEC;
417 usecs = nsecs / NSECS_PER_USEC; 424 usecs = nsecs / NSECS_PER_USEC;
418 printf("%5lu.%06lu: ", secs, usecs); 425 if (nanosecs)
426 printf("%5lu.%09llu: ", secs, nsecs);
427 else
428 printf("%5lu.%06lu: ", secs, usecs);
419 } 429 }
420} 430}
421 431
432static inline char
433mispred_str(struct branch_entry *br)
434{
435 if (!(br->flags.mispred || br->flags.predicted))
436 return '-';
437
438 return br->flags.predicted ? 'P' : 'M';
439}
440
441static void print_sample_brstack(union perf_event *event __maybe_unused,
442 struct perf_sample *sample,
443 struct thread *thread __maybe_unused,
444 struct perf_event_attr *attr __maybe_unused)
445{
446 struct branch_stack *br = sample->branch_stack;
447 u64 i;
448
449 if (!(br && br->nr))
450 return;
451
452 for (i = 0; i < br->nr; i++) {
453 printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ",
454 br->entries[i].from,
455 br->entries[i].to,
456 mispred_str( br->entries + i),
457 br->entries[i].flags.in_tx? 'X' : '-',
458 br->entries[i].flags.abort? 'A' : '-',
459 br->entries[i].flags.cycles);
460 }
461}
462
463static void print_sample_brstacksym(union perf_event *event __maybe_unused,
464 struct perf_sample *sample,
465 struct thread *thread __maybe_unused,
466 struct perf_event_attr *attr __maybe_unused)
467{
468 struct branch_stack *br = sample->branch_stack;
469 struct addr_location alf, alt;
470 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
471 u64 i, from, to;
472
473 if (!(br && br->nr))
474 return;
475
476 for (i = 0; i < br->nr; i++) {
477
478 memset(&alf, 0, sizeof(alf));
479 memset(&alt, 0, sizeof(alt));
480 from = br->entries[i].from;
481 to = br->entries[i].to;
482
483 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, from, &alf);
484 if (alf.map)
485 alf.sym = map__find_symbol(alf.map, alf.addr, NULL);
486
487 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, to, &alt);
488 if (alt.map)
489 alt.sym = map__find_symbol(alt.map, alt.addr, NULL);
490
491 symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
492 putchar('/');
493 symbol__fprintf_symname_offs(alt.sym, &alt, stdout);
494 printf("/%c/%c/%c/%d ",
495 mispred_str( br->entries + i),
496 br->entries[i].flags.in_tx? 'X' : '-',
497 br->entries[i].flags.abort? 'A' : '-',
498 br->entries[i].flags.cycles);
499 }
500}
501
502
422static void print_sample_addr(union perf_event *event, 503static void print_sample_addr(union perf_event *event,
423 struct perf_sample *sample, 504 struct perf_sample *sample,
424 struct thread *thread, 505 struct thread *thread,
@@ -471,7 +552,7 @@ static void print_sample_bts(union perf_event *event,
471 } 552 }
472 } 553 }
473 perf_evsel__print_ip(evsel, sample, al, print_opts, 554 perf_evsel__print_ip(evsel, sample, al, print_opts,
474 PERF_MAX_STACK_DEPTH); 555 scripting_max_stack);
475 } 556 }
476 557
477 /* print branch_to information */ 558 /* print branch_to information */
@@ -548,12 +629,17 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
548 629
549 perf_evsel__print_ip(evsel, sample, al, 630 perf_evsel__print_ip(evsel, sample, al,
550 output[attr->type].print_ip_opts, 631 output[attr->type].print_ip_opts,
551 PERF_MAX_STACK_DEPTH); 632 scripting_max_stack);
552 } 633 }
553 634
554 if (PRINT_FIELD(IREGS)) 635 if (PRINT_FIELD(IREGS))
555 print_sample_iregs(event, sample, thread, attr); 636 print_sample_iregs(event, sample, thread, attr);
556 637
638 if (PRINT_FIELD(BRSTACK))
639 print_sample_brstack(event, sample, thread, attr);
640 else if (PRINT_FIELD(BRSTACKSYM))
641 print_sample_brstacksym(event, sample, thread, attr);
642
557 printf("\n"); 643 printf("\n");
558} 644}
559 645
@@ -680,7 +766,10 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
680 766
681 set_print_ip_opts(&evsel->attr); 767 set_print_ip_opts(&evsel->attr);
682 768
683 return perf_evsel__check_attr(evsel, scr->session); 769 if (evsel->attr.sample_type)
770 err = perf_evsel__check_attr(evsel, scr->session);
771
772 return err;
684} 773}
685 774
686static int process_comm_event(struct perf_tool *tool, 775static int process_comm_event(struct perf_tool *tool,
@@ -1672,7 +1761,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1672 "comma separated output fields prepend with 'type:'. " 1761 "comma separated output fields prepend with 'type:'. "
1673 "Valid types: hw,sw,trace,raw. " 1762 "Valid types: hw,sw,trace,raw. "
1674 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1763 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1675 "addr,symoff,period,iregs,flags", parse_output_fields), 1764 "addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields),
1676 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1765 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1677 "system-wide collection from all CPUs"), 1766 "system-wide collection from all CPUs"),
1678 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1767 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -1695,6 +1784,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1695 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events, 1784 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
1696 "Show context switch events (if recorded)"), 1785 "Show context switch events (if recorded)"),
1697 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 1786 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
1787 OPT_BOOLEAN(0, "ns", &nanosecs,
1788 "Use 9 decimal places when displaying time"),
1698 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 1789 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
1699 "Instruction Tracing options", 1790 "Instruction Tracing options",
1700 itrace_parse_synth_opts), 1791 itrace_parse_synth_opts),
@@ -1740,6 +1831,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1740 } 1831 }
1741 } 1832 }
1742 1833
1834 if (itrace_synth_opts.callchain &&
1835 itrace_synth_opts.callchain_sz > scripting_max_stack)
1836 scripting_max_stack = itrace_synth_opts.callchain_sz;
1837
1743 /* make sure PERF_EXEC_PATH is set for scripts */ 1838 /* make sure PERF_EXEC_PATH is set for scripts */
1744 perf_set_argv_exec_path(perf_exec_path()); 1839 perf_set_argv_exec_path(perf_exec_path());
1745 1840
@@ -1752,9 +1847,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1752 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX); 1847 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
1753 1848
1754 if (!rec_script_path && !rep_script_path) { 1849 if (!rec_script_path && !rep_script_path) {
1755 fprintf(stderr, " Couldn't find script %s\n\n See perf" 1850 usage_with_options_msg(script_usage, options,
1851 "Couldn't find script `%s'\n\n See perf"
1756 " script -l for available scripts.\n", argv[0]); 1852 " script -l for available scripts.\n", argv[0]);
1757 usage_with_options(script_usage, options);
1758 } 1853 }
1759 1854
1760 if (is_top_script(argv[0])) { 1855 if (is_top_script(argv[0])) {
@@ -1765,10 +1860,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1765 rep_args = has_required_arg(rep_script_path); 1860 rep_args = has_required_arg(rep_script_path);
1766 rec_args = (argc - 1) - rep_args; 1861 rec_args = (argc - 1) - rep_args;
1767 if (rec_args < 0) { 1862 if (rec_args < 0) {
1768 fprintf(stderr, " %s script requires options." 1863 usage_with_options_msg(script_usage, options,
1864 "`%s' script requires options."
1769 "\n\n See perf script -l for available " 1865 "\n\n See perf script -l for available "
1770 "scripts and options.\n", argv[0]); 1866 "scripts and options.\n", argv[0]);
1771 usage_with_options(script_usage, options);
1772 } 1867 }
1773 } 1868 }
1774 1869
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d46dbb1bc65d..e77880b5094d 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -100,6 +100,8 @@ static struct target target = {
100 .uid = UINT_MAX, 100 .uid = UINT_MAX,
101}; 101};
102 102
103typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
104
103static int run_count = 1; 105static int run_count = 1;
104static bool no_inherit = false; 106static bool no_inherit = false;
105static volatile pid_t child_pid = -1; 107static volatile pid_t child_pid = -1;
@@ -119,7 +121,10 @@ static unsigned int unit_width = 4; /* strlen("unit") */
119static bool forever = false; 121static bool forever = false;
120static struct timespec ref_time; 122static struct timespec ref_time;
121static struct cpu_map *aggr_map; 123static struct cpu_map *aggr_map;
122static int (*aggr_get_id)(struct cpu_map *m, int cpu); 124static aggr_get_id_t aggr_get_id;
125static bool append_file;
126static const char *output_name;
127static int output_fd;
123 128
124static volatile int done = 0; 129static volatile int done = 0;
125 130
@@ -215,7 +220,7 @@ static void read_counters(bool close_counters)
215 220
216 evlist__for_each(evsel_list, counter) { 221 evlist__for_each(evsel_list, counter) {
217 if (read_counter(counter)) 222 if (read_counter(counter))
218 pr_warning("failed to read counter %s\n", counter->name); 223 pr_debug("failed to read counter %s\n", counter->name);
219 224
220 if (perf_stat_process_counter(&stat_config, counter)) 225 if (perf_stat_process_counter(&stat_config, counter))
221 pr_warning("failed to process counter %s\n", counter->name); 226 pr_warning("failed to process counter %s\n", counter->name);
@@ -434,7 +439,7 @@ static void print_noise_pct(double total, double avg)
434 439
435static void print_noise(struct perf_evsel *evsel, double avg) 440static void print_noise(struct perf_evsel *evsel, double avg)
436{ 441{
437 struct perf_stat *ps; 442 struct perf_stat_evsel *ps;
438 443
439 if (run_count == 1) 444 if (run_count == 1)
440 return; 445 return;
@@ -479,6 +484,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
479 csv_sep); 484 csv_sep);
480 break; 485 break;
481 case AGGR_GLOBAL: 486 case AGGR_GLOBAL:
487 case AGGR_UNSET:
482 default: 488 default:
483 break; 489 break;
484 } 490 }
@@ -510,15 +516,6 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
510 516
511 if (evsel->cgrp) 517 if (evsel->cgrp)
512 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 518 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
513
514 if (csv_output || stat_config.interval)
515 return;
516
517 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
518 fprintf(output, " # %8.3f CPUs utilized ",
519 avg / avg_stats(&walltime_nsecs_stats));
520 else
521 fprintf(output, " ");
522} 519}
523 520
524static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) 521static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
@@ -526,7 +523,6 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
526 FILE *output = stat_config.output; 523 FILE *output = stat_config.output;
527 double sc = evsel->scale; 524 double sc = evsel->scale;
528 const char *fmt; 525 const char *fmt;
529 int cpu = cpu_map__id_to_cpu(id);
530 526
531 if (csv_output) { 527 if (csv_output) {
532 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s"; 528 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
@@ -539,9 +535,6 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
539 535
540 aggr_printout(evsel, id, nr); 536 aggr_printout(evsel, id, nr);
541 537
542 if (stat_config.aggr_mode == AGGR_GLOBAL)
543 cpu = 0;
544
545 fprintf(output, fmt, avg, csv_sep); 538 fprintf(output, fmt, avg, csv_sep);
546 539
547 if (evsel->unit) 540 if (evsel->unit)
@@ -553,12 +546,24 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
553 546
554 if (evsel->cgrp) 547 if (evsel->cgrp)
555 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 548 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
549}
556 550
557 if (csv_output || stat_config.interval) 551static void printout(int id, int nr, struct perf_evsel *counter, double uval)
558 return; 552{
553 int cpu = cpu_map__id_to_cpu(id);
554
555 if (stat_config.aggr_mode == AGGR_GLOBAL)
556 cpu = 0;
559 557
560 perf_stat__print_shadow_stats(output, evsel, avg, cpu, 558 if (nsec_counter(counter))
561 stat_config.aggr_mode); 559 nsec_printout(id, nr, counter, uval);
560 else
561 abs_printout(id, nr, counter, uval);
562
563 if (!csv_output && !stat_config.interval)
564 perf_stat__print_shadow_stats(stat_config.output, counter,
565 uval, cpu,
566 stat_config.aggr_mode);
562} 567}
563 568
564static void print_aggr(char *prefix) 569static void print_aggr(char *prefix)
@@ -614,12 +619,7 @@ static void print_aggr(char *prefix)
614 continue; 619 continue;
615 } 620 }
616 uval = val * counter->scale; 621 uval = val * counter->scale;
617 622 printout(id, nr, counter, uval);
618 if (nsec_counter(counter))
619 nsec_printout(id, nr, counter, uval);
620 else
621 abs_printout(id, nr, counter, uval);
622
623 if (!csv_output) 623 if (!csv_output)
624 print_noise(counter, 1.0); 624 print_noise(counter, 1.0);
625 625
@@ -650,11 +650,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
650 fprintf(output, "%s", prefix); 650 fprintf(output, "%s", prefix);
651 651
652 uval = val * counter->scale; 652 uval = val * counter->scale;
653 653 printout(thread, 0, counter, uval);
654 if (nsec_counter(counter))
655 nsec_printout(thread, 0, counter, uval);
656 else
657 abs_printout(thread, 0, counter, uval);
658 654
659 if (!csv_output) 655 if (!csv_output)
660 print_noise(counter, 1.0); 656 print_noise(counter, 1.0);
@@ -671,7 +667,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
671static void print_counter_aggr(struct perf_evsel *counter, char *prefix) 667static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
672{ 668{
673 FILE *output = stat_config.output; 669 FILE *output = stat_config.output;
674 struct perf_stat *ps = counter->priv; 670 struct perf_stat_evsel *ps = counter->priv;
675 double avg = avg_stats(&ps->res_stats[0]); 671 double avg = avg_stats(&ps->res_stats[0]);
676 int scaled = counter->counts->scaled; 672 int scaled = counter->counts->scaled;
677 double uval; 673 double uval;
@@ -704,11 +700,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
704 } 700 }
705 701
706 uval = avg * counter->scale; 702 uval = avg * counter->scale;
707 703 printout(-1, 0, counter, uval);
708 if (nsec_counter(counter))
709 nsec_printout(-1, 0, counter, uval);
710 else
711 abs_printout(-1, 0, counter, uval);
712 704
713 print_noise(counter, avg); 705 print_noise(counter, avg);
714 706
@@ -761,12 +753,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
761 } 753 }
762 754
763 uval = val * counter->scale; 755 uval = val * counter->scale;
764 756 printout(cpu, 0, counter, uval);
765 if (nsec_counter(counter))
766 nsec_printout(cpu, 0, counter, uval);
767 else
768 abs_printout(cpu, 0, counter, uval);
769
770 if (!csv_output) 757 if (!csv_output)
771 print_noise(counter, 1.0); 758 print_noise(counter, 1.0);
772 print_running(run, ena); 759 print_running(run, ena);
@@ -799,6 +786,8 @@ static void print_interval(char *prefix, struct timespec *ts)
799 case AGGR_GLOBAL: 786 case AGGR_GLOBAL:
800 default: 787 default:
801 fprintf(output, "# time counts %*s events\n", unit_width, "unit"); 788 fprintf(output, "# time counts %*s events\n", unit_width, "unit");
789 case AGGR_UNSET:
790 break;
802 } 791 }
803 } 792 }
804 793
@@ -880,6 +869,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
880 evlist__for_each(evsel_list, counter) 869 evlist__for_each(evsel_list, counter)
881 print_counter(counter, prefix); 870 print_counter(counter, prefix);
882 break; 871 break;
872 case AGGR_UNSET:
883 default: 873 default:
884 break; 874 break;
885 } 875 }
@@ -940,30 +930,151 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
940 return 0; 930 return 0;
941} 931}
942 932
933static const struct option stat_options[] = {
934 OPT_BOOLEAN('T', "transaction", &transaction_run,
935 "hardware transaction statistics"),
936 OPT_CALLBACK('e', "event", &evsel_list, "event",
937 "event selector. use 'perf list' to list available events",
938 parse_events_option),
939 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
940 "event filter", parse_filter),
941 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
942 "child tasks do not inherit counters"),
943 OPT_STRING('p', "pid", &target.pid, "pid",
944 "stat events on existing process id"),
945 OPT_STRING('t', "tid", &target.tid, "tid",
946 "stat events on existing thread id"),
947 OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
948 "system-wide collection from all CPUs"),
949 OPT_BOOLEAN('g', "group", &group,
950 "put the counters into a counter group"),
951 OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"),
952 OPT_INCR('v', "verbose", &verbose,
953 "be more verbose (show counter open errors, etc)"),
954 OPT_INTEGER('r', "repeat", &run_count,
955 "repeat command and print average + stddev (max: 100, forever: 0)"),
956 OPT_BOOLEAN('n', "null", &null_run,
957 "null run - dont start any counters"),
958 OPT_INCR('d', "detailed", &detailed_run,
959 "detailed run - start a lot of events"),
960 OPT_BOOLEAN('S', "sync", &sync_run,
961 "call sync() before starting a run"),
962 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
963 "print large numbers with thousands\' separators",
964 stat__set_big_num),
965 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
966 "list of cpus to monitor in system-wide"),
967 OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
968 "disable CPU count aggregation", AGGR_NONE),
969 OPT_STRING('x', "field-separator", &csv_sep, "separator",
970 "print counts with custom separator"),
971 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
972 "monitor event in cgroup name only", parse_cgroups),
973 OPT_STRING('o', "output", &output_name, "file", "output file name"),
974 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
975 OPT_INTEGER(0, "log-fd", &output_fd,
976 "log output to fd, instead of stderr"),
977 OPT_STRING(0, "pre", &pre_cmd, "command",
978 "command to run prior to the measured command"),
979 OPT_STRING(0, "post", &post_cmd, "command",
980 "command to run after to the measured command"),
981 OPT_UINTEGER('I', "interval-print", &stat_config.interval,
982 "print counts at regular interval in ms (>= 10)"),
983 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
984 "aggregate counts per processor socket", AGGR_SOCKET),
985 OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
986 "aggregate counts per physical processor core", AGGR_CORE),
987 OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
988 "aggregate counts per thread", AGGR_THREAD),
989 OPT_UINTEGER('D', "delay", &initial_delay,
990 "ms to wait before starting measurement after program start"),
991 OPT_END()
992};
993
994static int perf_stat__get_socket(struct cpu_map *map, int cpu)
995{
996 return cpu_map__get_socket(map, cpu, NULL);
997}
998
999static int perf_stat__get_core(struct cpu_map *map, int cpu)
1000{
1001 return cpu_map__get_core(map, cpu, NULL);
1002}
1003
1004static int cpu_map__get_max(struct cpu_map *map)
1005{
1006 int i, max = -1;
1007
1008 for (i = 0; i < map->nr; i++) {
1009 if (map->map[i] > max)
1010 max = map->map[i];
1011 }
1012
1013 return max;
1014}
1015
1016static struct cpu_map *cpus_aggr_map;
1017
1018static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx)
1019{
1020 int cpu;
1021
1022 if (idx >= map->nr)
1023 return -1;
1024
1025 cpu = map->map[idx];
1026
1027 if (cpus_aggr_map->map[cpu] == -1)
1028 cpus_aggr_map->map[cpu] = get_id(map, idx);
1029
1030 return cpus_aggr_map->map[cpu];
1031}
1032
1033static int perf_stat__get_socket_cached(struct cpu_map *map, int idx)
1034{
1035 return perf_stat__get_aggr(perf_stat__get_socket, map, idx);
1036}
1037
1038static int perf_stat__get_core_cached(struct cpu_map *map, int idx)
1039{
1040 return perf_stat__get_aggr(perf_stat__get_core, map, idx);
1041}
1042
943static int perf_stat_init_aggr_mode(void) 1043static int perf_stat_init_aggr_mode(void)
944{ 1044{
1045 int nr;
1046
945 switch (stat_config.aggr_mode) { 1047 switch (stat_config.aggr_mode) {
946 case AGGR_SOCKET: 1048 case AGGR_SOCKET:
947 if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { 1049 if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
948 perror("cannot build socket map"); 1050 perror("cannot build socket map");
949 return -1; 1051 return -1;
950 } 1052 }
951 aggr_get_id = cpu_map__get_socket; 1053 aggr_get_id = perf_stat__get_socket_cached;
952 break; 1054 break;
953 case AGGR_CORE: 1055 case AGGR_CORE:
954 if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { 1056 if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
955 perror("cannot build core map"); 1057 perror("cannot build core map");
956 return -1; 1058 return -1;
957 } 1059 }
958 aggr_get_id = cpu_map__get_core; 1060 aggr_get_id = perf_stat__get_core_cached;
959 break; 1061 break;
960 case AGGR_NONE: 1062 case AGGR_NONE:
961 case AGGR_GLOBAL: 1063 case AGGR_GLOBAL:
962 case AGGR_THREAD: 1064 case AGGR_THREAD:
1065 case AGGR_UNSET:
963 default: 1066 default:
964 break; 1067 break;
965 } 1068 }
966 return 0; 1069
1070 /*
1071 * The evsel_list->cpus is the base we operate on,
1072 * taking the highest cpu number to be the size of
1073 * the aggregation translate cpumap.
1074 */
1075 nr = cpu_map__get_max(evsel_list->cpus);
1076 cpus_aggr_map = cpu_map__empty_new(nr + 1);
1077 return cpus_aggr_map ? 0 : -ENOMEM;
967} 1078}
968 1079
969/* 1080/*
@@ -1127,69 +1238,6 @@ static int add_default_attributes(void)
1127 1238
1128int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) 1239int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1129{ 1240{
1130 bool append_file = false;
1131 int output_fd = 0;
1132 const char *output_name = NULL;
1133 const struct option options[] = {
1134 OPT_BOOLEAN('T', "transaction", &transaction_run,
1135 "hardware transaction statistics"),
1136 OPT_CALLBACK('e', "event", &evsel_list, "event",
1137 "event selector. use 'perf list' to list available events",
1138 parse_events_option),
1139 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1140 "event filter", parse_filter),
1141 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1142 "child tasks do not inherit counters"),
1143 OPT_STRING('p', "pid", &target.pid, "pid",
1144 "stat events on existing process id"),
1145 OPT_STRING('t', "tid", &target.tid, "tid",
1146 "stat events on existing thread id"),
1147 OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
1148 "system-wide collection from all CPUs"),
1149 OPT_BOOLEAN('g', "group", &group,
1150 "put the counters into a counter group"),
1151 OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"),
1152 OPT_INCR('v', "verbose", &verbose,
1153 "be more verbose (show counter open errors, etc)"),
1154 OPT_INTEGER('r', "repeat", &run_count,
1155 "repeat command and print average + stddev (max: 100, forever: 0)"),
1156 OPT_BOOLEAN('n', "null", &null_run,
1157 "null run - dont start any counters"),
1158 OPT_INCR('d', "detailed", &detailed_run,
1159 "detailed run - start a lot of events"),
1160 OPT_BOOLEAN('S', "sync", &sync_run,
1161 "call sync() before starting a run"),
1162 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1163 "print large numbers with thousands\' separators",
1164 stat__set_big_num),
1165 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
1166 "list of cpus to monitor in system-wide"),
1167 OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
1168 "disable CPU count aggregation", AGGR_NONE),
1169 OPT_STRING('x', "field-separator", &csv_sep, "separator",
1170 "print counts with custom separator"),
1171 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1172 "monitor event in cgroup name only", parse_cgroups),
1173 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1174 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1175 OPT_INTEGER(0, "log-fd", &output_fd,
1176 "log output to fd, instead of stderr"),
1177 OPT_STRING(0, "pre", &pre_cmd, "command",
1178 "command to run prior to the measured command"),
1179 OPT_STRING(0, "post", &post_cmd, "command",
1180 "command to run after to the measured command"),
1181 OPT_UINTEGER('I', "interval-print", &stat_config.interval,
1182 "print counts at regular interval in ms (>= 100)"),
1183 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
1184 "aggregate counts per processor socket", AGGR_SOCKET),
1185 OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
1186 "aggregate counts per physical processor core", AGGR_CORE),
1187 OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
1188 "aggregate counts per thread", AGGR_THREAD),
1189 OPT_UINTEGER('D', "delay", &initial_delay,
1190 "ms to wait before starting measurement after program start"),
1191 OPT_END()
1192 };
1193 const char * const stat_usage[] = { 1241 const char * const stat_usage[] = {
1194 "perf stat [<options>] [<command>]", 1242 "perf stat [<options>] [<command>]",
1195 NULL 1243 NULL
@@ -1205,7 +1253,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1205 if (evsel_list == NULL) 1253 if (evsel_list == NULL)
1206 return -ENOMEM; 1254 return -ENOMEM;
1207 1255
1208 argc = parse_options(argc, argv, options, stat_usage, 1256 argc = parse_options(argc, argv, stat_options, stat_usage,
1209 PARSE_OPT_STOP_AT_NON_OPTION); 1257 PARSE_OPT_STOP_AT_NON_OPTION);
1210 1258
1211 interval = stat_config.interval; 1259 interval = stat_config.interval;
@@ -1215,14 +1263,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1215 1263
1216 if (output_name && output_fd) { 1264 if (output_name && output_fd) {
1217 fprintf(stderr, "cannot use both --output and --log-fd\n"); 1265 fprintf(stderr, "cannot use both --output and --log-fd\n");
1218 parse_options_usage(stat_usage, options, "o", 1); 1266 parse_options_usage(stat_usage, stat_options, "o", 1);
1219 parse_options_usage(NULL, options, "log-fd", 0); 1267 parse_options_usage(NULL, stat_options, "log-fd", 0);
1220 goto out; 1268 goto out;
1221 } 1269 }
1222 1270
1223 if (output_fd < 0) { 1271 if (output_fd < 0) {
1224 fprintf(stderr, "argument to --log-fd must be a > 0\n"); 1272 fprintf(stderr, "argument to --log-fd must be a > 0\n");
1225 parse_options_usage(stat_usage, options, "log-fd", 0); 1273 parse_options_usage(stat_usage, stat_options, "log-fd", 0);
1226 goto out; 1274 goto out;
1227 } 1275 }
1228 1276
@@ -1262,8 +1310,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1262 /* User explicitly passed -B? */ 1310 /* User explicitly passed -B? */
1263 if (big_num_opt == 1) { 1311 if (big_num_opt == 1) {
1264 fprintf(stderr, "-B option not supported with -x\n"); 1312 fprintf(stderr, "-B option not supported with -x\n");
1265 parse_options_usage(stat_usage, options, "B", 1); 1313 parse_options_usage(stat_usage, stat_options, "B", 1);
1266 parse_options_usage(NULL, options, "x", 1); 1314 parse_options_usage(NULL, stat_options, "x", 1);
1267 goto out; 1315 goto out;
1268 } else /* Nope, so disable big number formatting */ 1316 } else /* Nope, so disable big number formatting */
1269 big_num = false; 1317 big_num = false;
@@ -1271,11 +1319,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1271 big_num = false; 1319 big_num = false;
1272 1320
1273 if (!argc && target__none(&target)) 1321 if (!argc && target__none(&target))
1274 usage_with_options(stat_usage, options); 1322 usage_with_options(stat_usage, stat_options);
1275 1323
1276 if (run_count < 0) { 1324 if (run_count < 0) {
1277 pr_err("Run count must be a positive number\n"); 1325 pr_err("Run count must be a positive number\n");
1278 parse_options_usage(stat_usage, options, "r", 1); 1326 parse_options_usage(stat_usage, stat_options, "r", 1);
1279 goto out; 1327 goto out;
1280 } else if (run_count == 0) { 1328 } else if (run_count == 0) {
1281 forever = true; 1329 forever = true;
@@ -1285,8 +1333,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1285 if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) { 1333 if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
1286 fprintf(stderr, "The --per-thread option is only available " 1334 fprintf(stderr, "The --per-thread option is only available "
1287 "when monitoring via -p -t options.\n"); 1335 "when monitoring via -p -t options.\n");
1288 parse_options_usage(NULL, options, "p", 1); 1336 parse_options_usage(NULL, stat_options, "p", 1);
1289 parse_options_usage(NULL, options, "t", 1); 1337 parse_options_usage(NULL, stat_options, "t", 1);
1290 goto out; 1338 goto out;
1291 } 1339 }
1292 1340
@@ -1300,9 +1348,9 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1300 fprintf(stderr, "both cgroup and no-aggregation " 1348 fprintf(stderr, "both cgroup and no-aggregation "
1301 "modes only available in system-wide mode\n"); 1349 "modes only available in system-wide mode\n");
1302 1350
1303 parse_options_usage(stat_usage, options, "G", 1); 1351 parse_options_usage(stat_usage, stat_options, "G", 1);
1304 parse_options_usage(NULL, options, "A", 1); 1352 parse_options_usage(NULL, stat_options, "A", 1);
1305 parse_options_usage(NULL, options, "a", 1); 1353 parse_options_usage(NULL, stat_options, "a", 1);
1306 goto out; 1354 goto out;
1307 } 1355 }
1308 1356
@@ -1314,12 +1362,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1314 if (perf_evlist__create_maps(evsel_list, &target) < 0) { 1362 if (perf_evlist__create_maps(evsel_list, &target) < 0) {
1315 if (target__has_task(&target)) { 1363 if (target__has_task(&target)) {
1316 pr_err("Problems finding threads of monitor\n"); 1364 pr_err("Problems finding threads of monitor\n");
1317 parse_options_usage(stat_usage, options, "p", 1); 1365 parse_options_usage(stat_usage, stat_options, "p", 1);
1318 parse_options_usage(NULL, options, "t", 1); 1366 parse_options_usage(NULL, stat_options, "t", 1);
1319 } else if (target__has_cpu(&target)) { 1367 } else if (target__has_cpu(&target)) {
1320 perror("failed to parse CPUs map"); 1368 perror("failed to parse CPUs map");
1321 parse_options_usage(stat_usage, options, "C", 1); 1369 parse_options_usage(stat_usage, stat_options, "C", 1);
1322 parse_options_usage(NULL, options, "a", 1); 1370 parse_options_usage(NULL, stat_options, "a", 1);
1323 } 1371 }
1324 goto out; 1372 goto out;
1325 } 1373 }
@@ -1332,9 +1380,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1332 thread_map__read_comms(evsel_list->threads); 1380 thread_map__read_comms(evsel_list->threads);
1333 1381
1334 if (interval && interval < 100) { 1382 if (interval && interval < 100) {
1335 pr_err("print interval must be >= 100ms\n"); 1383 if (interval < 10) {
1336 parse_options_usage(stat_usage, options, "I", 1); 1384 pr_err("print interval must be >= 10ms\n");
1337 goto out; 1385 parse_options_usage(stat_usage, stat_options, "I", 1);
1386 goto out;
1387 } else
1388 pr_warning("print interval < 100ms. "
1389 "The overhead percentage could be high in some cases. "
1390 "Please proceed with caution.\n");
1338 } 1391 }
1339 1392
1340 if (perf_evlist__alloc_stats(evsel_list, interval)) 1393 if (perf_evlist__alloc_stats(evsel_list, interval))
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 8c465c83aabf..7e2e72e6d9d1 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -655,7 +655,7 @@ static int symbol_filter(struct map *map, struct symbol *sym)
655{ 655{
656 const char *name = sym->name; 656 const char *name = sym->name;
657 657
658 if (!map->dso->kernel) 658 if (!__map__is_kernel(map))
659 return 0; 659 return 0;
660 /* 660 /*
661 * ppc64 uses function descriptors and appends a '.' to the 661 * ppc64 uses function descriptors and appends a '.' to the
@@ -857,9 +857,12 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
857 * TODO: we don't process guest user from host side 857 * TODO: we don't process guest user from host side
858 * except simple counting. 858 * except simple counting.
859 */ 859 */
860 /* Fall thru */
861 default:
862 goto next_event; 860 goto next_event;
861 default:
862 if (event->header.type == PERF_RECORD_SAMPLE)
863 goto next_event;
864 machine = &session->machines.host;
865 break;
863 } 866 }
864 867
865 868
@@ -952,7 +955,7 @@ static int __cmd_top(struct perf_top *top)
952 machines__set_symbol_filter(&top->session->machines, symbol_filter); 955 machines__set_symbol_filter(&top->session->machines, symbol_filter);
953 956
954 if (!objdump_path) { 957 if (!objdump_path) {
955 ret = perf_session_env__lookup_objdump(&top->session->header.env); 958 ret = perf_env__lookup_objdump(&top->session->header.env);
956 if (ret) 959 if (ret)
957 goto out_delete; 960 goto out_delete;
958 } 961 }
@@ -961,8 +964,18 @@ static int __cmd_top(struct perf_top *top)
961 if (ret) 964 if (ret)
962 goto out_delete; 965 goto out_delete;
963 966
967 if (perf_session__register_idle_thread(top->session) == NULL)
968 goto out_delete;
969
964 machine__synthesize_threads(&top->session->machines.host, &opts->target, 970 machine__synthesize_threads(&top->session->machines.host, &opts->target,
965 top->evlist->threads, false, opts->proc_map_timeout); 971 top->evlist->threads, false, opts->proc_map_timeout);
972
973 if (sort__has_socket) {
974 ret = perf_env__read_cpu_topology_map(&perf_env);
975 if (ret < 0)
976 goto out_err_cpu_topo;
977 }
978
966 ret = perf_top__start_counters(top); 979 ret = perf_top__start_counters(top);
967 if (ret) 980 if (ret)
968 goto out_delete; 981 goto out_delete;
@@ -1020,6 +1033,14 @@ out_delete:
1020 top->session = NULL; 1033 top->session = NULL;
1021 1034
1022 return ret; 1035 return ret;
1036
1037out_err_cpu_topo: {
1038 char errbuf[BUFSIZ];
1039 const char *err = strerror_r(-ret, errbuf, sizeof(errbuf));
1040
1041 ui__error("Could not read the CPU topology map: %s\n", err);
1042 goto out_delete;
1043}
1023} 1044}
1024 1045
1025static int 1046static int
@@ -1032,8 +1053,22 @@ callchain_opt(const struct option *opt, const char *arg, int unset)
1032static int 1053static int
1033parse_callchain_opt(const struct option *opt, const char *arg, int unset) 1054parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1034{ 1055{
1035 symbol_conf.use_callchain = true; 1056 struct record_opts *record = (struct record_opts *)opt->value;
1036 return record_parse_callchain_opt(opt, arg, unset); 1057
1058 record->callgraph_set = true;
1059 callchain_param.enabled = !unset;
1060 callchain_param.record_mode = CALLCHAIN_FP;
1061
1062 /*
1063 * --no-call-graph
1064 */
1065 if (unset) {
1066 symbol_conf.use_callchain = false;
1067 callchain_param.record_mode = CALLCHAIN_NONE;
1068 return 0;
1069 }
1070
1071 return parse_callchain_top_opt(arg);
1037} 1072}
1038 1073
1039static int perf_top_config(const char *var, const char *value, void *cb) 1074static int perf_top_config(const char *var, const char *value, void *cb)
@@ -1058,6 +1093,9 @@ parse_percent_limit(const struct option *opt, const char *arg,
1058 return 0; 1093 return 0;
1059} 1094}
1060 1095
1096const char top_callchain_help[] = CALLCHAIN_RECORD_HELP CALLCHAIN_REPORT_HELP
1097 "\n\t\t\t\tDefault: fp,graph,0.5,caller,function";
1098
1061int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1099int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1062{ 1100{
1063 char errbuf[BUFSIZ]; 1101 char errbuf[BUFSIZ];
@@ -1133,11 +1171,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1133 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1171 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1134 "Show a column with the number of samples"), 1172 "Show a column with the number of samples"),
1135 OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts, 1173 OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts,
1136 NULL, "enables call-graph recording", 1174 NULL, "enables call-graph recording and display",
1137 &callchain_opt), 1175 &callchain_opt),
1138 OPT_CALLBACK(0, "call-graph", &top.record_opts, 1176 OPT_CALLBACK(0, "call-graph", &top.record_opts,
1139 "mode[,dump_size]", record_callchain_help, 1177 "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]",
1140 &parse_callchain_opt), 1178 top_callchain_help, &parse_callchain_opt),
1141 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 1179 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
1142 "Accumulate callchains of children and show total overhead as well"), 1180 "Accumulate callchains of children and show total overhead as well"),
1143 OPT_INTEGER(0, "max-stack", &top.max_stack, 1181 OPT_INTEGER(0, "max-stack", &top.max_stack,
@@ -1267,6 +1305,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1267 perf_hpp__cancel_cumulate(); 1305 perf_hpp__cancel_cumulate();
1268 } 1306 }
1269 1307
1308 if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
1309 callchain_param.order = ORDER_CALLER;
1310
1270 symbol_conf.priv_size = sizeof(struct annotation); 1311 symbol_conf.priv_size = sizeof(struct annotation);
1271 1312
1272 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1313 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4e3abba03062..c783d8fd3a80 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -17,6 +17,7 @@
17 */ 17 */
18 18
19#include <traceevent/event-parse.h> 19#include <traceevent/event-parse.h>
20#include <api/fs/tracing_path.h>
20#include "builtin.h" 21#include "builtin.h"
21#include "util/color.h" 22#include "util/color.h"
22#include "util/debug.h" 23#include "util/debug.h"
@@ -37,6 +38,7 @@
37#include <stdlib.h> 38#include <stdlib.h>
38#include <sys/mman.h> 39#include <sys/mman.h>
39#include <linux/futex.h> 40#include <linux/futex.h>
41#include <linux/err.h>
40 42
41/* For older distros: */ 43/* For older distros: */
42#ifndef MAP_STACK 44#ifndef MAP_STACK
@@ -244,13 +246,14 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
244 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); 246 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
245 247
246 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */ 248 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
247 if (evsel == NULL) 249 if (IS_ERR(evsel))
248 evsel = perf_evsel__newtp("syscalls", direction); 250 evsel = perf_evsel__newtp("syscalls", direction);
249 251
250 if (evsel) { 252 if (IS_ERR(evsel))
251 if (perf_evsel__init_syscall_tp(evsel, handler)) 253 return NULL;
252 goto out_delete; 254
253 } 255 if (perf_evsel__init_syscall_tp(evsel, handler))
256 goto out_delete;
254 257
255 return evsel; 258 return evsel;
256 259
@@ -582,6 +585,12 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct sysc
582 585
583#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op 586#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
584 587
588static const char *bpf_cmd[] = {
589 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
590 "MAP_GET_NEXT_KEY", "PROG_LOAD",
591};
592static DEFINE_STRARRAY(bpf_cmd);
593
585static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", }; 594static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
586static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1); 595static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
587 596
@@ -1008,6 +1017,7 @@ static struct syscall_fmt {
1008 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ 1017 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
1009 [1] = SCA_ACCMODE, /* mode */ }, }, 1018 [1] = SCA_ACCMODE, /* mode */ }, },
1010 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 1019 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
1020 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
1011 { .name = "brk", .hexret = true, 1021 { .name = "brk", .hexret = true,
1012 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 1022 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
1013 { .name = "chdir", .errmsg = true, 1023 { .name = "chdir", .errmsg = true,
@@ -1704,12 +1714,12 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1704 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); 1714 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
1705 sc->tp_format = trace_event__tp_format("syscalls", tp_name); 1715 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1706 1716
1707 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) { 1717 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
1708 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias); 1718 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
1709 sc->tp_format = trace_event__tp_format("syscalls", tp_name); 1719 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1710 } 1720 }
1711 1721
1712 if (sc->tp_format == NULL) 1722 if (IS_ERR(sc->tp_format))
1713 return -1; 1723 return -1;
1714 1724
1715 sc->args = sc->tp_format->format.fields; 1725 sc->args = sc->tp_format->format.fields;
@@ -2389,7 +2399,8 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2389static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) 2399static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
2390{ 2400{
2391 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname"); 2401 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
2392 if (evsel == NULL) 2402
2403 if (IS_ERR(evsel))
2393 return false; 2404 return false;
2394 2405
2395 if (perf_evsel__field(evsel, "pathname") == NULL) { 2406 if (perf_evsel__field(evsel, "pathname") == NULL) {
@@ -2686,11 +2697,11 @@ out_delete_evlist:
2686 char errbuf[BUFSIZ]; 2697 char errbuf[BUFSIZ];
2687 2698
2688out_error_sched_stat_runtime: 2699out_error_sched_stat_runtime:
2689 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime"); 2700 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
2690 goto out_error; 2701 goto out_error;
2691 2702
2692out_error_raw_syscalls: 2703out_error_raw_syscalls:
2693 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)"); 2704 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
2694 goto out_error; 2705 goto out_error;
2695 2706
2696out_error_mmap: 2707out_error_mmap:
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 38a08539f4bf..de89ec574361 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -106,9 +106,14 @@ ifdef LIBBABELTRACE
106 FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf 106 FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
107endif 107endif
108 108
109FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi
109# include ARCH specific config 110# include ARCH specific config
110-include $(src-perf)/arch/$(ARCH)/Makefile 111-include $(src-perf)/arch/$(ARCH)/Makefile
111 112
113ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
114 CFLAGS += -DHAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
115endif
116
112include $(src-perf)/config/utilities.mak 117include $(src-perf)/config/utilities.mak
113 118
114ifeq ($(call get-executable,$(FLEX)),) 119ifeq ($(call get-executable,$(FLEX)),)
@@ -233,6 +238,7 @@ ifdef NO_LIBELF
233 NO_DEMANGLE := 1 238 NO_DEMANGLE := 1
234 NO_LIBUNWIND := 1 239 NO_LIBUNWIND := 1
235 NO_LIBDW_DWARF_UNWIND := 1 240 NO_LIBDW_DWARF_UNWIND := 1
241 NO_LIBBPF := 1
236else 242else
237 ifeq ($(feature-libelf), 0) 243 ifeq ($(feature-libelf), 0)
238 ifeq ($(feature-glibc), 1) 244 ifeq ($(feature-glibc), 1)
@@ -242,13 +248,14 @@ else
242 LIBC_SUPPORT := 1 248 LIBC_SUPPORT := 1
243 endif 249 endif
244 ifeq ($(LIBC_SUPPORT),1) 250 ifeq ($(LIBC_SUPPORT),1)
245 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev); 251 msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install elfutils-libelf-devel/libelf-dev);
246 252
247 NO_LIBELF := 1 253 NO_LIBELF := 1
248 NO_DWARF := 1 254 NO_DWARF := 1
249 NO_DEMANGLE := 1 255 NO_DEMANGLE := 1
250 NO_LIBUNWIND := 1 256 NO_LIBUNWIND := 1
251 NO_LIBDW_DWARF_UNWIND := 1 257 NO_LIBDW_DWARF_UNWIND := 1
258 NO_LIBBPF := 1
252 else 259 else
253 ifneq ($(filter s% -static%,$(LDFLAGS),),) 260 ifneq ($(filter s% -static%,$(LDFLAGS),),)
254 msg := $(error No static glibc found, please install glibc-static); 261 msg := $(error No static glibc found, please install glibc-static);
@@ -305,6 +312,13 @@ ifndef NO_LIBELF
305 $(call detected,CONFIG_DWARF) 312 $(call detected,CONFIG_DWARF)
306 endif # PERF_HAVE_DWARF_REGS 313 endif # PERF_HAVE_DWARF_REGS
307 endif # NO_DWARF 314 endif # NO_DWARF
315
316 ifndef NO_LIBBPF
317 ifeq ($(feature-bpf), 1)
318 CFLAGS += -DHAVE_LIBBPF_SUPPORT
319 $(call detected,CONFIG_LIBBPF)
320 endif
321 endif # NO_LIBBPF
308endif # NO_LIBELF 322endif # NO_LIBELF
309 323
310ifeq ($(ARCH),powerpc) 324ifeq ($(ARCH),powerpc)
@@ -320,6 +334,13 @@ ifndef NO_LIBUNWIND
320 endif 334 endif
321endif 335endif
322 336
337ifndef NO_LIBBPF
338 ifneq ($(feature-bpf), 1)
339 msg := $(warning BPF API too old. Please install recent kernel headers. BPF support in 'perf record' is disabled.)
340 NO_LIBBPF := 1
341 endif
342endif
343
323dwarf-post-unwind := 1 344dwarf-post-unwind := 1
324dwarf-post-unwind-text := BUG 345dwarf-post-unwind-text := BUG
325 346
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 07dbff5c0e60..3d4c7c09adea 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -8,14 +8,16 @@
8 */ 8 */
9#include "builtin.h" 9#include "builtin.h"
10 10
11#include "util/env.h"
11#include "util/exec_cmd.h" 12#include "util/exec_cmd.h"
12#include "util/cache.h" 13#include "util/cache.h"
13#include "util/quote.h" 14#include "util/quote.h"
14#include "util/run-command.h" 15#include "util/run-command.h"
15#include "util/parse-events.h" 16#include "util/parse-events.h"
16#include "util/parse-options.h" 17#include "util/parse-options.h"
18#include "util/bpf-loader.h"
17#include "util/debug.h" 19#include "util/debug.h"
18#include <api/fs/debugfs.h> 20#include <api/fs/tracing_path.h>
19#include <pthread.h> 21#include <pthread.h>
20 22
21const char perf_usage_string[] = 23const char perf_usage_string[] =
@@ -161,6 +163,20 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
161 break; 163 break;
162 164
163 /* 165 /*
166 * Shortcut for '-h' and '-v' options to invoke help
167 * and version command.
168 */
169 if (!strcmp(cmd, "-h")) {
170 (*argv)[0] = "--help";
171 break;
172 }
173
174 if (!strcmp(cmd, "-v")) {
175 (*argv)[0] = "--version";
176 break;
177 }
178
179 /*
164 * Check remaining flags. 180 * Check remaining flags.
165 */ 181 */
166 if (!prefixcmp(cmd, CMD_EXEC_PATH)) { 182 if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
@@ -214,7 +230,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
214 fprintf(stderr, "No directory given for --debugfs-dir.\n"); 230 fprintf(stderr, "No directory given for --debugfs-dir.\n");
215 usage(perf_usage_string); 231 usage(perf_usage_string);
216 } 232 }
217 perf_debugfs_set_path((*argv)[1]); 233 tracing_path_set((*argv)[1]);
218 if (envchanged) 234 if (envchanged)
219 *envchanged = 1; 235 *envchanged = 1;
220 (*argv)++; 236 (*argv)++;
@@ -230,7 +246,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
230 (*argv)++; 246 (*argv)++;
231 (*argc)--; 247 (*argc)--;
232 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { 248 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
233 perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR)); 249 tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
234 fprintf(stderr, "dir: %s\n", tracing_path); 250 fprintf(stderr, "dir: %s\n", tracing_path);
235 if (envchanged) 251 if (envchanged)
236 *envchanged = 1; 252 *envchanged = 1;
@@ -369,6 +385,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
369 385
370 status = p->fn(argc, argv, prefix); 386 status = p->fn(argc, argv, prefix);
371 exit_browser(status); 387 exit_browser(status);
388 perf_env__exit(&perf_env);
389 bpf__clear();
372 390
373 if (status) 391 if (status)
374 return status & 0xff; 392 return status & 0xff;
@@ -517,8 +535,10 @@ int main(int argc, const char **argv)
517 cmd = perf_extract_argv0_path(argv[0]); 535 cmd = perf_extract_argv0_path(argv[0]);
518 if (!cmd) 536 if (!cmd)
519 cmd = "perf-help"; 537 cmd = "perf-help";
520 /* get debugfs mount point from /proc/mounts */ 538
521 perf_debugfs_mount(NULL); 539 /* get debugfs/tracefs mount point from /proc/mounts */
540 tracing_path_mount();
541
522 /* 542 /*
523 * "perf-xxxx" is the same as "perf xxxx", but we obviously: 543 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
524 * 544 *
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
index b9d508336ae6..c235c22b107a 100755
--- a/tools/perf/python/twatch.py
+++ b/tools/perf/python/twatch.py
@@ -15,14 +15,14 @@
15 15
16import perf 16import perf
17 17
18def main(): 18def main(context_switch = 0, thread = -1):
19 cpus = perf.cpu_map() 19 cpus = perf.cpu_map()
20 threads = perf.thread_map() 20 threads = perf.thread_map(thread)
21 evsel = perf.evsel(type = perf.TYPE_SOFTWARE, 21 evsel = perf.evsel(type = perf.TYPE_SOFTWARE,
22 config = perf.COUNT_SW_DUMMY, 22 config = perf.COUNT_SW_DUMMY,
23 task = 1, comm = 1, mmap = 0, freq = 0, 23 task = 1, comm = 1, mmap = 0, freq = 0,
24 wakeup_events = 1, watermark = 1, 24 wakeup_events = 1, watermark = 1,
25 sample_id_all = 1, 25 sample_id_all = 1, context_switch = context_switch,
26 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU) 26 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU)
27 27
28 """What we want are just the PERF_RECORD_ lifetime events for threads, 28 """What we want are just the PERF_RECORD_ lifetime events for threads,
@@ -48,4 +48,21 @@ def main():
48 print event 48 print event
49 49
50if __name__ == '__main__': 50if __name__ == '__main__':
51 """
52 To test the PERF_RECORD_SWITCH record, pick a pid and replace
53 in the following line.
54
55 Example output:
56
57cpu: 3, pid: 31463, tid: 31593 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31593, switch_out: 1 }
58cpu: 1, pid: 31463, tid: 31489 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31489, switch_out: 1 }
59cpu: 2, pid: 31463, tid: 31496 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31496, switch_out: 1 }
60cpu: 3, pid: 31463, tid: 31491 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31491, switch_out: 0 }
61
62 It is possible as well to use event.misc & perf.PERF_RECORD_MISC_SWITCH_OUT
63 to figure out if this is a context switch in or out of the monitored threads.
64
65 If bored, please add command line option parsing support for these options :-)
66 """
67 # main(context_switch = 1, thread = 31463)
51 main() 68 main()
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 84a32037a80f..1b02cdc0cab6 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -61,6 +61,142 @@ import datetime
61# 61#
62# An example of using the database is provided by the script 62# An example of using the database is provided by the script
63# call-graph-from-postgresql.py. Refer to that script for details. 63# call-graph-from-postgresql.py. Refer to that script for details.
64#
65# Tables:
66#
67# The tables largely correspond to perf tools' data structures. They are largely self-explanatory.
68#
69# samples
70#
71# 'samples' is the main table. It represents what instruction was executing at a point in time
72# when something (a selected event) happened. The memory address is the instruction pointer or 'ip'.
73#
74# calls
75#
76# 'calls' represents function calls and is related to 'samples' by 'call_id' and 'return_id'.
77# 'calls' is only created when the 'calls' option to this script is specified.
78#
79# call_paths
80#
81# 'call_paths' represents all the call stacks. Each 'call' has an associated record in 'call_paths'.
82# 'calls_paths' is only created when the 'calls' option to this script is specified.
83#
84# branch_types
85#
86# 'branch_types' provides descriptions for each type of branch.
87#
88# comm_threads
89#
90# 'comm_threads' shows how 'comms' relates to 'threads'.
91#
92# comms
93#
94# 'comms' contains a record for each 'comm' - the name given to the executable that is running.
95#
96# dsos
97#
98# 'dsos' contains a record for each executable file or library.
99#
100# machines
101#
102# 'machines' can be used to distinguish virtual machines if virtualization is supported.
103#
104# selected_events
105#
106# 'selected_events' contains a record for each kind of event that has been sampled.
107#
108# symbols
109#
110# 'symbols' contains a record for each symbol. Only symbols that have samples are present.
111#
112# threads
113#
114# 'threads' contains a record for each thread.
115#
116# Views:
117#
118# Most of the tables have views for more friendly display. The views are:
119#
120# calls_view
121# call_paths_view
122# comm_threads_view
123# dsos_view
124# machines_view
125# samples_view
126# symbols_view
127# threads_view
128#
129# More examples of browsing the database with psql:
130# Note that some of the examples are not the most optimal SQL query.
131# Note that call information is only available if the script's 'calls' option has been used.
132#
133# Top 10 function calls (not aggregated by symbol):
134#
135# SELECT * FROM calls_view ORDER BY elapsed_time DESC LIMIT 10;
136#
137# Top 10 function calls (aggregated by symbol):
138#
139# SELECT symbol_id,(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,
140# SUM(elapsed_time) AS tot_elapsed_time,SUM(branch_count) AS tot_branch_count
141# FROM calls_view GROUP BY symbol_id ORDER BY tot_elapsed_time DESC LIMIT 10;
142#
143# Note that the branch count gives a rough estimation of cpu usage, so functions
144# that took a long time but have a relatively low branch count must have spent time
145# waiting.
146#
147# Find symbols by pattern matching on part of the name (e.g. names containing 'alloc'):
148#
149# SELECT * FROM symbols_view WHERE name LIKE '%alloc%';
150#
151# Top 10 function calls for a specific symbol (e.g. whose symbol_id is 187):
152#
153# SELECT * FROM calls_view WHERE symbol_id = 187 ORDER BY elapsed_time DESC LIMIT 10;
154#
155# Show function calls made by function in the same context (i.e. same call path) (e.g. one with call_path_id 254):
156#
157# SELECT * FROM calls_view WHERE parent_call_path_id = 254;
158#
159# Show branches made during a function call (e.g. where call_id is 29357 and return_id is 29370 and tid is 29670)
160#
161# SELECT * FROM samples_view WHERE id >= 29357 AND id <= 29370 AND tid = 29670 AND event LIKE 'branches%';
162#
163# Show transactions:
164#
165# SELECT * FROM samples_view WHERE event = 'transactions';
166#
167# Note transaction start has 'in_tx' true whereas, transaction end has 'in_tx' false.
168# Transaction aborts have branch_type_name 'transaction abort'
169#
170# Show transaction aborts:
171#
172# SELECT * FROM samples_view WHERE event = 'transactions' AND branch_type_name = 'transaction abort';
173#
174# To print a call stack requires walking the call_paths table. For example this python script:
175# #!/usr/bin/python2
176#
177# import sys
178# from PySide.QtSql import *
179#
180# if __name__ == '__main__':
181# if (len(sys.argv) < 3):
182# print >> sys.stderr, "Usage is: printcallstack.py <database name> <call_path_id>"
183# raise Exception("Too few arguments")
184# dbname = sys.argv[1]
185# call_path_id = sys.argv[2]
186# db = QSqlDatabase.addDatabase('QPSQL')
187# db.setDatabaseName(dbname)
188# if not db.open():
189# raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
190# query = QSqlQuery(db)
191# print " id ip symbol_id symbol dso_id dso_short_name"
192# while call_path_id != 0 and call_path_id != 1:
193# ret = query.exec_('SELECT * FROM call_paths_view WHERE id = ' + str(call_path_id))
194# if not ret:
195# raise Exception("Query failed: " + query.lastError().text())
196# if not query.next():
197# raise Exception("Query failed")
198# print "{0:>6} {1:>10} {2:>9} {3:<30} {4:>6} {5:<30}".format(query.value(0), query.value(1), query.value(2), query.value(3), query.value(4), query.value(5))
199# call_path_id = query.value(6)
64 200
65from PySide.QtSql import * 201from PySide.QtSql import *
66 202
@@ -244,6 +380,91 @@ if perf_db_export_calls:
244 'parent_call_path_id bigint,' 380 'parent_call_path_id bigint,'
245 'flags integer)') 381 'flags integer)')
246 382
383do_query(query, 'CREATE VIEW machines_view AS '
384 'SELECT '
385 'id,'
386 'pid,'
387 'root_dir,'
388 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
389 ' FROM machines')
390
391do_query(query, 'CREATE VIEW dsos_view AS '
392 'SELECT '
393 'id,'
394 'machine_id,'
395 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
396 'short_name,'
397 'long_name,'
398 'build_id'
399 ' FROM dsos')
400
401do_query(query, 'CREATE VIEW symbols_view AS '
402 'SELECT '
403 'id,'
404 'name,'
405 '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
406 'dso_id,'
407 'sym_start,'
408 'sym_end,'
409 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
410 ' FROM symbols')
411
412do_query(query, 'CREATE VIEW threads_view AS '
413 'SELECT '
414 'id,'
415 'machine_id,'
416 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
417 'process_id,'
418 'pid,'
419 'tid'
420 ' FROM threads')
421
422do_query(query, 'CREATE VIEW comm_threads_view AS '
423 'SELECT '
424 'comm_id,'
425 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
426 'thread_id,'
427 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
428 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
429 ' FROM comm_threads')
430
431if perf_db_export_calls:
432 do_query(query, 'CREATE VIEW call_paths_view AS '
433 'SELECT '
434 'c.id,'
435 'to_hex(c.ip) AS ip,'
436 'c.symbol_id,'
437 '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
438 '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
439 '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'
440 'c.parent_id,'
441 'to_hex(p.ip) AS parent_ip,'
442 'p.symbol_id AS parent_symbol_id,'
443 '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
444 '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
445 '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
446 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
447 do_query(query, 'CREATE VIEW calls_view AS '
448 'SELECT '
449 'calls.id,'
450 'thread_id,'
451 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
452 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
453 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
454 'call_path_id,'
455 'to_hex(ip) AS ip,'
456 'symbol_id,'
457 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
458 'call_time,'
459 'return_time,'
460 'return_time - call_time AS elapsed_time,'
461 'branch_count,'
462 'call_id,'
463 'return_id,'
464 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,'
465 'parent_call_path_id'
466 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
467
247do_query(query, 'CREATE VIEW samples_view AS ' 468do_query(query, 'CREATE VIEW samples_view AS '
248 'SELECT ' 469 'SELECT '
249 'id,' 470 'id,'
diff --git a/tools/perf/tests/.gitignore b/tools/perf/tests/.gitignore
new file mode 100644
index 000000000000..489fc9ffbcb0
--- /dev/null
+++ b/tools/perf/tests/.gitignore
@@ -0,0 +1,2 @@
1llvm-src-base.c
2llvm-src-kbuild.c
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index c1518bdd0f1b..f41ebf8849fe 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -8,7 +8,6 @@ perf-y += openat-syscall-all-cpus.o
8perf-y += openat-syscall-tp-fields.o 8perf-y += openat-syscall-tp-fields.o
9perf-y += mmap-basic.o 9perf-y += mmap-basic.o
10perf-y += perf-record.o 10perf-y += perf-record.o
11perf-y += rdpmc.o
12perf-y += evsel-roundtrip-name.o 11perf-y += evsel-roundtrip-name.o
13perf-y += evsel-tp-sched.o 12perf-y += evsel-tp-sched.o
14perf-y += fdarray.o 13perf-y += fdarray.o
@@ -32,9 +31,23 @@ perf-y += sample-parsing.o
32perf-y += parse-no-sample-id-all.o 31perf-y += parse-no-sample-id-all.o
33perf-y += kmod-path.o 32perf-y += kmod-path.o
34perf-y += thread-map.o 33perf-y += thread-map.o
35perf-y += llvm.o 34perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o
35perf-y += bpf.o
36perf-y += topology.o
36 37
37perf-$(CONFIG_X86) += perf-time-to-tsc.o 38$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c
39 $(call rule_mkdir)
40 $(Q)echo '#include <tests/llvm.h>' > $@
41 $(Q)echo 'const char test_llvm__bpf_base_prog[] =' >> $@
42 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
43 $(Q)echo ';' >> $@
44
45$(OUTPUT)tests/llvm-src-kbuild.c: tests/bpf-script-test-kbuild.c
46 $(call rule_mkdir)
47 $(Q)echo '#include <tests/llvm.h>' > $@
48 $(Q)echo 'const char test_llvm__bpf_test_kbuild_prog[] =' >> $@
49 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
50 $(Q)echo ';' >> $@
38 51
39ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) 52ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
40perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o 53perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 2dfc9ad0e6f2..638875a0960a 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -171,6 +171,5 @@ int test__attr(void)
171 !lstat(path_perf, &st)) 171 !lstat(path_perf, &st))
172 return run_dir(path_dir, path_perf); 172 return run_dir(path_dir, path_perf);
173 173
174 fprintf(stderr, " (omitted)"); 174 return TEST_SKIP;
175 return 0;
176} 175}
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
new file mode 100644
index 000000000000..0ec9c2c03164
--- /dev/null
+++ b/tools/perf/tests/bpf-script-example.c
@@ -0,0 +1,48 @@
1/*
2 * bpf-script-example.c
3 * Test basic LLVM building
4 */
5#ifndef LINUX_VERSION_CODE
6# error Need LINUX_VERSION_CODE
7# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
8#endif
9#define BPF_ANY 0
10#define BPF_MAP_TYPE_ARRAY 2
11#define BPF_FUNC_map_lookup_elem 1
12#define BPF_FUNC_map_update_elem 2
13
14static void *(*bpf_map_lookup_elem)(void *map, void *key) =
15 (void *) BPF_FUNC_map_lookup_elem;
16static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
17 (void *) BPF_FUNC_map_update_elem;
18
19struct bpf_map_def {
20 unsigned int type;
21 unsigned int key_size;
22 unsigned int value_size;
23 unsigned int max_entries;
24};
25
26#define SEC(NAME) __attribute__((section(NAME), used))
27struct bpf_map_def SEC("maps") flip_table = {
28 .type = BPF_MAP_TYPE_ARRAY,
29 .key_size = sizeof(int),
30 .value_size = sizeof(int),
31 .max_entries = 1,
32};
33
34SEC("func=sys_epoll_pwait")
35int bpf_func__sys_epoll_pwait(void *ctx)
36{
37 int ind =0;
38 int *flag = bpf_map_lookup_elem(&flip_table, &ind);
39 int new_flag;
40 if (!flag)
41 return 0;
42 /* flip flag and store back */
43 new_flag = !*flag;
44 bpf_map_update_elem(&flip_table, &ind, &new_flag, BPF_ANY);
45 return new_flag;
46}
47char _license[] SEC("license") = "GPL";
48int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/tests/bpf-script-test-kbuild.c b/tools/perf/tests/bpf-script-test-kbuild.c
new file mode 100644
index 000000000000..3626924740d8
--- /dev/null
+++ b/tools/perf/tests/bpf-script-test-kbuild.c
@@ -0,0 +1,21 @@
1/*
2 * bpf-script-test-kbuild.c
3 * Test include from kernel header
4 */
5#ifndef LINUX_VERSION_CODE
6# error Need LINUX_VERSION_CODE
7# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
8#endif
9#define SEC(NAME) __attribute__((section(NAME), used))
10
11#include <uapi/linux/fs.h>
12#include <uapi/asm/ptrace.h>
13
14SEC("func=vfs_llseek")
15int bpf_func__vfs_llseek(void *ctx)
16{
17 return 0;
18}
19
20char _license[] SEC("license") = "GPL";
21int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
new file mode 100644
index 000000000000..ec16f7812c8b
--- /dev/null
+++ b/tools/perf/tests/bpf.c
@@ -0,0 +1,209 @@
1#include <stdio.h>
2#include <sys/epoll.h>
3#include <util/bpf-loader.h>
4#include <util/evlist.h>
5#include "tests.h"
6#include "llvm.h"
7#include "debug.h"
8#define NR_ITERS 111
9
10#ifdef HAVE_LIBBPF_SUPPORT
11
12static int epoll_pwait_loop(void)
13{
14 int i;
15
16 /* Should fail NR_ITERS times */
17 for (i = 0; i < NR_ITERS; i++)
18 epoll_pwait(-(i + 1), NULL, 0, 0, NULL);
19 return 0;
20}
21
22static struct {
23 enum test_llvm__testcase prog_id;
24 const char *desc;
25 const char *name;
26 const char *msg_compile_fail;
27 const char *msg_load_fail;
28 int (*target_func)(void);
29 int expect_result;
30} bpf_testcase_table[] = {
31 {
32 LLVM_TESTCASE_BASE,
33 "Test basic BPF filtering",
34 "[basic_bpf_test]",
35 "fix 'perf test LLVM' first",
36 "load bpf object failed",
37 &epoll_pwait_loop,
38 (NR_ITERS + 1) / 2,
39 },
40};
41
42static int do_test(struct bpf_object *obj, int (*func)(void),
43 int expect)
44{
45 struct record_opts opts = {
46 .target = {
47 .uid = UINT_MAX,
48 .uses_mmap = true,
49 },
50 .freq = 0,
51 .mmap_pages = 256,
52 .default_interval = 1,
53 };
54
55 char pid[16];
56 char sbuf[STRERR_BUFSIZE];
57 struct perf_evlist *evlist;
58 int i, ret = TEST_FAIL, err = 0, count = 0;
59
60 struct parse_events_evlist parse_evlist;
61 struct parse_events_error parse_error;
62
63 bzero(&parse_error, sizeof(parse_error));
64 bzero(&parse_evlist, sizeof(parse_evlist));
65 parse_evlist.error = &parse_error;
66 INIT_LIST_HEAD(&parse_evlist.list);
67
68 err = parse_events_load_bpf_obj(&parse_evlist, &parse_evlist.list, obj);
69 if (err || list_empty(&parse_evlist.list)) {
70 pr_debug("Failed to add events selected by BPF\n");
71 if (!err)
72 return TEST_FAIL;
73 }
74
75 snprintf(pid, sizeof(pid), "%d", getpid());
76 pid[sizeof(pid) - 1] = '\0';
77 opts.target.tid = opts.target.pid = pid;
78
79 /* Instead of perf_evlist__new_default, don't add default events */
80 evlist = perf_evlist__new();
81 if (!evlist) {
82 pr_debug("No ehough memory to create evlist\n");
83 return TEST_FAIL;
84 }
85
86 err = perf_evlist__create_maps(evlist, &opts.target);
87 if (err < 0) {
88 pr_debug("Not enough memory to create thread/cpu maps\n");
89 goto out_delete_evlist;
90 }
91
92 perf_evlist__splice_list_tail(evlist, &parse_evlist.list);
93 evlist->nr_groups = parse_evlist.nr_groups;
94
95 perf_evlist__config(evlist, &opts);
96
97 err = perf_evlist__open(evlist);
98 if (err < 0) {
99 pr_debug("perf_evlist__open: %s\n",
100 strerror_r(errno, sbuf, sizeof(sbuf)));
101 goto out_delete_evlist;
102 }
103
104 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
105 if (err < 0) {
106 pr_debug("perf_evlist__mmap: %s\n",
107 strerror_r(errno, sbuf, sizeof(sbuf)));
108 goto out_delete_evlist;
109 }
110
111 perf_evlist__enable(evlist);
112 (*func)();
113 perf_evlist__disable(evlist);
114
115 for (i = 0; i < evlist->nr_mmaps; i++) {
116 union perf_event *event;
117
118 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
119 const u32 type = event->header.type;
120
121 if (type == PERF_RECORD_SAMPLE)
122 count ++;
123 }
124 }
125
126 if (count != expect)
127 pr_debug("BPF filter result incorrect\n");
128
129 ret = TEST_OK;
130
131out_delete_evlist:
132 perf_evlist__delete(evlist);
133 return ret;
134}
135
136static struct bpf_object *
137prepare_bpf(void *obj_buf, size_t obj_buf_sz, const char *name)
138{
139 struct bpf_object *obj;
140
141 obj = bpf__prepare_load_buffer(obj_buf, obj_buf_sz, name);
142 if (IS_ERR(obj)) {
143 pr_debug("Compile BPF program failed.\n");
144 return NULL;
145 }
146 return obj;
147}
148
149static int __test__bpf(int index)
150{
151 int ret;
152 void *obj_buf;
153 size_t obj_buf_sz;
154 struct bpf_object *obj;
155
156 ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
157 bpf_testcase_table[index].prog_id,
158 true);
159 if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
160 pr_debug("Unable to get BPF object, %s\n",
161 bpf_testcase_table[index].msg_compile_fail);
162 if (index == 0)
163 return TEST_SKIP;
164 else
165 return TEST_FAIL;
166 }
167
168 obj = prepare_bpf(obj_buf, obj_buf_sz,
169 bpf_testcase_table[index].name);
170 if (!obj) {
171 ret = TEST_FAIL;
172 goto out;
173 }
174
175 ret = do_test(obj,
176 bpf_testcase_table[index].target_func,
177 bpf_testcase_table[index].expect_result);
178out:
179 bpf__clear();
180 return ret;
181}
182
183int test__bpf(void)
184{
185 unsigned int i;
186 int err;
187
188 if (geteuid() != 0) {
189 pr_debug("Only root can run BPF test\n");
190 return TEST_SKIP;
191 }
192
193 for (i = 0; i < ARRAY_SIZE(bpf_testcase_table); i++) {
194 err = __test__bpf(i);
195
196 if (err != TEST_OK)
197 return err;
198 }
199
200 return TEST_OK;
201}
202
203#else
204int test__bpf(void)
205{
206 pr_debug("Skip BPF test because BPF support is not compiled\n");
207 return TEST_SKIP;
208}
209#endif
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 136cd934be66..80c442eab767 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -14,10 +14,13 @@
14#include "parse-options.h" 14#include "parse-options.h"
15#include "symbol.h" 15#include "symbol.h"
16 16
17static struct test { 17struct test __weak arch_tests[] = {
18 const char *desc; 18 {
19 int (*func)(void); 19 .func = NULL,
20} tests[] = { 20 },
21};
22
23static struct test generic_tests[] = {
21 { 24 {
22 .desc = "vmlinux symtab matches kallsyms", 25 .desc = "vmlinux symtab matches kallsyms",
23 .func = test__vmlinux_matches_kallsyms, 26 .func = test__vmlinux_matches_kallsyms,
@@ -38,12 +41,6 @@ static struct test {
38 .desc = "parse events tests", 41 .desc = "parse events tests",
39 .func = test__parse_events, 42 .func = test__parse_events,
40 }, 43 },
41#if defined(__x86_64__) || defined(__i386__)
42 {
43 .desc = "x86 rdpmc test",
44 .func = test__rdpmc,
45 },
46#endif
47 { 44 {
48 .desc = "Validate PERF_RECORD_* events & perf_sample fields", 45 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
49 .func = test__PERF_RECORD, 46 .func = test__PERF_RECORD,
@@ -104,12 +101,6 @@ static struct test {
104 .desc = "Test software clock events have valid period values", 101 .desc = "Test software clock events have valid period values",
105 .func = test__sw_clock_freq, 102 .func = test__sw_clock_freq,
106 }, 103 },
107#if defined(__x86_64__) || defined(__i386__)
108 {
109 .desc = "Test converting perf time to TSC",
110 .func = test__perf_time_to_tsc,
111 },
112#endif
113 { 104 {
114 .desc = "Test object code reading", 105 .desc = "Test object code reading",
115 .func = test__code_reading, 106 .func = test__code_reading,
@@ -126,14 +117,6 @@ static struct test {
126 .desc = "Test parsing with no sample_id_all bit set", 117 .desc = "Test parsing with no sample_id_all bit set",
127 .func = test__parse_no_sample_id_all, 118 .func = test__parse_no_sample_id_all,
128 }, 119 },
129#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
130#ifdef HAVE_DWARF_UNWIND_SUPPORT
131 {
132 .desc = "Test dwarf unwind",
133 .func = test__dwarf_unwind,
134 },
135#endif
136#endif
137 { 120 {
138 .desc = "Test filtering hist entries", 121 .desc = "Test filtering hist entries",
139 .func = test__hists_filter, 122 .func = test__hists_filter,
@@ -179,11 +162,24 @@ static struct test {
179 .func = test__llvm, 162 .func = test__llvm,
180 }, 163 },
181 { 164 {
165 .desc = "Test topology in session",
166 .func = test_session_topology,
167 },
168 {
169 .desc = "Test BPF filter",
170 .func = test__bpf,
171 },
172 {
182 .func = NULL, 173 .func = NULL,
183 }, 174 },
184}; 175};
185 176
186static bool perf_test__matches(int curr, int argc, const char *argv[]) 177static struct test *tests[] = {
178 generic_tests,
179 arch_tests,
180};
181
182static bool perf_test__matches(struct test *test, int curr, int argc, const char *argv[])
187{ 183{
188 int i; 184 int i;
189 185
@@ -200,7 +196,7 @@ static bool perf_test__matches(int curr, int argc, const char *argv[])
200 continue; 196 continue;
201 } 197 }
202 198
203 if (strstr(tests[curr].desc, argv[i])) 199 if (strcasestr(test->desc, argv[i]))
204 return true; 200 return true;
205 } 201 }
206 202
@@ -237,27 +233,31 @@ static int run_test(struct test *test)
237 return err; 233 return err;
238} 234}
239 235
236#define for_each_test(j, t) \
237 for (j = 0; j < ARRAY_SIZE(tests); j++) \
238 for (t = &tests[j][0]; t->func; t++)
239
240static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) 240static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
241{ 241{
242 struct test *t;
243 unsigned int j;
242 int i = 0; 244 int i = 0;
243 int width = 0; 245 int width = 0;
244 246
245 while (tests[i].func) { 247 for_each_test(j, t) {
246 int len = strlen(tests[i].desc); 248 int len = strlen(t->desc);
247 249
248 if (width < len) 250 if (width < len)
249 width = len; 251 width = len;
250 ++i;
251 } 252 }
252 253
253 i = 0; 254 for_each_test(j, t) {
254 while (tests[i].func) {
255 int curr = i++, err; 255 int curr = i++, err;
256 256
257 if (!perf_test__matches(curr, argc, argv)) 257 if (!perf_test__matches(t, curr, argc, argv))
258 continue; 258 continue;
259 259
260 pr_info("%2d: %-*s:", i, width, tests[curr].desc); 260 pr_info("%2d: %-*s:", i, width, t->desc);
261 261
262 if (intlist__find(skiplist, i)) { 262 if (intlist__find(skiplist, i)) {
263 color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); 263 color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
@@ -265,8 +265,8 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
265 } 265 }
266 266
267 pr_debug("\n--- start ---\n"); 267 pr_debug("\n--- start ---\n");
268 err = run_test(&tests[curr]); 268 err = run_test(t);
269 pr_debug("---- end ----\n%s:", tests[curr].desc); 269 pr_debug("---- end ----\n%s:", t->desc);
270 270
271 switch (err) { 271 switch (err) {
272 case TEST_OK: 272 case TEST_OK:
@@ -287,15 +287,15 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
287 287
288static int perf_test__list(int argc, const char **argv) 288static int perf_test__list(int argc, const char **argv)
289{ 289{
290 unsigned int j;
291 struct test *t;
290 int i = 0; 292 int i = 0;
291 293
292 while (tests[i].func) { 294 for_each_test(j, t) {
293 int curr = i++; 295 if (argc > 1 && !strstr(t->desc, argv[1]))
294
295 if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
296 continue; 296 continue;
297 297
298 pr_info("%2d: %s\n", i, tests[curr].desc); 298 pr_info("%2d: %s\n", ++i, t->desc);
299 } 299 }
300 300
301 return 0; 301 return 0;
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 39c784a100a9..a767a6400c5c 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -33,20 +33,20 @@ static unsigned int hex(char c)
33 return c - 'A' + 10; 33 return c - 'A' + 10;
34} 34}
35 35
36static void read_objdump_line(const char *line, size_t line_len, void **buf, 36static size_t read_objdump_line(const char *line, size_t line_len, void *buf,
37 size_t *len) 37 size_t len)
38{ 38{
39 const char *p; 39 const char *p;
40 size_t i; 40 size_t i, j = 0;
41 41
42 /* Skip to a colon */ 42 /* Skip to a colon */
43 p = strchr(line, ':'); 43 p = strchr(line, ':');
44 if (!p) 44 if (!p)
45 return; 45 return 0;
46 i = p + 1 - line; 46 i = p + 1 - line;
47 47
48 /* Read bytes */ 48 /* Read bytes */
49 while (*len) { 49 while (j < len) {
50 char c1, c2; 50 char c1, c2;
51 51
52 /* Skip spaces */ 52 /* Skip spaces */
@@ -65,20 +65,26 @@ static void read_objdump_line(const char *line, size_t line_len, void **buf,
65 if (i < line_len && line[i] && !isspace(line[i])) 65 if (i < line_len && line[i] && !isspace(line[i]))
66 break; 66 break;
67 /* Store byte */ 67 /* Store byte */
68 *(unsigned char *)*buf = (hex(c1) << 4) | hex(c2); 68 *(unsigned char *)buf = (hex(c1) << 4) | hex(c2);
69 *buf += 1; 69 buf += 1;
70 *len -= 1; 70 j++;
71 } 71 }
72 /* return number of successfully read bytes */
73 return j;
72} 74}
73 75
74static int read_objdump_output(FILE *f, void **buf, size_t *len) 76static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
75{ 77{
76 char *line = NULL; 78 char *line = NULL;
77 size_t line_len; 79 size_t line_len, off_last = 0;
78 ssize_t ret; 80 ssize_t ret;
79 int err = 0; 81 int err = 0;
82 u64 addr, last_addr = start_addr;
83
84 while (off_last < *len) {
85 size_t off, read_bytes, written_bytes;
86 unsigned char tmp[BUFSZ];
80 87
81 while (1) {
82 ret = getline(&line, &line_len, f); 88 ret = getline(&line, &line_len, f);
83 if (feof(f)) 89 if (feof(f))
84 break; 90 break;
@@ -87,9 +93,33 @@ static int read_objdump_output(FILE *f, void **buf, size_t *len)
87 err = -1; 93 err = -1;
88 break; 94 break;
89 } 95 }
90 read_objdump_line(line, ret, buf, len); 96
97 /* read objdump data into temporary buffer */
98 read_bytes = read_objdump_line(line, ret, tmp, sizeof(tmp));
99 if (!read_bytes)
100 continue;
101
102 if (sscanf(line, "%"PRIx64, &addr) != 1)
103 continue;
104 if (addr < last_addr) {
105 pr_debug("addr going backwards, read beyond section?\n");
106 break;
107 }
108 last_addr = addr;
109
110 /* copy it from temporary buffer to 'buf' according
111 * to address on current objdump line */
112 off = addr - start_addr;
113 if (off >= *len)
114 break;
115 written_bytes = MIN(read_bytes, *len - off);
116 memcpy(buf + off, tmp, written_bytes);
117 off_last = off + written_bytes;
91 } 118 }
92 119
120 /* len returns number of bytes that could not be read */
121 *len -= off_last;
122
93 free(line); 123 free(line);
94 124
95 return err; 125 return err;
@@ -103,7 +133,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
103 FILE *f; 133 FILE *f;
104 int ret; 134 int ret;
105 135
106 fmt = "%s -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s"; 136 fmt = "%s -z -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s";
107 ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len, 137 ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len,
108 filename); 138 filename);
109 if (ret <= 0 || (size_t)ret >= sizeof(cmd)) 139 if (ret <= 0 || (size_t)ret >= sizeof(cmd))
@@ -120,7 +150,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
120 return -1; 150 return -1;
121 } 151 }
122 152
123 ret = read_objdump_output(f, &buf, &len); 153 ret = read_objdump_output(f, buf, &len, addr);
124 if (len) { 154 if (len) {
125 pr_debug("objdump read too few bytes\n"); 155 pr_debug("objdump read too few bytes\n");
126 if (!ret) 156 if (!ret)
@@ -132,6 +162,18 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
132 return ret; 162 return ret;
133} 163}
134 164
165static void dump_buf(unsigned char *buf, size_t len)
166{
167 size_t i;
168
169 for (i = 0; i < len; i++) {
170 pr_debug("0x%02x ", buf[i]);
171 if (i % 16 == 15)
172 pr_debug("\n");
173 }
174 pr_debug("\n");
175}
176
135static int read_object_code(u64 addr, size_t len, u8 cpumode, 177static int read_object_code(u64 addr, size_t len, u8 cpumode,
136 struct thread *thread, struct state *state) 178 struct thread *thread, struct state *state)
137{ 179{
@@ -234,6 +276,10 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
234 /* The results should be identical */ 276 /* The results should be identical */
235 if (memcmp(buf1, buf2, len)) { 277 if (memcmp(buf1, buf2, len)) {
236 pr_debug("Bytes read differ from those read by objdump\n"); 278 pr_debug("Bytes read differ from those read by objdump\n");
279 pr_debug("buf1 (dso):\n");
280 dump_buf(buf1, len);
281 pr_debug("buf2 (objdump):\n");
282 dump_buf(buf2, len);
237 return -1; 283 return -1;
238 } 284 }
239 pr_debug("Bytes read match those read by objdump\n"); 285 pr_debug("Bytes read match those read by objdump\n");
@@ -427,7 +473,7 @@ static int do_test_code_reading(bool try_kcore)
427 symbol_conf.kallsyms_name = "/proc/kallsyms"; 473 symbol_conf.kallsyms_name = "/proc/kallsyms";
428 474
429 /* Load kernel map */ 475 /* Load kernel map */
430 map = machine->vmlinux_maps[MAP__FUNCTION]; 476 map = machine__kernel_map(machine);
431 ret = map__load(map, NULL); 477 ret = map__load(map, NULL);
432 if (ret < 0) { 478 if (ret < 0) {
433 pr_debug("map__load failed\n"); 479 pr_debug("map__load failed\n");
@@ -567,16 +613,16 @@ int test__code_reading(void)
567 case TEST_CODE_READING_OK: 613 case TEST_CODE_READING_OK:
568 return 0; 614 return 0;
569 case TEST_CODE_READING_NO_VMLINUX: 615 case TEST_CODE_READING_NO_VMLINUX:
570 fprintf(stderr, " (no vmlinux)"); 616 pr_debug("no vmlinux\n");
571 return 0; 617 return 0;
572 case TEST_CODE_READING_NO_KCORE: 618 case TEST_CODE_READING_NO_KCORE:
573 fprintf(stderr, " (no kcore)"); 619 pr_debug("no kcore\n");
574 return 0; 620 return 0;
575 case TEST_CODE_READING_NO_ACCESS: 621 case TEST_CODE_READING_NO_ACCESS:
576 fprintf(stderr, " (no access)"); 622 pr_debug("no access\n");
577 return 0; 623 return 0;
578 case TEST_CODE_READING_NO_KERNEL_OBJ: 624 case TEST_CODE_READING_NO_KERNEL_OBJ:
579 fprintf(stderr, " (no kernel obj)"); 625 pr_debug("no kernel obj\n");
580 return 0; 626 return 0;
581 default: 627 default:
582 return -1; 628 return -1;
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 40b36c462427..07221793a3ac 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -11,6 +11,10 @@
11#include "thread.h" 11#include "thread.h"
12#include "callchain.h" 12#include "callchain.h"
13 13
14#if defined (__x86_64__) || defined (__i386__)
15#include "arch-tests.h"
16#endif
17
14/* For bsearch. We try to unwind functions in shared object. */ 18/* For bsearch. We try to unwind functions in shared object. */
15#include <stdlib.h> 19#include <stdlib.h>
16 20
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 52162425c969..790e413d9a1f 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -1,3 +1,4 @@
1#include <linux/err.h>
1#include <traceevent/event-parse.h> 2#include <traceevent/event-parse.h>
2#include "evsel.h" 3#include "evsel.h"
3#include "tests.h" 4#include "tests.h"
@@ -36,8 +37,8 @@ int test__perf_evsel__tp_sched_test(void)
36 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); 37 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch");
37 int ret = 0; 38 int ret = 0;
38 39
39 if (evsel == NULL) { 40 if (IS_ERR(evsel)) {
40 pr_debug("perf_evsel__new\n"); 41 pr_debug("perf_evsel__newtp failed with %ld\n", PTR_ERR(evsel));
41 return -1; 42 return -1;
42 } 43 }
43 44
@@ -66,6 +67,11 @@ int test__perf_evsel__tp_sched_test(void)
66 67
67 evsel = perf_evsel__newtp("sched", "sched_wakeup"); 68 evsel = perf_evsel__newtp("sched", "sched_wakeup");
68 69
70 if (IS_ERR(evsel)) {
71 pr_debug("perf_evsel__newtp failed with %ld\n", PTR_ERR(evsel));
72 return -1;
73 }
74
69 if (perf_evsel__test_field(evsel, "comm", 16, true)) 75 if (perf_evsel__test_field(evsel, "comm", 16, true))
70 ret = -1; 76 ret = -1;
71 77
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index ce48775e6ada..818acf875dd0 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -16,30 +16,31 @@ struct sample {
16 struct thread *thread; 16 struct thread *thread;
17 struct map *map; 17 struct map *map;
18 struct symbol *sym; 18 struct symbol *sym;
19 int socket;
19}; 20};
20 21
21/* For the numbers, see hists_common.c */ 22/* For the numbers, see hists_common.c */
22static struct sample fake_samples[] = { 23static struct sample fake_samples[] = {
23 /* perf [kernel] schedule() */ 24 /* perf [kernel] schedule() */
24 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, }, 25 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, .socket = 0 },
25 /* perf [perf] main() */ 26 /* perf [perf] main() */
26 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, }, 27 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, .socket = 0 },
27 /* perf [libc] malloc() */ 28 /* perf [libc] malloc() */
28 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, }, 29 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, .socket = 0 },
29 /* perf [perf] main() */ 30 /* perf [perf] main() */
30 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, }, /* will be merged */ 31 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, .socket = 0 }, /* will be merged */
31 /* perf [perf] cmd_record() */ 32 /* perf [perf] cmd_record() */
32 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, }, 33 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, .socket = 1 },
33 /* perf [kernel] page_fault() */ 34 /* perf [kernel] page_fault() */
34 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, 35 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 1 },
35 /* bash [bash] main() */ 36 /* bash [bash] main() */
36 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, }, 37 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, .socket = 2 },
37 /* bash [bash] xmalloc() */ 38 /* bash [bash] xmalloc() */
38 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, }, 39 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, .socket = 2 },
39 /* bash [libc] malloc() */ 40 /* bash [libc] malloc() */
40 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_LIBC_MALLOC, }, 41 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_LIBC_MALLOC, .socket = 3 },
41 /* bash [kernel] page_fault() */ 42 /* bash [kernel] page_fault() */
42 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, 43 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 3 },
43}; 44};
44 45
45static int add_hist_entries(struct perf_evlist *evlist, 46static int add_hist_entries(struct perf_evlist *evlist,
@@ -83,6 +84,7 @@ static int add_hist_entries(struct perf_evlist *evlist,
83 &sample) < 0) 84 &sample) < 0)
84 goto out; 85 goto out;
85 86
87 al.socket = fake_samples[i].socket;
86 if (hist_entry_iter__add(&iter, &al, 88 if (hist_entry_iter__add(&iter, &al,
87 PERF_MAX_STACK_DEPTH, NULL) < 0) { 89 PERF_MAX_STACK_DEPTH, NULL) < 0) {
88 addr_location__put(&al); 90 addr_location__put(&al);
@@ -253,6 +255,39 @@ int test__hists_filter(void)
253 TEST_ASSERT_VAL("Unmatched total period for symbol filter", 255 TEST_ASSERT_VAL("Unmatched total period for symbol filter",
254 hists->stats.total_non_filtered_period == 300); 256 hists->stats.total_non_filtered_period == 300);
255 257
258 /* remove symbol filter first */
259 hists->symbol_filter_str = NULL;
260 hists__filter_by_symbol(hists);
261
262 /* now applying socket filters */
263 hists->socket_filter = 2;
264 hists__filter_by_socket(hists);
265
266 if (verbose > 2) {
267 pr_info("Histogram for socket filters\n");
268 print_hists_out(hists);
269 }
270
271 /* normal stats should be invariant */
272 TEST_ASSERT_VAL("Invalid nr samples",
273 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
274 TEST_ASSERT_VAL("Invalid nr hist entries",
275 hists->nr_entries == 9);
276 TEST_ASSERT_VAL("Invalid total period",
277 hists->stats.total_period == 1000);
278
279 /* but filter stats are changed */
280 TEST_ASSERT_VAL("Unmatched nr samples for socket filter",
281 hists->stats.nr_non_filtered_samples == 2);
282 TEST_ASSERT_VAL("Unmatched nr hist entries for socket filter",
283 hists->nr_non_filtered_entries == 2);
284 TEST_ASSERT_VAL("Unmatched total period for socket filter",
285 hists->stats.total_non_filtered_period == 200);
286
287 /* remove socket filter first */
288 hists->socket_filter = -1;
289 hists__filter_by_socket(hists);
290
256 /* now applying all filters at once. */ 291 /* now applying all filters at once. */
257 hists->thread_filter = fake_samples[1].thread; 292 hists->thread_filter = fake_samples[1].thread;
258 hists->dso_filter = fake_samples[1].map->dso; 293 hists->dso_filter = fake_samples[1].map->dso;
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index 4d4b9837b630..a2e2269aa093 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -90,8 +90,8 @@ int test__keep_tracking(void)
90 evsel->attr.enable_on_exec = 0; 90 evsel->attr.enable_on_exec = 0;
91 91
92 if (perf_evlist__open(evlist) < 0) { 92 if (perf_evlist__open(evlist) < 0) {
93 fprintf(stderr, " (not supported)"); 93 pr_debug("Unable to open dummy and cycles event\n");
94 err = 0; 94 err = TEST_SKIP;
95 goto out_err; 95 goto out_err;
96 } 96 }
97 97
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index 52d55971f66f..bc4cf507cde5 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -2,6 +2,7 @@
2#include <bpf/libbpf.h> 2#include <bpf/libbpf.h>
3#include <util/llvm-utils.h> 3#include <util/llvm-utils.h>
4#include <util/cache.h> 4#include <util/cache.h>
5#include "llvm.h"
5#include "tests.h" 6#include "tests.h"
6#include "debug.h" 7#include "debug.h"
7 8
@@ -11,42 +12,58 @@ static int perf_config_cb(const char *var, const char *val,
11 return perf_default_config(var, val, arg); 12 return perf_default_config(var, val, arg);
12} 13}
13 14
14/*
15 * Randomly give it a "version" section since we don't really load it
16 * into kernel
17 */
18static const char test_bpf_prog[] =
19 "__attribute__((section(\"do_fork\"), used)) "
20 "int fork(void *ctx) {return 0;} "
21 "char _license[] __attribute__((section(\"license\"), used)) = \"GPL\";"
22 "int _version __attribute__((section(\"version\"), used)) = 0x40100;";
23
24#ifdef HAVE_LIBBPF_SUPPORT 15#ifdef HAVE_LIBBPF_SUPPORT
25static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) 16static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
26{ 17{
27 struct bpf_object *obj; 18 struct bpf_object *obj;
28 19
29 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL); 20 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
30 if (!obj) 21 if (IS_ERR(obj))
31 return -1; 22 return TEST_FAIL;
32 bpf_object__close(obj); 23 bpf_object__close(obj);
33 return 0; 24 return TEST_OK;
34} 25}
35#else 26#else
36static int test__bpf_parsing(void *obj_buf __maybe_unused, 27static int test__bpf_parsing(void *obj_buf __maybe_unused,
37 size_t obj_buf_sz __maybe_unused) 28 size_t obj_buf_sz __maybe_unused)
38{ 29{
39 fprintf(stderr, " (skip bpf parsing)"); 30 pr_debug("Skip bpf parsing\n");
40 return 0; 31 return TEST_OK;
41} 32}
42#endif 33#endif
43 34
44int test__llvm(void) 35static struct {
36 const char *source;
37 const char *desc;
38} bpf_source_table[__LLVM_TESTCASE_MAX] = {
39 [LLVM_TESTCASE_BASE] = {
40 .source = test_llvm__bpf_base_prog,
41 .desc = "Basic BPF llvm compiling test",
42 },
43 [LLVM_TESTCASE_KBUILD] = {
44 .source = test_llvm__bpf_test_kbuild_prog,
45 .desc = "Test kbuild searching",
46 },
47};
48
49
50int
51test_llvm__fetch_bpf_obj(void **p_obj_buf,
52 size_t *p_obj_buf_sz,
53 enum test_llvm__testcase index,
54 bool force)
45{ 55{
46 char *tmpl_new, *clang_opt_new; 56 const char *source;
47 void *obj_buf; 57 const char *desc;
48 size_t obj_buf_sz; 58 const char *tmpl_old, *clang_opt_old;
49 int err, old_verbose; 59 char *tmpl_new = NULL, *clang_opt_new = NULL;
60 int err, old_verbose, ret = TEST_FAIL;
61
62 if (index >= __LLVM_TESTCASE_MAX)
63 return TEST_FAIL;
64
65 source = bpf_source_table[index].source;
66 desc = bpf_source_table[index].desc;
50 67
51 perf_config(perf_config_cb, NULL); 68 perf_config(perf_config_cb, NULL);
52 69
@@ -54,45 +71,100 @@ int test__llvm(void)
54 * Skip this test if user's .perfconfig doesn't set [llvm] section 71 * Skip this test if user's .perfconfig doesn't set [llvm] section
55 * and clang is not found in $PATH, and this is not perf test -v 72 * and clang is not found in $PATH, and this is not perf test -v
56 */ 73 */
57 if (verbose == 0 && !llvm_param.user_set_param && llvm__search_clang()) { 74 if (!force && (verbose == 0 &&
58 fprintf(stderr, " (no clang, try 'perf test -v LLVM')"); 75 !llvm_param.user_set_param &&
76 llvm__search_clang())) {
77 pr_debug("No clang and no verbosive, skip this test\n");
59 return TEST_SKIP; 78 return TEST_SKIP;
60 } 79 }
61 80
62 old_verbose = verbose;
63 /* 81 /*
64 * llvm is verbosity when error. Suppress all error output if 82 * llvm is verbosity when error. Suppress all error output if
65 * not 'perf test -v'. 83 * not 'perf test -v'.
66 */ 84 */
85 old_verbose = verbose;
67 if (verbose == 0) 86 if (verbose == 0)
68 verbose = -1; 87 verbose = -1;
69 88
89 *p_obj_buf = NULL;
90 *p_obj_buf_sz = 0;
91
70 if (!llvm_param.clang_bpf_cmd_template) 92 if (!llvm_param.clang_bpf_cmd_template)
71 return -1; 93 goto out;
72 94
73 if (!llvm_param.clang_opt) 95 if (!llvm_param.clang_opt)
74 llvm_param.clang_opt = strdup(""); 96 llvm_param.clang_opt = strdup("");
75 97
76 err = asprintf(&tmpl_new, "echo '%s' | %s", test_bpf_prog, 98 err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
77 llvm_param.clang_bpf_cmd_template); 99 llvm_param.clang_bpf_cmd_template,
100 old_verbose ? "" : " 2>/dev/null");
78 if (err < 0) 101 if (err < 0)
79 return -1; 102 goto out;
80 err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt); 103 err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
81 if (err < 0) 104 if (err < 0)
82 return -1; 105 goto out;
83 106
107 tmpl_old = llvm_param.clang_bpf_cmd_template;
84 llvm_param.clang_bpf_cmd_template = tmpl_new; 108 llvm_param.clang_bpf_cmd_template = tmpl_new;
109 clang_opt_old = llvm_param.clang_opt;
85 llvm_param.clang_opt = clang_opt_new; 110 llvm_param.clang_opt = clang_opt_new;
86 err = llvm__compile_bpf("-", &obj_buf, &obj_buf_sz); 111
112 err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
113
114 llvm_param.clang_bpf_cmd_template = tmpl_old;
115 llvm_param.clang_opt = clang_opt_old;
87 116
88 verbose = old_verbose; 117 verbose = old_verbose;
89 if (err) { 118 if (err)
90 if (!verbose) 119 goto out;
91 fprintf(stderr, " (use -v to see error message)"); 120
92 return -1; 121 ret = TEST_OK;
93 } 122out:
123 free(tmpl_new);
124 free(clang_opt_new);
125 if (ret != TEST_OK)
126 pr_debug("Failed to compile test case: '%s'\n", desc);
127 return ret;
128}
129
130int test__llvm(void)
131{
132 enum test_llvm__testcase i;
133
134 for (i = 0; i < __LLVM_TESTCASE_MAX; i++) {
135 int ret;
136 void *obj_buf = NULL;
137 size_t obj_buf_sz = 0;
138
139 ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
140 i, false);
94 141
95 err = test__bpf_parsing(obj_buf, obj_buf_sz); 142 if (ret == TEST_OK) {
96 free(obj_buf); 143 ret = test__bpf_parsing(obj_buf, obj_buf_sz);
97 return err; 144 if (ret != TEST_OK)
145 pr_debug("Failed to parse test case '%s'\n",
146 bpf_source_table[i].desc);
147 }
148 free(obj_buf);
149
150 switch (ret) {
151 case TEST_SKIP:
152 return TEST_SKIP;
153 case TEST_OK:
154 break;
155 default:
156 /*
157 * Test 0 is the basic LLVM test. If test 0
158 * fail, the basic LLVM support not functional
159 * so the whole test should fail. If other test
160 * case fail, it can be fixed by adjusting
161 * config so don't report error.
162 */
163 if (i == 0)
164 return TEST_FAIL;
165 else
166 return TEST_SKIP;
167 }
168 }
169 return TEST_OK;
98} 170}
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
new file mode 100644
index 000000000000..d91d8f44efee
--- /dev/null
+++ b/tools/perf/tests/llvm.h
@@ -0,0 +1,18 @@
1#ifndef PERF_TEST_LLVM_H
2#define PERF_TEST_LLVM_H
3
4#include <stddef.h> /* for size_t */
5#include <stdbool.h> /* for bool */
6
7extern const char test_llvm__bpf_base_prog[];
8extern const char test_llvm__bpf_test_kbuild_prog[];
9
10enum test_llvm__testcase {
11 LLVM_TESTCASE_BASE,
12 LLVM_TESTCASE_KBUILD,
13 __LLVM_TESTCASE_MAX,
14};
15
16int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
17 enum test_llvm__testcase index, bool force);
18#endif
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index ba31c4bd441d..8ea3dffc5065 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -44,6 +44,7 @@ make_no_libnuma := NO_LIBNUMA=1
44make_no_libaudit := NO_LIBAUDIT=1 44make_no_libaudit := NO_LIBAUDIT=1
45make_no_libbionic := NO_LIBBIONIC=1 45make_no_libbionic := NO_LIBBIONIC=1
46make_no_auxtrace := NO_AUXTRACE=1 46make_no_auxtrace := NO_AUXTRACE=1
47make_no_libbpf := NO_LIBBPF=1
47make_tags := tags 48make_tags := tags
48make_cscope := cscope 49make_cscope := cscope
49make_help := help 50make_help := help
@@ -66,7 +67,7 @@ make_static := LDFLAGS=-static
66make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 67make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
67make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 68make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
68make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 69make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
69make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 70make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
70 71
71# $(run) contains all available tests 72# $(run) contains all available tests
72run := make_pure 73run := make_pure
@@ -94,6 +95,7 @@ run += make_no_libnuma
94run += make_no_libaudit 95run += make_no_libaudit
95run += make_no_libbionic 96run += make_no_libbionic
96run += make_no_auxtrace 97run += make_no_auxtrace
98run += make_no_libbpf
97run += make_help 99run += make_help
98run += make_doc 100run += make_doc
99run += make_perf_o 101run += make_perf_o
@@ -219,6 +221,11 @@ test_O = $(if $(test_$1),$(test_$1),$(test_default_O))
219 221
220all: 222all:
221 223
224ifdef SHUF
225run := $(shell shuf -e $(run))
226run_O := $(shell shuf -e $(run_O))
227endif
228
222ifdef DEBUG 229ifdef DEBUG
223d := $(info run $(run)) 230d := $(info run $(run))
224d := $(info run_O $(run_O)) 231d := $(info run_O $(run_O))
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 666b67a4df9d..4495493c9431 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -3,6 +3,7 @@
3#include "thread_map.h" 3#include "thread_map.h"
4#include "cpumap.h" 4#include "cpumap.h"
5#include "tests.h" 5#include "tests.h"
6#include <linux/err.h>
6 7
7/* 8/*
8 * This test will generate random numbers of calls to some getpid syscalls, 9 * This test will generate random numbers of calls to some getpid syscalls,
@@ -65,7 +66,7 @@ int test__basic_mmap(void)
65 66
66 snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); 67 snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
67 evsels[i] = perf_evsel__newtp("syscalls", name); 68 evsels[i] = perf_evsel__newtp("syscalls", name);
68 if (evsels[i] == NULL) { 69 if (IS_ERR(evsels[i])) {
69 pr_debug("perf_evsel__new\n"); 70 pr_debug("perf_evsel__new\n");
70 goto out_delete_evlist; 71 goto out_delete_evlist;
71 } 72 }
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index a572f87e9c8d..2006485a2859 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -1,3 +1,5 @@
1#include <api/fs/fs.h>
2#include <linux/err.h>
1#include "evsel.h" 3#include "evsel.h"
2#include "tests.h" 4#include "tests.h"
3#include "thread_map.h" 5#include "thread_map.h"
@@ -14,6 +16,7 @@ int test__openat_syscall_event_on_all_cpus(void)
14 cpu_set_t cpu_set; 16 cpu_set_t cpu_set;
15 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 17 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
16 char sbuf[STRERR_BUFSIZE]; 18 char sbuf[STRERR_BUFSIZE];
19 char errbuf[BUFSIZ];
17 20
18 if (threads == NULL) { 21 if (threads == NULL) {
19 pr_debug("thread_map__new\n"); 22 pr_debug("thread_map__new\n");
@@ -29,13 +32,9 @@ int test__openat_syscall_event_on_all_cpus(void)
29 CPU_ZERO(&cpu_set); 32 CPU_ZERO(&cpu_set);
30 33
31 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); 34 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
32 if (evsel == NULL) { 35 if (IS_ERR(evsel)) {
33 if (tracefs_configured()) 36 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
34 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n"); 37 pr_debug("%s\n", errbuf);
35 else if (debugfs_configured())
36 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
37 else
38 pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
39 goto out_thread_map_delete; 38 goto out_thread_map_delete;
40 } 39 }
41 40
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 01a19626c846..5e811cd8f1c3 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -1,3 +1,4 @@
1#include <linux/err.h>
1#include "perf.h" 2#include "perf.h"
2#include "evlist.h" 3#include "evlist.h"
3#include "evsel.h" 4#include "evsel.h"
@@ -30,7 +31,7 @@ int test__syscall_openat_tp_fields(void)
30 } 31 }
31 32
32 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); 33 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
33 if (evsel == NULL) { 34 if (IS_ERR(evsel)) {
34 pr_debug("%s: perf_evsel__newtp\n", __func__); 35 pr_debug("%s: perf_evsel__newtp\n", __func__);
35 goto out_delete_evlist; 36 goto out_delete_evlist;
36 } 37 }
@@ -88,7 +89,7 @@ int test__syscall_openat_tp_fields(void)
88 89
89 err = perf_evsel__parse_sample(evsel, event, &sample); 90 err = perf_evsel__parse_sample(evsel, event, &sample);
90 if (err) { 91 if (err) {
91 pr_err("Can't parse sample, err = %d\n", err); 92 pr_debug("Can't parse sample, err = %d\n", err);
92 goto out_delete_evlist; 93 goto out_delete_evlist;
93 } 94 }
94 95
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index c9a37bc6b33a..033b54797b8a 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -1,3 +1,5 @@
1#include <api/fs/tracing_path.h>
2#include <linux/err.h>
1#include "thread_map.h" 3#include "thread_map.h"
2#include "evsel.h" 4#include "evsel.h"
3#include "debug.h" 5#include "debug.h"
@@ -10,6 +12,7 @@ int test__openat_syscall_event(void)
10 unsigned int nr_openat_calls = 111, i; 12 unsigned int nr_openat_calls = 111, i;
11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 13 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
12 char sbuf[STRERR_BUFSIZE]; 14 char sbuf[STRERR_BUFSIZE];
15 char errbuf[BUFSIZ];
13 16
14 if (threads == NULL) { 17 if (threads == NULL) {
15 pr_debug("thread_map__new\n"); 18 pr_debug("thread_map__new\n");
@@ -17,13 +20,9 @@ int test__openat_syscall_event(void)
17 } 20 }
18 21
19 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); 22 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
20 if (evsel == NULL) { 23 if (IS_ERR(evsel)) {
21 if (tracefs_configured()) 24 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
22 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n"); 25 pr_debug("%s\n", errbuf);
23 else if (debugfs_configured())
24 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
25 else
26 pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
27 goto out_thread_map_delete; 26 goto out_thread_map_delete;
28 } 27 }
29 28
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 9b6b2b6324a1..636d7b42d844 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -3,11 +3,11 @@
3#include "evsel.h" 3#include "evsel.h"
4#include "evlist.h" 4#include "evlist.h"
5#include <api/fs/fs.h> 5#include <api/fs/fs.h>
6#include <api/fs/tracefs.h>
7#include <api/fs/debugfs.h>
8#include "tests.h" 6#include "tests.h"
9#include "debug.h" 7#include "debug.h"
8#include "util.h"
10#include <linux/hw_breakpoint.h> 9#include <linux/hw_breakpoint.h>
10#include <api/fs/fs.h>
11 11
12#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ 12#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
13 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) 13 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
@@ -1260,25 +1260,24 @@ test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist)
1260 return test__checkevent_breakpoint_rw(evlist); 1260 return test__checkevent_breakpoint_rw(evlist);
1261} 1261}
1262 1262
1263static int test__checkevent_precise_max_modifier(struct perf_evlist *evlist)
1264{
1265 struct perf_evsel *evsel = perf_evlist__first(evlist);
1266
1267 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
1268 TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
1269 TEST_ASSERT_VAL("wrong config",
1270 PERF_COUNT_SW_TASK_CLOCK == evsel->attr.config);
1271 return 0;
1272}
1273
1263static int count_tracepoints(void) 1274static int count_tracepoints(void)
1264{ 1275{
1265 char events_path[PATH_MAX];
1266 struct dirent *events_ent; 1276 struct dirent *events_ent;
1267 const char *mountpoint;
1268 DIR *events_dir; 1277 DIR *events_dir;
1269 int cnt = 0; 1278 int cnt = 0;
1270 1279
1271 mountpoint = tracefs_find_mountpoint(); 1280 events_dir = opendir(tracing_events_path);
1272 if (mountpoint) {
1273 scnprintf(events_path, PATH_MAX, "%s/events",
1274 mountpoint);
1275 } else {
1276 mountpoint = debugfs_find_mountpoint();
1277 scnprintf(events_path, PATH_MAX, "%s/tracing/events",
1278 mountpoint);
1279 }
1280
1281 events_dir = opendir(events_path);
1282 1281
1283 TEST_ASSERT_VAL("Can't open events dir", events_dir); 1282 TEST_ASSERT_VAL("Can't open events dir", events_dir);
1284 1283
@@ -1295,7 +1294,7 @@ static int count_tracepoints(void)
1295 continue; 1294 continue;
1296 1295
1297 scnprintf(sys_path, PATH_MAX, "%s/%s", 1296 scnprintf(sys_path, PATH_MAX, "%s/%s",
1298 events_path, events_ent->d_name); 1297 tracing_events_path, events_ent->d_name);
1299 1298
1300 sys_dir = opendir(sys_path); 1299 sys_dir = opendir(sys_path);
1301 TEST_ASSERT_VAL("Can't open sys dir", sys_dir); 1300 TEST_ASSERT_VAL("Can't open sys dir", sys_dir);
@@ -1575,6 +1574,11 @@ static struct evlist_test test__events[] = {
1575 .check = test__checkevent_exclude_idle_modifier_1, 1574 .check = test__checkevent_exclude_idle_modifier_1,
1576 .id = 46, 1575 .id = 46,
1577 }, 1576 },
1577 {
1578 .name = "task-clock:P,cycles",
1579 .check = test__checkevent_precise_max_modifier,
1580 .id = 47,
1581 },
1578}; 1582};
1579 1583
1580static struct evlist_test test__events_pmu[] = { 1584static struct evlist_test test__events_pmu[] = {
@@ -1750,6 +1754,17 @@ static int test_pmu_events(void)
1750 return ret; 1754 return ret;
1751} 1755}
1752 1756
1757static void debug_warn(const char *warn, va_list params)
1758{
1759 char msg[1024];
1760
1761 if (!verbose)
1762 return;
1763
1764 vsnprintf(msg, sizeof(msg), warn, params);
1765 fprintf(stderr, " Warning: %s\n", msg);
1766}
1767
1753int test__parse_events(void) 1768int test__parse_events(void)
1754{ 1769{
1755 int ret1, ret2 = 0; 1770 int ret1, ret2 = 0;
@@ -1761,6 +1776,8 @@ do { \
1761 ret2 = ret1; \ 1776 ret2 = ret1; \
1762} while (0) 1777} while (0)
1763 1778
1779 set_warning_routine(debug_warn);
1780
1764 TEST_EVENTS(test__events); 1781 TEST_EVENTS(test__events);
1765 1782
1766 if (test_pmu()) 1783 if (test_pmu())
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index e698742d4fec..a02af503100c 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -366,7 +366,7 @@ int test__switch_tracking(void)
366 366
367 /* Third event */ 367 /* Third event */
368 if (!perf_evlist__can_select_event(evlist, sched_switch)) { 368 if (!perf_evlist__can_select_event(evlist, sched_switch)) {
369 fprintf(stderr, " (no sched_switch)"); 369 pr_debug("No sched_switch\n");
370 err = 0; 370 err = 0;
371 goto out; 371 goto out;
372 } 372 }
@@ -442,7 +442,7 @@ int test__switch_tracking(void)
442 } 442 }
443 443
444 if (perf_evlist__open(evlist) < 0) { 444 if (perf_evlist__open(evlist) < 0) {
445 fprintf(stderr, " (not supported)"); 445 pr_debug("Not supported\n");
446 err = 0; 446 err = 0;
447 goto out; 447 goto out;
448 } 448 }
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index bf113a247987..3c8734a3abbc 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -24,13 +24,17 @@ enum {
24 TEST_SKIP = -2, 24 TEST_SKIP = -2,
25}; 25};
26 26
27struct test {
28 const char *desc;
29 int (*func)(void);
30};
31
27/* Tests */ 32/* Tests */
28int test__vmlinux_matches_kallsyms(void); 33int test__vmlinux_matches_kallsyms(void);
29int test__openat_syscall_event(void); 34int test__openat_syscall_event(void);
30int test__openat_syscall_event_on_all_cpus(void); 35int test__openat_syscall_event_on_all_cpus(void);
31int test__basic_mmap(void); 36int test__basic_mmap(void);
32int test__PERF_RECORD(void); 37int test__PERF_RECORD(void);
33int test__rdpmc(void);
34int test__perf_evsel__roundtrip_name_test(void); 38int test__perf_evsel__roundtrip_name_test(void);
35int test__perf_evsel__tp_sched_test(void); 39int test__perf_evsel__tp_sched_test(void);
36int test__syscall_openat_tp_fields(void); 40int test__syscall_openat_tp_fields(void);
@@ -46,7 +50,6 @@ int test__bp_signal(void);
46int test__bp_signal_overflow(void); 50int test__bp_signal_overflow(void);
47int test__task_exit(void); 51int test__task_exit(void);
48int test__sw_clock_freq(void); 52int test__sw_clock_freq(void);
49int test__perf_time_to_tsc(void);
50int test__code_reading(void); 53int test__code_reading(void);
51int test__sample_parsing(void); 54int test__sample_parsing(void);
52int test__keep_tracking(void); 55int test__keep_tracking(void);
@@ -63,8 +66,10 @@ int test__fdarray__add(void);
63int test__kmod_path__parse(void); 66int test__kmod_path__parse(void);
64int test__thread_map(void); 67int test__thread_map(void);
65int test__llvm(void); 68int test__llvm(void);
69int test__bpf(void);
70int test_session_topology(void);
66 71
67#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__) 72#if defined(__arm__) || defined(__aarch64__)
68#ifdef HAVE_DWARF_UNWIND_SUPPORT 73#ifdef HAVE_DWARF_UNWIND_SUPPORT
69struct thread; 74struct thread;
70struct perf_sample; 75struct perf_sample;
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
new file mode 100644
index 000000000000..f5bb096c3bd9
--- /dev/null
+++ b/tools/perf/tests/topology.c
@@ -0,0 +1,115 @@
1#include <string.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include "tests.h"
5#include "util.h"
6#include "session.h"
7#include "evlist.h"
8#include "debug.h"
9
10#define TEMPL "/tmp/perf-test-XXXXXX"
11#define DATA_SIZE 10
12
13static int get_temp(char *path)
14{
15 int fd;
16
17 strcpy(path, TEMPL);
18
19 fd = mkstemp(path);
20 if (fd < 0) {
21 perror("mkstemp failed");
22 return -1;
23 }
24
25 close(fd);
26 return 0;
27}
28
29static int session_write_header(char *path)
30{
31 struct perf_session *session;
32 struct perf_data_file file = {
33 .path = path,
34 .mode = PERF_DATA_MODE_WRITE,
35 };
36
37 session = perf_session__new(&file, false, NULL);
38 TEST_ASSERT_VAL("can't get session", session);
39
40 session->evlist = perf_evlist__new_default();
41 TEST_ASSERT_VAL("can't get evlist", session->evlist);
42
43 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
44 perf_header__set_feat(&session->header, HEADER_NRCPUS);
45
46 session->header.data_size += DATA_SIZE;
47
48 TEST_ASSERT_VAL("failed to write header",
49 !perf_session__write_header(session, session->evlist, file.fd, true));
50
51 perf_session__delete(session);
52
53 return 0;
54}
55
56static int check_cpu_topology(char *path, struct cpu_map *map)
57{
58 struct perf_session *session;
59 struct perf_data_file file = {
60 .path = path,
61 .mode = PERF_DATA_MODE_READ,
62 };
63 int i;
64
65 session = perf_session__new(&file, false, NULL);
66 TEST_ASSERT_VAL("can't get session", session);
67
68 for (i = 0; i < session->header.env.nr_cpus_online; i++) {
69 pr_debug("CPU %d, core %d, socket %d\n", i,
70 session->header.env.cpu[i].core_id,
71 session->header.env.cpu[i].socket_id);
72 }
73
74 for (i = 0; i < map->nr; i++) {
75 TEST_ASSERT_VAL("Core ID doesn't match",
76 (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i, NULL) & 0xffff)));
77
78 TEST_ASSERT_VAL("Socket ID doesn't match",
79 (session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i, NULL)));
80 }
81
82 perf_session__delete(session);
83
84 return 0;
85}
86
87int test_session_topology(void)
88{
89 char path[PATH_MAX];
90 struct cpu_map *map;
91 int ret = -1;
92
93 TEST_ASSERT_VAL("can't get templ file", !get_temp(path));
94
95 pr_debug("templ file: %s\n", path);
96
97 if (session_write_header(path))
98 goto free_path;
99
100 map = cpu_map__new(NULL);
101 if (map == NULL) {
102 pr_debug("failed to get system cpumap\n");
103 goto free_path;
104 }
105
106 if (check_cpu_topology(path, map))
107 goto free_map;
108 ret = 0;
109
110free_map:
111 cpu_map__put(map);
112free_path:
113 unlink(path);
114 return ret;
115}
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index b34c5fc829ae..d677e018e504 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -68,7 +68,7 @@ int test__vmlinux_matches_kallsyms(void)
68 * to see if the running kernel was relocated by checking if it has the 68 * to see if the running kernel was relocated by checking if it has the
69 * same value in the vmlinux file we load. 69 * same value in the vmlinux file we load.
70 */ 70 */
71 kallsyms_map = machine__kernel_map(&kallsyms, type); 71 kallsyms_map = machine__kernel_map(&kallsyms);
72 72
73 /* 73 /*
74 * Step 5: 74 * Step 5:
@@ -80,7 +80,7 @@ int test__vmlinux_matches_kallsyms(void)
80 goto out; 80 goto out;
81 } 81 }
82 82
83 vmlinux_map = machine__kernel_map(&vmlinux, type); 83 vmlinux_map = machine__kernel_map(&vmlinux);
84 84
85 /* 85 /*
86 * Step 6: 86 * Step 6:
diff --git a/tools/perf/trace/strace/groups/file b/tools/perf/trace/strace/groups/file
index 62378a899d79..722e25d200bf 100644
--- a/tools/perf/trace/strace/groups/file
+++ b/tools/perf/trace/strace/groups/file
@@ -9,6 +9,7 @@ mkdir
9open 9open
10openat 10openat
11quotactl 11quotactl
12read
12readlink 13readlink
13rename 14rename
14rmdir 15rmdir
@@ -16,3 +17,4 @@ stat
16statfs 17statfs
17symlink 18symlink
18unlink 19unlink
20write
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index c6c7e5189214..e9703c0829f1 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -393,6 +393,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
393 393
394 if (browser->use_navkeypressed && !browser->navkeypressed) { 394 if (browser->use_navkeypressed && !browser->navkeypressed) {
395 if (key == K_DOWN || key == K_UP || 395 if (key == K_DOWN || key == K_UP ||
396 (browser->columns && (key == K_LEFT || key == K_RIGHT)) ||
396 key == K_PGDN || key == K_PGUP || 397 key == K_PGDN || key == K_PGUP ||
397 key == K_HOME || key == K_END || 398 key == K_HOME || key == K_END ||
398 key == ' ') { 399 key == ' ') {
@@ -421,6 +422,18 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
421 browser->seek(browser, -1, SEEK_CUR); 422 browser->seek(browser, -1, SEEK_CUR);
422 } 423 }
423 break; 424 break;
425 case K_RIGHT:
426 if (!browser->columns)
427 goto out;
428 if (browser->horiz_scroll < browser->columns - 1)
429 ++browser->horiz_scroll;
430 break;
431 case K_LEFT:
432 if (!browser->columns)
433 goto out;
434 if (browser->horiz_scroll != 0)
435 --browser->horiz_scroll;
436 break;
424 case K_PGDN: 437 case K_PGDN:
425 case ' ': 438 case ' ':
426 if (browser->top_idx + browser->rows > browser->nr_entries - 1) 439 if (browser->top_idx + browser->rows > browser->nr_entries - 1)
@@ -459,6 +472,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
459 browser->seek(browser, -offset, SEEK_END); 472 browser->seek(browser, -offset, SEEK_END);
460 break; 473 break;
461 default: 474 default:
475 out:
462 return key; 476 return key;
463 } 477 }
464 } 478 }
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index f3cef564de02..01781de59532 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -14,7 +14,7 @@
14struct ui_browser { 14struct ui_browser {
15 u64 index, top_idx; 15 u64 index, top_idx;
16 void *top, *entries; 16 void *top, *entries;
17 u16 y, x, width, height, rows; 17 u16 y, x, width, height, rows, columns, horiz_scroll;
18 int current_color; 18 int current_color;
19 void *priv; 19 void *priv;
20 const char *title; 20 const char *title;
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 29739b347599..d4d7cc27252f 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -768,8 +768,8 @@ static int annotate_browser__run(struct annotate_browser *browser,
768 "UP/DOWN/PGUP\n" 768 "UP/DOWN/PGUP\n"
769 "PGDN/SPACE Navigate\n" 769 "PGDN/SPACE Navigate\n"
770 "q/ESC/CTRL+C Exit\n\n" 770 "q/ESC/CTRL+C Exit\n\n"
771 "-> Go to target\n" 771 "ENTER Go to target\n"
772 "<- Exit\n" 772 "ESC Exit\n"
773 "H Cycle thru hottest instructions\n" 773 "H Cycle thru hottest instructions\n"
774 "j Toggle showing jump to target arrows\n" 774 "j Toggle showing jump to target arrows\n"
775 "J Toggle showing number of jump sources on targets\n" 775 "J Toggle showing number of jump sources on targets\n"
@@ -1056,7 +1056,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1056 goto out_free_offsets; 1056 goto out_free_offsets;
1057 } 1057 }
1058 1058
1059 ui_helpline__push("Press <- or ESC to exit"); 1059 ui_helpline__push("Press ESC to exit");
1060 1060
1061 notes = symbol__annotation(sym); 1061 notes = symbol__annotation(sym);
1062 browser.start = map__rip_2objdump(map, sym->start); 1062 browser.start = map__rip_2objdump(map, sym->start);
@@ -1125,8 +1125,8 @@ static struct annotate_config {
1125 ANNOTATE_CFG(jump_arrows), 1125 ANNOTATE_CFG(jump_arrows),
1126 ANNOTATE_CFG(show_linenr), 1126 ANNOTATE_CFG(show_linenr),
1127 ANNOTATE_CFG(show_nr_jumps), 1127 ANNOTATE_CFG(show_nr_jumps),
1128 ANNOTATE_CFG(use_offset),
1129 ANNOTATE_CFG(show_total_period), 1128 ANNOTATE_CFG(show_total_period),
1129 ANNOTATE_CFG(use_offset),
1130}; 1130};
1131 1131
1132#undef ANNOTATE_CFG 1132#undef ANNOTATE_CFG
@@ -1152,9 +1152,9 @@ static int annotate__config(const char *var, const char *value,
1152 sizeof(struct annotate_config), annotate_config__cmp); 1152 sizeof(struct annotate_config), annotate_config__cmp);
1153 1153
1154 if (cfg == NULL) 1154 if (cfg == NULL)
1155 return -1; 1155 ui__warning("%s variable unknown, ignoring...", var);
1156 1156 else
1157 *cfg->value = perf_config_bool(name, value); 1157 *cfg->value = perf_config_bool(name, value);
1158 return 0; 1158 return 0;
1159} 1159}
1160 1160
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index c04c60d4863c..fa9eb92c9e24 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -784,11 +784,12 @@ static int hist_browser__show_entry(struct hist_browser *browser,
784 .size = sizeof(s), 784 .size = sizeof(s),
785 .ptr = &arg, 785 .ptr = &arg,
786 }; 786 };
787 int column = 0;
787 788
788 hist_browser__gotorc(browser, row, 0); 789 hist_browser__gotorc(browser, row, 0);
789 790
790 perf_hpp__for_each_format(fmt) { 791 perf_hpp__for_each_format(fmt) {
791 if (perf_hpp__should_skip(fmt)) 792 if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll)
792 continue; 793 continue;
793 794
794 if (current_entry && browser->b.navkeypressed) { 795 if (current_entry && browser->b.navkeypressed) {
@@ -861,14 +862,16 @@ static int advance_hpp_check(struct perf_hpp *hpp, int inc)
861 return hpp->size <= 0; 862 return hpp->size <= 0;
862} 863}
863 864
864static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists) 865static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf, size_t size)
865{ 866{
867 struct hists *hists = browser->hists;
866 struct perf_hpp dummy_hpp = { 868 struct perf_hpp dummy_hpp = {
867 .buf = buf, 869 .buf = buf,
868 .size = size, 870 .size = size,
869 }; 871 };
870 struct perf_hpp_fmt *fmt; 872 struct perf_hpp_fmt *fmt;
871 size_t ret = 0; 873 size_t ret = 0;
874 int column = 0;
872 875
873 if (symbol_conf.use_callchain) { 876 if (symbol_conf.use_callchain) {
874 ret = scnprintf(buf, size, " "); 877 ret = scnprintf(buf, size, " ");
@@ -877,7 +880,7 @@ static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists)
877 } 880 }
878 881
879 perf_hpp__for_each_format(fmt) { 882 perf_hpp__for_each_format(fmt) {
880 if (perf_hpp__should_skip(fmt)) 883 if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll)
881 continue; 884 continue;
882 885
883 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 886 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
@@ -896,7 +899,7 @@ static void hist_browser__show_headers(struct hist_browser *browser)
896{ 899{
897 char headers[1024]; 900 char headers[1024];
898 901
899 hists__scnprintf_headers(headers, sizeof(headers), browser->hists); 902 hists_browser__scnprintf_headers(browser, headers, sizeof(headers));
900 ui_browser__gotorc(&browser->b, 0, 0); 903 ui_browser__gotorc(&browser->b, 0, 0);
901 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); 904 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
902 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); 905 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
@@ -1261,6 +1264,7 @@ static int hists__browser_title(struct hists *hists,
1261 int printed; 1264 int printed;
1262 const struct dso *dso = hists->dso_filter; 1265 const struct dso *dso = hists->dso_filter;
1263 const struct thread *thread = hists->thread_filter; 1266 const struct thread *thread = hists->thread_filter;
1267 int socket_id = hists->socket_filter;
1264 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 1268 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
1265 u64 nr_events = hists->stats.total_period; 1269 u64 nr_events = hists->stats.total_period;
1266 struct perf_evsel *evsel = hists_to_evsel(hists); 1270 struct perf_evsel *evsel = hists_to_evsel(hists);
@@ -1314,6 +1318,9 @@ static int hists__browser_title(struct hists *hists,
1314 if (dso) 1318 if (dso)
1315 printed += scnprintf(bf + printed, size - printed, 1319 printed += scnprintf(bf + printed, size - printed,
1316 ", DSO: %s", dso->short_name); 1320 ", DSO: %s", dso->short_name);
1321 if (socket_id > -1)
1322 printed += scnprintf(bf + printed, size - printed,
1323 ", Processor Socket: %d", socket_id);
1317 if (!is_report_browser(hbt)) { 1324 if (!is_report_browser(hbt)) {
1318 struct perf_top *top = hbt->arg; 1325 struct perf_top *top = hbt->arg;
1319 1326
@@ -1423,8 +1430,8 @@ close_file_and_continue:
1423 1430
1424struct popup_action { 1431struct popup_action {
1425 struct thread *thread; 1432 struct thread *thread;
1426 struct dso *dso;
1427 struct map_symbol ms; 1433 struct map_symbol ms;
1434 int socket;
1428 1435
1429 int (*fn)(struct hist_browser *browser, struct popup_action *act); 1436 int (*fn)(struct hist_browser *browser, struct popup_action *act);
1430}; 1437};
@@ -1437,7 +1444,7 @@ do_annotate(struct hist_browser *browser, struct popup_action *act)
1437 struct hist_entry *he; 1444 struct hist_entry *he;
1438 int err; 1445 int err;
1439 1446
1440 if (!objdump_path && perf_session_env__lookup_objdump(browser->env)) 1447 if (!objdump_path && perf_env__lookup_objdump(browser->env))
1441 return 0; 1448 return 0;
1442 1449
1443 notes = symbol__annotation(act->ms.sym); 1450 notes = symbol__annotation(act->ms.sym);
@@ -1488,7 +1495,7 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act)
1488 thread__zput(browser->hists->thread_filter); 1495 thread__zput(browser->hists->thread_filter);
1489 ui_helpline__pop(); 1496 ui_helpline__pop();
1490 } else { 1497 } else {
1491 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", 1498 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"",
1492 thread->comm_set ? thread__comm_str(thread) : "", 1499 thread->comm_set ? thread__comm_str(thread) : "",
1493 thread->tid); 1500 thread->tid);
1494 browser->hists->thread_filter = thread__get(thread); 1501 browser->hists->thread_filter = thread__get(thread);
@@ -1522,7 +1529,7 @@ add_thread_opt(struct hist_browser *browser, struct popup_action *act,
1522static int 1529static int
1523do_zoom_dso(struct hist_browser *browser, struct popup_action *act) 1530do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
1524{ 1531{
1525 struct dso *dso = act->dso; 1532 struct map *map = act->ms.map;
1526 1533
1527 if (browser->hists->dso_filter) { 1534 if (browser->hists->dso_filter) {
1528 pstack__remove(browser->pstack, &browser->hists->dso_filter); 1535 pstack__remove(browser->pstack, &browser->hists->dso_filter);
@@ -1530,11 +1537,11 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
1530 browser->hists->dso_filter = NULL; 1537 browser->hists->dso_filter = NULL;
1531 ui_helpline__pop(); 1538 ui_helpline__pop();
1532 } else { 1539 } else {
1533 if (dso == NULL) 1540 if (map == NULL)
1534 return 0; 1541 return 0;
1535 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", 1542 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s DSO\"",
1536 dso->kernel ? "the Kernel" : dso->short_name); 1543 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name);
1537 browser->hists->dso_filter = dso; 1544 browser->hists->dso_filter = map->dso;
1538 perf_hpp__set_elide(HISTC_DSO, true); 1545 perf_hpp__set_elide(HISTC_DSO, true);
1539 pstack__push(browser->pstack, &browser->hists->dso_filter); 1546 pstack__push(browser->pstack, &browser->hists->dso_filter);
1540 } 1547 }
@@ -1546,17 +1553,17 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
1546 1553
1547static int 1554static int
1548add_dso_opt(struct hist_browser *browser, struct popup_action *act, 1555add_dso_opt(struct hist_browser *browser, struct popup_action *act,
1549 char **optstr, struct dso *dso) 1556 char **optstr, struct map *map)
1550{ 1557{
1551 if (dso == NULL) 1558 if (map == NULL)
1552 return 0; 1559 return 0;
1553 1560
1554 if (asprintf(optstr, "Zoom %s %s DSO", 1561 if (asprintf(optstr, "Zoom %s %s DSO",
1555 browser->hists->dso_filter ? "out of" : "into", 1562 browser->hists->dso_filter ? "out of" : "into",
1556 dso->kernel ? "the Kernel" : dso->short_name) < 0) 1563 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name) < 0)
1557 return 0; 1564 return 0;
1558 1565
1559 act->dso = dso; 1566 act->ms.map = map;
1560 act->fn = do_zoom_dso; 1567 act->fn = do_zoom_dso;
1561 return 1; 1568 return 1;
1562} 1569}
@@ -1672,6 +1679,41 @@ add_exit_opt(struct hist_browser *browser __maybe_unused,
1672 return 1; 1679 return 1;
1673} 1680}
1674 1681
1682static int
1683do_zoom_socket(struct hist_browser *browser, struct popup_action *act)
1684{
1685 if (browser->hists->socket_filter > -1) {
1686 pstack__remove(browser->pstack, &browser->hists->socket_filter);
1687 browser->hists->socket_filter = -1;
1688 perf_hpp__set_elide(HISTC_SOCKET, false);
1689 } else {
1690 browser->hists->socket_filter = act->socket;
1691 perf_hpp__set_elide(HISTC_SOCKET, true);
1692 pstack__push(browser->pstack, &browser->hists->socket_filter);
1693 }
1694
1695 hists__filter_by_socket(browser->hists);
1696 hist_browser__reset(browser);
1697 return 0;
1698}
1699
1700static int
1701add_socket_opt(struct hist_browser *browser, struct popup_action *act,
1702 char **optstr, int socket_id)
1703{
1704 if (socket_id < 0)
1705 return 0;
1706
1707 if (asprintf(optstr, "Zoom %s Processor Socket %d",
1708 (browser->hists->socket_filter > -1) ? "out of" : "into",
1709 socket_id) < 0)
1710 return 0;
1711
1712 act->socket = socket_id;
1713 act->fn = do_zoom_socket;
1714 return 1;
1715}
1716
1675static void hist_browser__update_nr_entries(struct hist_browser *hb) 1717static void hist_browser__update_nr_entries(struct hist_browser *hb)
1676{ 1718{
1677 u64 nr_entries = 0; 1719 u64 nr_entries = 0;
@@ -1717,14 +1759,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1717 "For multiple event sessions:\n\n" \ 1759 "For multiple event sessions:\n\n" \
1718 "TAB/UNTAB Switch events\n\n" \ 1760 "TAB/UNTAB Switch events\n\n" \
1719 "For symbolic views (--sort has sym):\n\n" \ 1761 "For symbolic views (--sort has sym):\n\n" \
1720 "-> Zoom into DSO/Threads & Annotate current symbol\n" \ 1762 "ENTER Zoom into DSO/Threads & Annotate current symbol\n" \
1721 "<- Zoom out\n" \ 1763 "ESC Zoom out\n" \
1722 "a Annotate current symbol\n" \ 1764 "a Annotate current symbol\n" \
1723 "C Collapse all callchains\n" \ 1765 "C Collapse all callchains\n" \
1724 "d Zoom into current DSO\n" \ 1766 "d Zoom into current DSO\n" \
1725 "E Expand all callchains\n" \ 1767 "E Expand all callchains\n" \
1726 "F Toggle percentage of filtered entries\n" \ 1768 "F Toggle percentage of filtered entries\n" \
1727 "H Display column headers\n" \ 1769 "H Display column headers\n" \
1770 "m Display context menu\n" \
1771 "S Zoom into current Processor Socket\n" \
1728 1772
1729 /* help messages are sorted by lexical order of the hotkey */ 1773 /* help messages are sorted by lexical order of the hotkey */
1730 const char report_help[] = HIST_BROWSER_HELP_COMMON 1774 const char report_help[] = HIST_BROWSER_HELP_COMMON
@@ -1755,7 +1799,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1755 hist_browser__update_nr_entries(browser); 1799 hist_browser__update_nr_entries(browser);
1756 } 1800 }
1757 1801
1758 browser->pstack = pstack__new(2); 1802 browser->pstack = pstack__new(3);
1759 if (browser->pstack == NULL) 1803 if (browser->pstack == NULL)
1760 goto out; 1804 goto out;
1761 1805
@@ -1764,16 +1808,26 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1764 memset(options, 0, sizeof(options)); 1808 memset(options, 0, sizeof(options));
1765 memset(actions, 0, sizeof(actions)); 1809 memset(actions, 0, sizeof(actions));
1766 1810
1767 perf_hpp__for_each_format(fmt) 1811 perf_hpp__for_each_format(fmt) {
1768 perf_hpp__reset_width(fmt, hists); 1812 perf_hpp__reset_width(fmt, hists);
1813 /*
1814 * This is done just once, and activates the horizontal scrolling
1815 * code in the ui_browser code, it would be better to have a the
1816 * counter in the perf_hpp code, but I couldn't find doing it here
1817 * works, FIXME by setting this in hist_browser__new, for now, be
1818 * clever 8-)
1819 */
1820 ++browser->b.columns;
1821 }
1769 1822
1770 if (symbol_conf.col_width_list_str) 1823 if (symbol_conf.col_width_list_str)
1771 perf_hpp__set_user_width(symbol_conf.col_width_list_str); 1824 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
1772 1825
1773 while (1) { 1826 while (1) {
1774 struct thread *thread = NULL; 1827 struct thread *thread = NULL;
1775 struct dso *dso = NULL; 1828 struct map *map = NULL;
1776 int choice = 0; 1829 int choice = 0;
1830 int socked_id = -1;
1777 1831
1778 nr_options = 0; 1832 nr_options = 0;
1779 1833
@@ -1781,7 +1835,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1781 1835
1782 if (browser->he_selection != NULL) { 1836 if (browser->he_selection != NULL) {
1783 thread = hist_browser__selected_thread(browser); 1837 thread = hist_browser__selected_thread(browser);
1784 dso = browser->selection->map ? browser->selection->map->dso : NULL; 1838 map = browser->selection->map;
1839 socked_id = browser->he_selection->socket;
1785 } 1840 }
1786 switch (key) { 1841 switch (key) {
1787 case K_TAB: 1842 case K_TAB:
@@ -1814,7 +1869,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1814 hist_browser__dump(browser); 1869 hist_browser__dump(browser);
1815 continue; 1870 continue;
1816 case 'd': 1871 case 'd':
1817 actions->dso = dso; 1872 actions->ms.map = map;
1818 do_zoom_dso(browser, actions); 1873 do_zoom_dso(browser, actions);
1819 continue; 1874 continue;
1820 case 'V': 1875 case 'V':
@@ -1824,9 +1879,14 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1824 actions->thread = thread; 1879 actions->thread = thread;
1825 do_zoom_thread(browser, actions); 1880 do_zoom_thread(browser, actions);
1826 continue; 1881 continue;
1882 case 'S':
1883 actions->socket = socked_id;
1884 do_zoom_socket(browser, actions);
1885 continue;
1827 case '/': 1886 case '/':
1828 if (ui_browser__input_window("Symbol to show", 1887 if (ui_browser__input_window("Symbol to show",
1829 "Please enter the name of symbol you want to see", 1888 "Please enter the name of symbol you want to see.\n"
1889 "To remove the filter later, press / + ENTER.",
1830 buf, "ENTER: OK, ESC: Cancel", 1890 buf, "ENTER: OK, ESC: Cancel",
1831 delay_secs * 2) == K_ENTER) { 1891 delay_secs * 2) == K_ENTER) {
1832 hists->symbol_filter_str = *buf ? buf : NULL; 1892 hists->symbol_filter_str = *buf ? buf : NULL;
@@ -1871,6 +1931,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1871 continue; 1931 continue;
1872 case K_ENTER: 1932 case K_ENTER:
1873 case K_RIGHT: 1933 case K_RIGHT:
1934 case 'm':
1874 /* menu */ 1935 /* menu */
1875 break; 1936 break;
1876 case K_ESC: 1937 case K_ESC:
@@ -1899,9 +1960,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1899 * Ditto for thread below. 1960 * Ditto for thread below.
1900 */ 1961 */
1901 do_zoom_dso(browser, actions); 1962 do_zoom_dso(browser, actions);
1902 } 1963 } else if (top == &browser->hists->thread_filter) {
1903 if (top == &browser->hists->thread_filter)
1904 do_zoom_thread(browser, actions); 1964 do_zoom_thread(browser, actions);
1965 } else if (top == &browser->hists->socket_filter) {
1966 do_zoom_socket(browser, actions);
1967 }
1905 continue; 1968 continue;
1906 } 1969 }
1907 case 'q': 1970 case 'q':
@@ -1965,12 +2028,14 @@ skip_annotation:
1965 nr_options += add_thread_opt(browser, &actions[nr_options], 2028 nr_options += add_thread_opt(browser, &actions[nr_options],
1966 &options[nr_options], thread); 2029 &options[nr_options], thread);
1967 nr_options += add_dso_opt(browser, &actions[nr_options], 2030 nr_options += add_dso_opt(browser, &actions[nr_options],
1968 &options[nr_options], dso); 2031 &options[nr_options], map);
1969 nr_options += add_map_opt(browser, &actions[nr_options], 2032 nr_options += add_map_opt(browser, &actions[nr_options],
1970 &options[nr_options], 2033 &options[nr_options],
1971 browser->selection ? 2034 browser->selection ?
1972 browser->selection->map : NULL); 2035 browser->selection->map : NULL);
1973 2036 nr_options += add_socket_opt(browser, &actions[nr_options],
2037 &options[nr_options],
2038 socked_id);
1974 /* perf script support */ 2039 /* perf script support */
1975 if (browser->he_selection) { 2040 if (browser->he_selection) {
1976 nr_options += add_script_opt(browser, 2041 nr_options += add_script_opt(browser,
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index 8c154c7d4669..80912778bb6d 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -72,7 +72,7 @@ static int map_browser__run(struct map_browser *browser)
72 int key; 72 int key;
73 73
74 if (ui_browser__show(&browser->b, browser->map->dso->long_name, 74 if (ui_browser__show(&browser->b, browser->map->dso->long_name,
75 "Press <- or ESC to exit, %s / to search", 75 "Press ESC to exit, %s / to search",
76 verbose ? "" : "restart with -v to use") < 0) 76 verbose ? "" : "restart with -v to use") < 0)
77 return -1; 77 return -1;
78 78
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index e13b48d705ef..ad6b6ee3770e 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -89,7 +89,7 @@ static int script_browser__run(struct perf_script_browser *browser)
89 int key; 89 int key;
90 90
91 if (ui_browser__show(&browser->b, browser->script_name, 91 if (ui_browser__show(&browser->b, browser->script_name,
92 "Press <- or ESC to exit") < 0) 92 "Press ESC to exit") < 0)
93 return -1; 93 return -1;
94 94
95 while (1) { 95 while (1) {
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 25d608394d74..5029ba2b55af 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -463,27 +463,27 @@ void perf_hpp__init(void)
463 return; 463 return;
464 464
465 if (symbol_conf.cumulate_callchain) { 465 if (symbol_conf.cumulate_callchain) {
466 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC); 466 hpp_dimension__add_output(PERF_HPP__OVERHEAD_ACC);
467 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self"; 467 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self";
468 } 468 }
469 469
470 perf_hpp__column_enable(PERF_HPP__OVERHEAD); 470 hpp_dimension__add_output(PERF_HPP__OVERHEAD);
471 471
472 if (symbol_conf.show_cpu_utilization) { 472 if (symbol_conf.show_cpu_utilization) {
473 perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS); 473 hpp_dimension__add_output(PERF_HPP__OVERHEAD_SYS);
474 perf_hpp__column_enable(PERF_HPP__OVERHEAD_US); 474 hpp_dimension__add_output(PERF_HPP__OVERHEAD_US);
475 475
476 if (perf_guest) { 476 if (perf_guest) {
477 perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_SYS); 477 hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_SYS);
478 perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_US); 478 hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_US);
479 } 479 }
480 } 480 }
481 481
482 if (symbol_conf.show_nr_samples) 482 if (symbol_conf.show_nr_samples)
483 perf_hpp__column_enable(PERF_HPP__SAMPLES); 483 hpp_dimension__add_output(PERF_HPP__SAMPLES);
484 484
485 if (symbol_conf.show_total_period) 485 if (symbol_conf.show_total_period)
486 perf_hpp__column_enable(PERF_HPP__PERIOD); 486 hpp_dimension__add_output(PERF_HPP__PERIOD);
487 487
488 /* prepend overhead field for backward compatiblity. */ 488 /* prepend overhead field for backward compatiblity. */
489 list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list; 489 list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list;
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index 60d1f29b4b50..7dfeba0a91f3 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -141,10 +141,6 @@ int ui__init(void)
141 141
142 SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB); 142 SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB);
143 143
144 ui_helpline__init();
145 ui_browser__init();
146 tui_progress__init();
147
148 signal(SIGSEGV, ui__signal_backtrace); 144 signal(SIGSEGV, ui__signal_backtrace);
149 signal(SIGFPE, ui__signal_backtrace); 145 signal(SIGFPE, ui__signal_backtrace);
150 signal(SIGINT, ui__signal); 146 signal(SIGINT, ui__signal);
@@ -153,6 +149,10 @@ int ui__init(void)
153 149
154 perf_error__register(&perf_tui_eops); 150 perf_error__register(&perf_tui_eops);
155 151
152 ui_helpline__init();
153 ui_browser__init();
154 tui_progress__init();
155
156 hist_browser__init_hpp(); 156 hist_browser__init_hpp();
157out: 157out:
158 return err; 158 return err;
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index e5f18a288b74..591b3fe3ed49 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -5,6 +5,7 @@ libperf-y += build-id.o
5libperf-y += config.o 5libperf-y += config.o
6libperf-y += ctype.o 6libperf-y += ctype.o
7libperf-y += db-export.o 7libperf-y += db-export.o
8libperf-y += env.o
8libperf-y += environment.o 9libperf-y += environment.o
9libperf-y += event.o 10libperf-y += event.o
10libperf-y += evlist.o 11libperf-y += evlist.o
@@ -86,6 +87,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-bts.o
86libperf-y += parse-branch-options.o 87libperf-y += parse-branch-options.o
87libperf-y += parse-regs-options.o 88libperf-y += parse-regs-options.o
88 89
90libperf-$(CONFIG_LIBBPF) += bpf-loader.o
89libperf-$(CONFIG_LIBELF) += symbol-elf.o 91libperf-$(CONFIG_LIBELF) += symbol-elf.o
90libperf-$(CONFIG_LIBELF) += probe-file.o 92libperf-$(CONFIG_LIBELF) += probe-file.o
91libperf-$(CONFIG_LIBELF) += probe-event.o 93libperf-$(CONFIG_LIBELF) += probe-event.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index d1eece70b84d..1dd1949b0e79 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -548,8 +548,11 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
548 548
549 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 549 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
550 550
551 if (addr < sym->start || addr >= sym->end) 551 if (addr < sym->start || addr >= sym->end) {
552 pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n",
553 __func__, __LINE__, sym->name, sym->start, addr, sym->end);
552 return -ERANGE; 554 return -ERANGE;
555 }
553 556
554 offset = addr - sym->start; 557 offset = addr - sym->start;
555 h = annotation__histogram(notes, evidx); 558 h = annotation__histogram(notes, evidx);
@@ -1081,6 +1084,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
1081 struct kcore_extract kce; 1084 struct kcore_extract kce;
1082 bool delete_extract = false; 1085 bool delete_extract = false;
1083 int lineno = 0; 1086 int lineno = 0;
1087 int nline;
1084 1088
1085 if (filename) 1089 if (filename)
1086 symbol__join_symfs(symfs_filename, filename); 1090 symbol__join_symfs(symfs_filename, filename);
@@ -1176,6 +1180,9 @@ fallback:
1176 1180
1177 ret = decompress_to_file(m.ext, symfs_filename, fd); 1181 ret = decompress_to_file(m.ext, symfs_filename, fd);
1178 1182
1183 if (ret)
1184 pr_err("Cannot decompress %s %s\n", m.ext, symfs_filename);
1185
1179 free(m.ext); 1186 free(m.ext);
1180 close(fd); 1187 close(fd);
1181 1188
@@ -1201,13 +1208,25 @@ fallback:
1201 pr_debug("Executing: %s\n", command); 1208 pr_debug("Executing: %s\n", command);
1202 1209
1203 file = popen(command, "r"); 1210 file = popen(command, "r");
1204 if (!file) 1211 if (!file) {
1212 pr_err("Failure running %s\n", command);
1213 /*
1214 * If we were using debug info should retry with
1215 * original binary.
1216 */
1205 goto out_remove_tmp; 1217 goto out_remove_tmp;
1218 }
1206 1219
1207 while (!feof(file)) 1220 nline = 0;
1221 while (!feof(file)) {
1208 if (symbol__parse_objdump_line(sym, map, file, privsize, 1222 if (symbol__parse_objdump_line(sym, map, file, privsize,
1209 &lineno) < 0) 1223 &lineno) < 0)
1210 break; 1224 break;
1225 nline++;
1226 }
1227
1228 if (nline == 0)
1229 pr_err("No output from %s\n", command);
1211 1230
1212 /* 1231 /*
1213 * kallsyms does not have symbol sizes so there may a nop at the end. 1232 * kallsyms does not have symbol sizes so there may a nop at the end.
@@ -1601,6 +1620,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1601 len = symbol__size(sym); 1620 len = symbol__size(sym);
1602 1621
1603 if (print_lines) { 1622 if (print_lines) {
1623 srcline_full_filename = full_paths;
1604 symbol__get_source_line(sym, map, evsel, &source_line, len); 1624 symbol__get_source_line(sym, map, evsel, &source_line, len);
1605 print_summary(&source_line, dso->long_name); 1625 print_summary(&source_line, dso->long_name);
1606 } 1626 }
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index e9996092a093..cea323d9ee7e 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -122,7 +122,7 @@ struct annotated_source {
122 struct list_head source; 122 struct list_head source;
123 struct source_line *lines; 123 struct source_line *lines;
124 int nr_histograms; 124 int nr_histograms;
125 int sizeof_sym_hist; 125 size_t sizeof_sym_hist;
126 struct cyc_hist *cycles_hist; 126 struct cyc_hist *cycles_hist;
127 struct sym_hist histograms[0]; 127 struct sym_hist histograms[0];
128}; 128};
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index a980e7c50ee0..7f10430af39c 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -926,6 +926,8 @@ s64 perf_event__process_auxtrace(struct perf_tool *tool,
926#define PERF_ITRACE_DEFAULT_PERIOD 100000 926#define PERF_ITRACE_DEFAULT_PERIOD 100000
927#define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16 927#define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16
928#define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024 928#define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024
929#define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64
930#define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024
929 931
930void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) 932void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
931{ 933{
@@ -936,6 +938,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
936 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; 938 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
937 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; 939 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
938 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; 940 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
941 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
939} 942}
940 943
941/* 944/*
@@ -950,6 +953,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
950 const char *p; 953 const char *p;
951 char *endptr; 954 char *endptr;
952 bool period_type_set = false; 955 bool period_type_set = false;
956 bool period_set = false;
953 957
954 synth_opts->set = true; 958 synth_opts->set = true;
955 959
@@ -971,6 +975,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
971 p += 1; 975 p += 1;
972 if (isdigit(*p)) { 976 if (isdigit(*p)) {
973 synth_opts->period = strtoull(p, &endptr, 10); 977 synth_opts->period = strtoull(p, &endptr, 10);
978 period_set = true;
974 p = endptr; 979 p = endptr;
975 while (*p == ' ' || *p == ',') 980 while (*p == ' ' || *p == ',')
976 p += 1; 981 p += 1;
@@ -1041,6 +1046,23 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
1041 synth_opts->callchain_sz = val; 1046 synth_opts->callchain_sz = val;
1042 } 1047 }
1043 break; 1048 break;
1049 case 'l':
1050 synth_opts->last_branch = true;
1051 synth_opts->last_branch_sz =
1052 PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
1053 while (*p == ' ' || *p == ',')
1054 p += 1;
1055 if (isdigit(*p)) {
1056 unsigned int val;
1057
1058 val = strtoul(p, &endptr, 10);
1059 p = endptr;
1060 if (!val ||
1061 val > PERF_ITRACE_MAX_LAST_BRANCH_SZ)
1062 goto out_err;
1063 synth_opts->last_branch_sz = val;
1064 }
1065 break;
1044 case ' ': 1066 case ' ':
1045 case ',': 1067 case ',':
1046 break; 1068 break;
@@ -1053,7 +1075,7 @@ out:
1053 if (!period_type_set) 1075 if (!period_type_set)
1054 synth_opts->period_type = 1076 synth_opts->period_type =
1055 PERF_ITRACE_DEFAULT_PERIOD_TYPE; 1077 PERF_ITRACE_DEFAULT_PERIOD_TYPE;
1056 if (!synth_opts->period) 1078 if (!period_set)
1057 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; 1079 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
1058 } 1080 }
1059 1081
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index bf72b77a588a..b86f90db1352 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -63,7 +63,9 @@ enum itrace_period_type {
63 * @calls: limit branch samples to calls (can be combined with @returns) 63 * @calls: limit branch samples to calls (can be combined with @returns)
64 * @returns: limit branch samples to returns (can be combined with @calls) 64 * @returns: limit branch samples to returns (can be combined with @calls)
65 * @callchain: add callchain to 'instructions' events 65 * @callchain: add callchain to 'instructions' events
66 * @last_branch: add branch context to 'instruction' events
66 * @callchain_sz: maximum callchain size 67 * @callchain_sz: maximum callchain size
68 * @last_branch_sz: branch context size
67 * @period: 'instructions' events period 69 * @period: 'instructions' events period
68 * @period_type: 'instructions' events period type 70 * @period_type: 'instructions' events period type
69 */ 71 */
@@ -79,7 +81,9 @@ struct itrace_synth_opts {
79 bool calls; 81 bool calls;
80 bool returns; 82 bool returns;
81 bool callchain; 83 bool callchain;
84 bool last_branch;
82 unsigned int callchain_sz; 85 unsigned int callchain_sz;
86 unsigned int last_branch_sz;
83 unsigned long long period; 87 unsigned long long period;
84 enum itrace_period_type period_type; 88 enum itrace_period_type period_type;
85}; 89};
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
new file mode 100644
index 000000000000..4c50411371db
--- /dev/null
+++ b/tools/perf/util/bpf-loader.c
@@ -0,0 +1,457 @@
1/*
2 * bpf-loader.c
3 *
4 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
5 * Copyright (C) 2015 Huawei Inc.
6 */
7
8#include <bpf/libbpf.h>
9#include <linux/err.h>
10#include "perf.h"
11#include "debug.h"
12#include "bpf-loader.h"
13#include "probe-event.h"
14#include "probe-finder.h" // for MAX_PROBES
15#include "llvm-utils.h"
16
17#define DEFINE_PRINT_FN(name, level) \
18static int libbpf_##name(const char *fmt, ...) \
19{ \
20 va_list args; \
21 int ret; \
22 \
23 va_start(args, fmt); \
24 ret = veprintf(level, verbose, pr_fmt(fmt), args);\
25 va_end(args); \
26 return ret; \
27}
28
29DEFINE_PRINT_FN(warning, 1)
30DEFINE_PRINT_FN(info, 1)
31DEFINE_PRINT_FN(debug, 1)
32
33struct bpf_prog_priv {
34 struct perf_probe_event pev;
35};
36
37static bool libbpf_initialized;
38
39struct bpf_object *
40bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, const char *name)
41{
42 struct bpf_object *obj;
43
44 if (!libbpf_initialized) {
45 libbpf_set_print(libbpf_warning,
46 libbpf_info,
47 libbpf_debug);
48 libbpf_initialized = true;
49 }
50
51 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, name);
52 if (IS_ERR(obj)) {
53 pr_debug("bpf: failed to load buffer\n");
54 return ERR_PTR(-EINVAL);
55 }
56
57 return obj;
58}
59
60struct bpf_object *bpf__prepare_load(const char *filename, bool source)
61{
62 struct bpf_object *obj;
63
64 if (!libbpf_initialized) {
65 libbpf_set_print(libbpf_warning,
66 libbpf_info,
67 libbpf_debug);
68 libbpf_initialized = true;
69 }
70
71 if (source) {
72 int err;
73 void *obj_buf;
74 size_t obj_buf_sz;
75
76 err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
77 if (err)
78 return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
79 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
80 free(obj_buf);
81 } else
82 obj = bpf_object__open(filename);
83
84 if (IS_ERR(obj)) {
85 pr_debug("bpf: failed to load %s\n", filename);
86 return obj;
87 }
88
89 return obj;
90}
91
92void bpf__clear(void)
93{
94 struct bpf_object *obj, *tmp;
95
96 bpf_object__for_each_safe(obj, tmp) {
97 bpf__unprobe(obj);
98 bpf_object__close(obj);
99 }
100}
101
102static void
103bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
104 void *_priv)
105{
106 struct bpf_prog_priv *priv = _priv;
107
108 cleanup_perf_probe_events(&priv->pev, 1);
109 free(priv);
110}
111
112static int
113config_bpf_program(struct bpf_program *prog)
114{
115 struct perf_probe_event *pev = NULL;
116 struct bpf_prog_priv *priv = NULL;
117 const char *config_str;
118 int err;
119
120 config_str = bpf_program__title(prog, false);
121 if (IS_ERR(config_str)) {
122 pr_debug("bpf: unable to get title for program\n");
123 return PTR_ERR(config_str);
124 }
125
126 priv = calloc(sizeof(*priv), 1);
127 if (!priv) {
128 pr_debug("bpf: failed to alloc priv\n");
129 return -ENOMEM;
130 }
131 pev = &priv->pev;
132
133 pr_debug("bpf: config program '%s'\n", config_str);
134 err = parse_perf_probe_command(config_str, pev);
135 if (err < 0) {
136 pr_debug("bpf: '%s' is not a valid config string\n",
137 config_str);
138 err = -BPF_LOADER_ERRNO__CONFIG;
139 goto errout;
140 }
141
142 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
143 pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
144 config_str, PERF_BPF_PROBE_GROUP);
145 err = -BPF_LOADER_ERRNO__GROUP;
146 goto errout;
147 } else if (!pev->group)
148 pev->group = strdup(PERF_BPF_PROBE_GROUP);
149
150 if (!pev->group) {
151 pr_debug("bpf: strdup failed\n");
152 err = -ENOMEM;
153 goto errout;
154 }
155
156 if (!pev->event) {
157 pr_debug("bpf: '%s': event name is missing. Section name should be 'key=value'\n",
158 config_str);
159 err = -BPF_LOADER_ERRNO__EVENTNAME;
160 goto errout;
161 }
162 pr_debug("bpf: config '%s' is ok\n", config_str);
163
164 err = bpf_program__set_private(prog, priv, bpf_prog_priv__clear);
165 if (err) {
166 pr_debug("Failed to set priv for program '%s'\n", config_str);
167 goto errout;
168 }
169
170 return 0;
171
172errout:
173 if (pev)
174 clear_perf_probe_event(pev);
175 free(priv);
176 return err;
177}
178
179static int bpf__prepare_probe(void)
180{
181 static int err = 0;
182 static bool initialized = false;
183
184 /*
185 * Make err static, so if init failed the first, bpf__prepare_probe()
186 * fails each time without calling init_probe_symbol_maps multiple
187 * times.
188 */
189 if (initialized)
190 return err;
191
192 initialized = true;
193 err = init_probe_symbol_maps(false);
194 if (err < 0)
195 pr_debug("Failed to init_probe_symbol_maps\n");
196 probe_conf.max_probes = MAX_PROBES;
197 return err;
198}
199
200int bpf__probe(struct bpf_object *obj)
201{
202 int err = 0;
203 struct bpf_program *prog;
204 struct bpf_prog_priv *priv;
205 struct perf_probe_event *pev;
206
207 err = bpf__prepare_probe();
208 if (err) {
209 pr_debug("bpf__prepare_probe failed\n");
210 return err;
211 }
212
213 bpf_object__for_each_program(prog, obj) {
214 err = config_bpf_program(prog);
215 if (err)
216 goto out;
217
218 err = bpf_program__get_private(prog, (void **)&priv);
219 if (err || !priv)
220 goto out;
221 pev = &priv->pev;
222
223 err = convert_perf_probe_events(pev, 1);
224 if (err < 0) {
225 pr_debug("bpf_probe: failed to convert perf probe events");
226 goto out;
227 }
228
229 err = apply_perf_probe_events(pev, 1);
230 if (err < 0) {
231 pr_debug("bpf_probe: failed to apply perf probe events");
232 goto out;
233 }
234 }
235out:
236 return err < 0 ? err : 0;
237}
238
239#define EVENTS_WRITE_BUFSIZE 4096
240int bpf__unprobe(struct bpf_object *obj)
241{
242 int err, ret = 0;
243 struct bpf_program *prog;
244 struct bpf_prog_priv *priv;
245
246 bpf_object__for_each_program(prog, obj) {
247 int i;
248
249 err = bpf_program__get_private(prog, (void **)&priv);
250 if (err || !priv)
251 continue;
252
253 for (i = 0; i < priv->pev.ntevs; i++) {
254 struct probe_trace_event *tev = &priv->pev.tevs[i];
255 char name_buf[EVENTS_WRITE_BUFSIZE];
256 struct strfilter *delfilter;
257
258 snprintf(name_buf, EVENTS_WRITE_BUFSIZE,
259 "%s:%s", tev->group, tev->event);
260 name_buf[EVENTS_WRITE_BUFSIZE - 1] = '\0';
261
262 delfilter = strfilter__new(name_buf, NULL);
263 if (!delfilter) {
264 pr_debug("Failed to create filter for unprobing\n");
265 ret = -ENOMEM;
266 continue;
267 }
268
269 err = del_perf_probe_events(delfilter);
270 strfilter__delete(delfilter);
271 if (err) {
272 pr_debug("Failed to delete %s\n", name_buf);
273 ret = err;
274 continue;
275 }
276 }
277 }
278 return ret;
279}
280
281int bpf__load(struct bpf_object *obj)
282{
283 int err;
284
285 err = bpf_object__load(obj);
286 if (err) {
287 pr_debug("bpf: load objects failed\n");
288 return err;
289 }
290 return 0;
291}
292
293int bpf__foreach_tev(struct bpf_object *obj,
294 bpf_prog_iter_callback_t func,
295 void *arg)
296{
297 struct bpf_program *prog;
298 int err;
299
300 bpf_object__for_each_program(prog, obj) {
301 struct probe_trace_event *tev;
302 struct perf_probe_event *pev;
303 struct bpf_prog_priv *priv;
304 int i, fd;
305
306 err = bpf_program__get_private(prog,
307 (void **)&priv);
308 if (err || !priv) {
309 pr_debug("bpf: failed to get private field\n");
310 return -BPF_LOADER_ERRNO__INTERNAL;
311 }
312
313 pev = &priv->pev;
314 for (i = 0; i < pev->ntevs; i++) {
315 tev = &pev->tevs[i];
316
317 fd = bpf_program__fd(prog);
318 if (fd < 0) {
319 pr_debug("bpf: failed to get file descriptor\n");
320 return fd;
321 }
322
323 err = (*func)(tev, fd, arg);
324 if (err) {
325 pr_debug("bpf: call back failed, stop iterate\n");
326 return err;
327 }
328 }
329 }
330 return 0;
331}
332
333#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)
334#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
335#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
336
337static const char *bpf_loader_strerror_table[NR_ERRNO] = {
338 [ERRCODE_OFFSET(CONFIG)] = "Invalid config string",
339 [ERRCODE_OFFSET(GROUP)] = "Invalid group name",
340 [ERRCODE_OFFSET(EVENTNAME)] = "No event name found in config string",
341 [ERRCODE_OFFSET(INTERNAL)] = "BPF loader internal error",
342 [ERRCODE_OFFSET(COMPILE)] = "Error when compiling BPF scriptlet",
343};
344
345static int
346bpf_loader_strerror(int err, char *buf, size_t size)
347{
348 char sbuf[STRERR_BUFSIZE];
349 const char *msg;
350
351 if (!buf || !size)
352 return -1;
353
354 err = err > 0 ? err : -err;
355
356 if (err >= __LIBBPF_ERRNO__START)
357 return libbpf_strerror(err, buf, size);
358
359 if (err >= __BPF_LOADER_ERRNO__START && err < __BPF_LOADER_ERRNO__END) {
360 msg = bpf_loader_strerror_table[ERRNO_OFFSET(err)];
361 snprintf(buf, size, "%s", msg);
362 buf[size - 1] = '\0';
363 return 0;
364 }
365
366 if (err >= __BPF_LOADER_ERRNO__END)
367 snprintf(buf, size, "Unknown bpf loader error %d", err);
368 else
369 snprintf(buf, size, "%s",
370 strerror_r(err, sbuf, sizeof(sbuf)));
371
372 buf[size - 1] = '\0';
373 return -1;
374}
375
376#define bpf__strerror_head(err, buf, size) \
377 char sbuf[STRERR_BUFSIZE], *emsg;\
378 if (!size)\
379 return 0;\
380 if (err < 0)\
381 err = -err;\
382 bpf_loader_strerror(err, sbuf, sizeof(sbuf));\
383 emsg = sbuf;\
384 switch (err) {\
385 default:\
386 scnprintf(buf, size, "%s", emsg);\
387 break;
388
389#define bpf__strerror_entry(val, fmt...)\
390 case val: {\
391 scnprintf(buf, size, fmt);\
392 break;\
393 }
394
395#define bpf__strerror_end(buf, size)\
396 }\
397 buf[size - 1] = '\0';
398
399int bpf__strerror_prepare_load(const char *filename, bool source,
400 int err, char *buf, size_t size)
401{
402 size_t n;
403 int ret;
404
405 n = snprintf(buf, size, "Failed to load %s%s: ",
406 filename, source ? " from source" : "");
407 if (n >= size) {
408 buf[size - 1] = '\0';
409 return 0;
410 }
411 buf += n;
412 size -= n;
413
414 ret = bpf_loader_strerror(err, buf, size);
415 buf[size - 1] = '\0';
416 return ret;
417}
418
419int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
420 int err, char *buf, size_t size)
421{
422 bpf__strerror_head(err, buf, size);
423 bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'");
424 bpf__strerror_entry(EACCES, "You need to be root");
425 bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0");
426 bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file");
427 bpf__strerror_end(buf, size);
428 return 0;
429}
430
431int bpf__strerror_load(struct bpf_object *obj,
432 int err, char *buf, size_t size)
433{
434 bpf__strerror_head(err, buf, size);
435 case LIBBPF_ERRNO__KVER: {
436 unsigned int obj_kver = bpf_object__get_kversion(obj);
437 unsigned int real_kver;
438
439 if (fetch_kernel_version(&real_kver, NULL, 0)) {
440 scnprintf(buf, size, "Unable to fetch kernel version");
441 break;
442 }
443
444 if (obj_kver != real_kver) {
445 scnprintf(buf, size,
446 "'version' ("KVER_FMT") doesn't match running kernel ("KVER_FMT")",
447 KVER_PARAM(obj_kver),
448 KVER_PARAM(real_kver));
449 break;
450 }
451
452 scnprintf(buf, size, "Failed to load program for unknown reason");
453 break;
454 }
455 bpf__strerror_end(buf, size);
456 return 0;
457}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
new file mode 100644
index 000000000000..9caf3ae4acf3
--- /dev/null
+++ b/tools/perf/util/bpf-loader.h
@@ -0,0 +1,118 @@
1/*
2 * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com>
3 * Copyright (C) 2015, Huawei Inc.
4 */
5#ifndef __BPF_LOADER_H
6#define __BPF_LOADER_H
7
8#include <linux/compiler.h>
9#include <linux/err.h>
10#include <string.h>
11#include <bpf/libbpf.h>
12#include "probe-event.h"
13#include "debug.h"
14
15enum bpf_loader_errno {
16 __BPF_LOADER_ERRNO__START = __LIBBPF_ERRNO__START - 100,
17 /* Invalid config string */
18 BPF_LOADER_ERRNO__CONFIG = __BPF_LOADER_ERRNO__START,
19 BPF_LOADER_ERRNO__GROUP, /* Invalid group name */
20 BPF_LOADER_ERRNO__EVENTNAME, /* Event name is missing */
21 BPF_LOADER_ERRNO__INTERNAL, /* BPF loader internal error */
22 BPF_LOADER_ERRNO__COMPILE, /* Error when compiling BPF scriptlet */
23 __BPF_LOADER_ERRNO__END,
24};
25
26struct bpf_object;
27#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
28
29typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
30 int fd, void *arg);
31
32#ifdef HAVE_LIBBPF_SUPPORT
33struct bpf_object *bpf__prepare_load(const char *filename, bool source);
34int bpf__strerror_prepare_load(const char *filename, bool source,
35 int err, char *buf, size_t size);
36
37struct bpf_object *bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz,
38 const char *name);
39
40void bpf__clear(void);
41
42int bpf__probe(struct bpf_object *obj);
43int bpf__unprobe(struct bpf_object *obj);
44int bpf__strerror_probe(struct bpf_object *obj, int err,
45 char *buf, size_t size);
46
47int bpf__load(struct bpf_object *obj);
48int bpf__strerror_load(struct bpf_object *obj, int err,
49 char *buf, size_t size);
50int bpf__foreach_tev(struct bpf_object *obj,
51 bpf_prog_iter_callback_t func, void *arg);
52#else
53static inline struct bpf_object *
54bpf__prepare_load(const char *filename __maybe_unused,
55 bool source __maybe_unused)
56{
57 pr_debug("ERROR: eBPF object loading is disabled during compiling.\n");
58 return ERR_PTR(-ENOTSUP);
59}
60
61static inline struct bpf_object *
62bpf__prepare_load_buffer(void *obj_buf __maybe_unused,
63 size_t obj_buf_sz __maybe_unused)
64{
65 return ERR_PTR(-ENOTSUP);
66}
67
68static inline void bpf__clear(void) { }
69
70static inline int bpf__probe(struct bpf_object *obj __maybe_unused) { return 0;}
71static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0;}
72static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; }
73
74static inline int
75bpf__foreach_tev(struct bpf_object *obj __maybe_unused,
76 bpf_prog_iter_callback_t func __maybe_unused,
77 void *arg __maybe_unused)
78{
79 return 0;
80}
81
82static inline int
83__bpf_strerror(char *buf, size_t size)
84{
85 if (!size)
86 return 0;
87 strncpy(buf,
88 "ERROR: eBPF object loading is disabled during compiling.\n",
89 size);
90 buf[size - 1] = '\0';
91 return 0;
92}
93
94static inline
95int bpf__strerror_prepare_load(const char *filename __maybe_unused,
96 bool source __maybe_unused,
97 int err __maybe_unused,
98 char *buf, size_t size)
99{
100 return __bpf_strerror(buf, size);
101}
102
103static inline int
104bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
105 int err __maybe_unused,
106 char *buf, size_t size)
107{
108 return __bpf_strerror(buf, size);
109}
110
111static inline int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
112 int err __maybe_unused,
113 char *buf, size_t size)
114{
115 return __bpf_strerror(buf, size);
116}
117#endif
118#endif
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index d909459fb54c..217b5a60e2ab 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -76,6 +76,7 @@ struct perf_tool build_id__mark_dso_hit_ops = {
76 .exit = perf_event__exit_del_thread, 76 .exit = perf_event__exit_del_thread,
77 .attr = perf_event__process_attr, 77 .attr = perf_event__process_attr,
78 .build_id = perf_event__process_build_id, 78 .build_id = perf_event__process_build_id,
79 .ordered_events = true,
79}; 80};
80 81
81int build_id__sprintf(const u8 *build_id, int len, char *bf) 82int build_id__sprintf(const u8 *build_id, int len, char *bf)
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 773fe13ce627..735ad48e1858 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -51,10 +51,12 @@ static int parse_callchain_order(const char *value)
51{ 51{
52 if (!strncmp(value, "caller", strlen(value))) { 52 if (!strncmp(value, "caller", strlen(value))) {
53 callchain_param.order = ORDER_CALLER; 53 callchain_param.order = ORDER_CALLER;
54 callchain_param.order_set = true;
54 return 0; 55 return 0;
55 } 56 }
56 if (!strncmp(value, "callee", strlen(value))) { 57 if (!strncmp(value, "callee", strlen(value))) {
57 callchain_param.order = ORDER_CALLEE; 58 callchain_param.order = ORDER_CALLEE;
59 callchain_param.order_set = true;
58 return 0; 60 return 0;
59 } 61 }
60 return -1; 62 return -1;
@@ -77,12 +79,14 @@ static int parse_callchain_sort_key(const char *value)
77 return -1; 79 return -1;
78} 80}
79 81
80int 82static int
81parse_callchain_report_opt(const char *arg) 83__parse_callchain_report_opt(const char *arg, bool allow_record_opt)
82{ 84{
83 char *tok; 85 char *tok;
84 char *endptr; 86 char *endptr;
85 bool minpcnt_set = false; 87 bool minpcnt_set = false;
88 bool record_opt_set = false;
89 bool try_stack_size = false;
86 90
87 symbol_conf.use_callchain = true; 91 symbol_conf.use_callchain = true;
88 92
@@ -100,6 +104,28 @@ parse_callchain_report_opt(const char *arg)
100 !parse_callchain_order(tok) || 104 !parse_callchain_order(tok) ||
101 !parse_callchain_sort_key(tok)) { 105 !parse_callchain_sort_key(tok)) {
102 /* parsing ok - move on to the next */ 106 /* parsing ok - move on to the next */
107 try_stack_size = false;
108 goto next;
109 } else if (allow_record_opt && !record_opt_set) {
110 if (parse_callchain_record(tok, &callchain_param))
111 goto try_numbers;
112
113 /* assume that number followed by 'dwarf' is stack size */
114 if (callchain_param.record_mode == CALLCHAIN_DWARF)
115 try_stack_size = true;
116
117 record_opt_set = true;
118 goto next;
119 }
120
121try_numbers:
122 if (try_stack_size) {
123 unsigned long size = 0;
124
125 if (get_stack_size(tok, &size) < 0)
126 return -1;
127 callchain_param.dump_size = size;
128 try_stack_size = false;
103 } else if (!minpcnt_set) { 129 } else if (!minpcnt_set) {
104 /* try to get the min percent */ 130 /* try to get the min percent */
105 callchain_param.min_percent = strtod(tok, &endptr); 131 callchain_param.min_percent = strtod(tok, &endptr);
@@ -112,7 +138,7 @@ parse_callchain_report_opt(const char *arg)
112 if (tok == endptr) 138 if (tok == endptr)
113 return -1; 139 return -1;
114 } 140 }
115 141next:
116 arg = NULL; 142 arg = NULL;
117 } 143 }
118 144
@@ -123,6 +149,16 @@ parse_callchain_report_opt(const char *arg)
123 return 0; 149 return 0;
124} 150}
125 151
152int parse_callchain_report_opt(const char *arg)
153{
154 return __parse_callchain_report_opt(arg, false);
155}
156
157int parse_callchain_top_opt(const char *arg)
158{
159 return __parse_callchain_report_opt(arg, true);
160}
161
126int perf_callchain_config(const char *var, const char *value) 162int perf_callchain_config(const char *var, const char *value)
127{ 163{
128 char *endptr; 164 char *endptr;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index acee2b3cd801..fce8161e54db 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -7,6 +7,30 @@
7#include "event.h" 7#include "event.h"
8#include "symbol.h" 8#include "symbol.h"
9 9
10#define HELP_PAD "\t\t\t\t"
11
12#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n"
13
14#ifdef HAVE_DWARF_UNWIND_SUPPORT
15# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n"
16#else
17# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|lbr)\n"
18#endif
19
20#define RECORD_SIZE_HELP \
21 HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \
22 HELP_PAD "\t\tdefault: 8192 (bytes)\n"
23
24#define CALLCHAIN_RECORD_HELP CALLCHAIN_HELP RECORD_MODE_HELP RECORD_SIZE_HELP
25
26#define CALLCHAIN_REPORT_HELP \
27 HELP_PAD "print_type:\tcall graph printing style (graph|flat|fractal|none)\n" \
28 HELP_PAD "threshold:\tminimum call graph inclusion threshold (<percent>)\n" \
29 HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \
30 HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \
31 HELP_PAD "sort_key:\tcall graph sort key (function|address)\n" \
32 HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n"
33
10enum perf_call_graph_mode { 34enum perf_call_graph_mode {
11 CALLCHAIN_NONE, 35 CALLCHAIN_NONE,
12 CALLCHAIN_FP, 36 CALLCHAIN_FP,
@@ -63,6 +87,7 @@ struct callchain_param {
63 double min_percent; 87 double min_percent;
64 sort_chain_func_t sort; 88 sort_chain_func_t sort;
65 enum chain_order order; 89 enum chain_order order;
90 bool order_set;
66 enum chain_key key; 91 enum chain_key key;
67 bool branch_callstack; 92 bool branch_callstack;
68}; 93};
@@ -180,6 +205,7 @@ extern const char record_callchain_help[];
180extern int parse_callchain_record(const char *arg, struct callchain_param *param); 205extern int parse_callchain_record(const char *arg, struct callchain_param *param);
181int parse_callchain_record_opt(const char *arg, struct callchain_param *param); 206int parse_callchain_record_opt(const char *arg, struct callchain_param *param);
182int parse_callchain_report_opt(const char *arg); 207int parse_callchain_report_opt(const char *arg);
208int parse_callchain_top_opt(const char *arg);
183int perf_callchain_config(const char *var, const char *value); 209int perf_callchain_config(const char *var, const char *value);
184 210
185static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, 211static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 3667e2123e5b..10af1e7524fb 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -203,6 +203,23 @@ struct cpu_map *cpu_map__dummy_new(void)
203 return cpus; 203 return cpus;
204} 204}
205 205
206struct cpu_map *cpu_map__empty_new(int nr)
207{
208 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr);
209
210 if (cpus != NULL) {
211 int i;
212
213 cpus->nr = nr;
214 for (i = 0; i < nr; i++)
215 cpus->map[i] = -1;
216
217 atomic_set(&cpus->refcnt, 1);
218 }
219
220 return cpus;
221}
222
206static void cpu_map__delete(struct cpu_map *map) 223static void cpu_map__delete(struct cpu_map *map)
207{ 224{
208 if (map) { 225 if (map) {
@@ -225,32 +242,32 @@ void cpu_map__put(struct cpu_map *map)
225 cpu_map__delete(map); 242 cpu_map__delete(map);
226} 243}
227 244
228int cpu_map__get_socket(struct cpu_map *map, int idx) 245static int cpu__get_topology_int(int cpu, const char *name, int *value)
229{ 246{
230 FILE *fp;
231 const char *mnt;
232 char path[PATH_MAX]; 247 char path[PATH_MAX];
233 int cpu, ret;
234 248
235 if (idx > map->nr) 249 snprintf(path, PATH_MAX,
236 return -1; 250 "devices/system/cpu/cpu%d/topology/%s", cpu, name);
237 251
238 cpu = map->map[idx]; 252 return sysfs__read_int(path, value);
253}
239 254
240 mnt = sysfs__mountpoint(); 255int cpu_map__get_socket_id(int cpu)
241 if (!mnt) 256{
242 return -1; 257 int value, ret = cpu__get_topology_int(cpu, "physical_package_id", &value);
258 return ret ?: value;
259}
243 260
244 snprintf(path, PATH_MAX, 261int cpu_map__get_socket(struct cpu_map *map, int idx, void *data __maybe_unused)
245 "%s/devices/system/cpu/cpu%d/topology/physical_package_id", 262{
246 mnt, cpu); 263 int cpu;
247 264
248 fp = fopen(path, "r"); 265 if (idx > map->nr)
249 if (!fp)
250 return -1; 266 return -1;
251 ret = fscanf(fp, "%d", &cpu); 267
252 fclose(fp); 268 cpu = map->map[idx];
253 return ret == 1 ? cpu : -1; 269
270 return cpu_map__get_socket_id(cpu);
254} 271}
255 272
256static int cmp_ids(const void *a, const void *b) 273static int cmp_ids(const void *a, const void *b)
@@ -258,8 +275,9 @@ static int cmp_ids(const void *a, const void *b)
258 return *(int *)a - *(int *)b; 275 return *(int *)a - *(int *)b;
259} 276}
260 277
261static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, 278int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
262 int (*f)(struct cpu_map *map, int cpu)) 279 int (*f)(struct cpu_map *map, int cpu, void *data),
280 void *data)
263{ 281{
264 struct cpu_map *c; 282 struct cpu_map *c;
265 int nr = cpus->nr; 283 int nr = cpus->nr;
@@ -271,7 +289,7 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
271 return -1; 289 return -1;
272 290
273 for (cpu = 0; cpu < nr; cpu++) { 291 for (cpu = 0; cpu < nr; cpu++) {
274 s1 = f(cpus, cpu); 292 s1 = f(cpus, cpu, data);
275 for (s2 = 0; s2 < c->nr; s2++) { 293 for (s2 = 0; s2 < c->nr; s2++) {
276 if (s1 == c->map[s2]) 294 if (s1 == c->map[s2])
277 break; 295 break;
@@ -284,40 +302,29 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
284 /* ensure we process id in increasing order */ 302 /* ensure we process id in increasing order */
285 qsort(c->map, c->nr, sizeof(int), cmp_ids); 303 qsort(c->map, c->nr, sizeof(int), cmp_ids);
286 304
287 atomic_set(&cpus->refcnt, 1); 305 atomic_set(&c->refcnt, 1);
288 *res = c; 306 *res = c;
289 return 0; 307 return 0;
290} 308}
291 309
292int cpu_map__get_core(struct cpu_map *map, int idx) 310int cpu_map__get_core_id(int cpu)
293{ 311{
294 FILE *fp; 312 int value, ret = cpu__get_topology_int(cpu, "core_id", &value);
295 const char *mnt; 313 return ret ?: value;
296 char path[PATH_MAX]; 314}
297 int cpu, ret, s; 315
316int cpu_map__get_core(struct cpu_map *map, int idx, void *data)
317{
318 int cpu, s;
298 319
299 if (idx > map->nr) 320 if (idx > map->nr)
300 return -1; 321 return -1;
301 322
302 cpu = map->map[idx]; 323 cpu = map->map[idx];
303 324
304 mnt = sysfs__mountpoint(); 325 cpu = cpu_map__get_core_id(cpu);
305 if (!mnt)
306 return -1;
307
308 snprintf(path, PATH_MAX,
309 "%s/devices/system/cpu/cpu%d/topology/core_id",
310 mnt, cpu);
311
312 fp = fopen(path, "r");
313 if (!fp)
314 return -1;
315 ret = fscanf(fp, "%d", &cpu);
316 fclose(fp);
317 if (ret != 1)
318 return -1;
319 326
320 s = cpu_map__get_socket(map, idx); 327 s = cpu_map__get_socket(map, idx, data);
321 if (s == -1) 328 if (s == -1)
322 return -1; 329 return -1;
323 330
@@ -332,12 +339,12 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
332 339
333int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp) 340int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp)
334{ 341{
335 return cpu_map__build_map(cpus, sockp, cpu_map__get_socket); 342 return cpu_map__build_map(cpus, sockp, cpu_map__get_socket, NULL);
336} 343}
337 344
338int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep) 345int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep)
339{ 346{
340 return cpu_map__build_map(cpus, corep, cpu_map__get_core); 347 return cpu_map__build_map(cpus, corep, cpu_map__get_core, NULL);
341} 348}
342 349
343/* setup simple routines to easily access node numbers given a cpu number */ 350/* setup simple routines to easily access node numbers given a cpu number */
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 0af9cecb4c51..85f7772457fa 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -15,11 +15,14 @@ struct cpu_map {
15}; 15};
16 16
17struct cpu_map *cpu_map__new(const char *cpu_list); 17struct cpu_map *cpu_map__new(const char *cpu_list);
18struct cpu_map *cpu_map__empty_new(int nr);
18struct cpu_map *cpu_map__dummy_new(void); 19struct cpu_map *cpu_map__dummy_new(void);
19struct cpu_map *cpu_map__read(FILE *file); 20struct cpu_map *cpu_map__read(FILE *file);
20size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); 21size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
21int cpu_map__get_socket(struct cpu_map *map, int idx); 22int cpu_map__get_socket_id(int cpu);
22int cpu_map__get_core(struct cpu_map *map, int idx); 23int cpu_map__get_socket(struct cpu_map *map, int idx, void *data);
24int cpu_map__get_core_id(int cpu);
25int cpu_map__get_core(struct cpu_map *map, int idx, void *data);
23int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp); 26int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp);
24int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep); 27int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep);
25 28
@@ -85,4 +88,7 @@ static inline int cpu__get_node(int cpu)
85 return cpunode_map[cpu]; 88 return cpunode_map[cpu];
86} 89}
87 90
91int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
92 int (*f)(struct cpu_map *map, int cpu, void *data),
93 void *data);
88#endif /* __PERF_CPUMAP_H */ 94#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 7c0c08386a1d..425df5c86c9c 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -933,6 +933,7 @@ static struct dso *__dso__findlink_by_longname(struct rb_root *root,
933 /* Add new node and rebalance tree */ 933 /* Add new node and rebalance tree */
934 rb_link_node(&dso->rb_node, parent, p); 934 rb_link_node(&dso->rb_node, parent, p);
935 rb_insert_color(&dso->rb_node, root); 935 rb_insert_color(&dso->rb_node, root);
936 dso->root = root;
936 } 937 }
937 return NULL; 938 return NULL;
938} 939}
@@ -945,15 +946,30 @@ static inline struct dso *__dso__find_by_longname(struct rb_root *root,
945 946
946void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) 947void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
947{ 948{
949 struct rb_root *root = dso->root;
950
948 if (name == NULL) 951 if (name == NULL)
949 return; 952 return;
950 953
951 if (dso->long_name_allocated) 954 if (dso->long_name_allocated)
952 free((char *)dso->long_name); 955 free((char *)dso->long_name);
953 956
957 if (root) {
958 rb_erase(&dso->rb_node, root);
959 /*
960 * __dso__findlink_by_longname() isn't guaranteed to add it
961 * back, so a clean removal is required here.
962 */
963 RB_CLEAR_NODE(&dso->rb_node);
964 dso->root = NULL;
965 }
966
954 dso->long_name = name; 967 dso->long_name = name;
955 dso->long_name_len = strlen(name); 968 dso->long_name_len = strlen(name);
956 dso->long_name_allocated = name_allocated; 969 dso->long_name_allocated = name_allocated;
970
971 if (root)
972 __dso__findlink_by_longname(root, dso, NULL);
957} 973}
958 974
959void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated) 975void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
@@ -1046,6 +1062,7 @@ struct dso *dso__new(const char *name)
1046 dso->kernel = DSO_TYPE_USER; 1062 dso->kernel = DSO_TYPE_USER;
1047 dso->needs_swap = DSO_SWAP__UNSET; 1063 dso->needs_swap = DSO_SWAP__UNSET;
1048 RB_CLEAR_NODE(&dso->rb_node); 1064 RB_CLEAR_NODE(&dso->rb_node);
1065 dso->root = NULL;
1049 INIT_LIST_HEAD(&dso->node); 1066 INIT_LIST_HEAD(&dso->node);
1050 INIT_LIST_HEAD(&dso->data.open_entry); 1067 INIT_LIST_HEAD(&dso->data.open_entry);
1051 pthread_mutex_init(&dso->lock, NULL); 1068 pthread_mutex_init(&dso->lock, NULL);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index fc8db9c764ac..45ec4d0a50ed 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -135,6 +135,7 @@ struct dso {
135 pthread_mutex_t lock; 135 pthread_mutex_t lock;
136 struct list_head node; 136 struct list_head node;
137 struct rb_node rb_node; /* rbtree node sorted by long name */ 137 struct rb_node rb_node; /* rbtree node sorted by long name */
138 struct rb_root *root; /* root of rbtree that rb_node is in */
138 struct rb_root symbols[MAP__NR_TYPES]; 139 struct rb_root symbols[MAP__NR_TYPES];
139 struct rb_root symbol_names[MAP__NR_TYPES]; 140 struct rb_root symbol_names[MAP__NR_TYPES];
140 struct { 141 struct {
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
new file mode 100644
index 000000000000..6af4f7c36820
--- /dev/null
+++ b/tools/perf/util/env.c
@@ -0,0 +1,86 @@
1#include "cpumap.h"
2#include "env.h"
3#include "util.h"
4
5struct perf_env perf_env;
6
7void perf_env__exit(struct perf_env *env)
8{
9 zfree(&env->hostname);
10 zfree(&env->os_release);
11 zfree(&env->version);
12 zfree(&env->arch);
13 zfree(&env->cpu_desc);
14 zfree(&env->cpuid);
15 zfree(&env->cmdline);
16 zfree(&env->cmdline_argv);
17 zfree(&env->sibling_cores);
18 zfree(&env->sibling_threads);
19 zfree(&env->numa_nodes);
20 zfree(&env->pmu_mappings);
21 zfree(&env->cpu);
22}
23
24int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
25{
26 int i;
27
28 /*
29 * If env->cmdline_argv has already been set, do not override it. This allows
30 * a command to set the cmdline, parse args and then call another
31 * builtin function that implements a command -- e.g, cmd_kvm calling
32 * cmd_record.
33 */
34 if (env->cmdline_argv != NULL)
35 return 0;
36
37 /* do not include NULL termination */
38 env->cmdline_argv = calloc(argc, sizeof(char *));
39 if (env->cmdline_argv == NULL)
40 goto out_enomem;
41
42 /*
43 * Must copy argv contents because it gets moved around during option
44 * parsing:
45 */
46 for (i = 0; i < argc ; i++) {
47 env->cmdline_argv[i] = argv[i];
48 if (env->cmdline_argv[i] == NULL)
49 goto out_free;
50 }
51
52 env->nr_cmdline = argc;
53
54 return 0;
55out_free:
56 zfree(&env->cmdline_argv);
57out_enomem:
58 return -ENOMEM;
59}
60
61int perf_env__read_cpu_topology_map(struct perf_env *env)
62{
63 int cpu, nr_cpus;
64
65 if (env->cpu != NULL)
66 return 0;
67
68 if (env->nr_cpus_avail == 0)
69 env->nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
70
71 nr_cpus = env->nr_cpus_avail;
72 if (nr_cpus == -1)
73 return -EINVAL;
74
75 env->cpu = calloc(nr_cpus, sizeof(env->cpu[0]));
76 if (env->cpu == NULL)
77 return -ENOMEM;
78
79 for (cpu = 0; cpu < nr_cpus; ++cpu) {
80 env->cpu[cpu].core_id = cpu_map__get_core_id(cpu);
81 env->cpu[cpu].socket_id = cpu_map__get_socket_id(cpu);
82 }
83
84 env->nr_cpus_avail = nr_cpus;
85 return 0;
86}
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
new file mode 100644
index 000000000000..0132b9557c02
--- /dev/null
+++ b/tools/perf/util/env.h
@@ -0,0 +1,44 @@
1#ifndef __PERF_ENV_H
2#define __PERF_ENV_H
3
4struct cpu_topology_map {
5 int socket_id;
6 int core_id;
7};
8
9struct perf_env {
10 char *hostname;
11 char *os_release;
12 char *version;
13 char *arch;
14 int nr_cpus_online;
15 int nr_cpus_avail;
16 char *cpu_desc;
17 char *cpuid;
18 unsigned long long total_mem;
19 unsigned int msr_pmu_type;
20
21 int nr_cmdline;
22 int nr_sibling_cores;
23 int nr_sibling_threads;
24 int nr_numa_nodes;
25 int nr_pmu_mappings;
26 int nr_groups;
27 char *cmdline;
28 const char **cmdline_argv;
29 char *sibling_cores;
30 char *sibling_threads;
31 char *numa_nodes;
32 char *pmu_mappings;
33 struct cpu_topology_map *cpu;
34};
35
36extern struct perf_env perf_env;
37
38void perf_env__exit(struct perf_env *env);
39
40int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]);
41
42int perf_env__read_cpu_topology_map(struct perf_env *env);
43
44#endif /* __PERF_ENV_H */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 7ff61274ed57..8b10621b415c 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -67,7 +67,8 @@ static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
67 char filename[PATH_MAX]; 67 char filename[PATH_MAX];
68 char bf[4096]; 68 char bf[4096];
69 int fd; 69 int fd;
70 size_t size = 0, n; 70 size_t size = 0;
71 ssize_t n;
71 char *nl, *name, *tgids, *ppids; 72 char *nl, *name, *tgids, *ppids;
72 73
73 *tgid = -1; 74 *tgid = -1;
@@ -167,7 +168,7 @@ static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
167 return 0; 168 return 0;
168} 169}
169 170
170static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 171pid_t perf_event__synthesize_comm(struct perf_tool *tool,
171 union perf_event *event, pid_t pid, 172 union perf_event *event, pid_t pid,
172 perf_event__handler_t process, 173 perf_event__handler_t process,
173 struct machine *machine) 174 struct machine *machine)
@@ -378,7 +379,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
378 for (pos = maps__first(maps); pos; pos = map__next(pos)) { 379 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
379 size_t size; 380 size_t size;
380 381
381 if (pos->dso->kernel) 382 if (__map__is_kernel(pos))
382 continue; 383 continue;
383 384
384 size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 385 size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
@@ -649,12 +650,12 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
649 size_t size; 650 size_t size;
650 const char *mmap_name; 651 const char *mmap_name;
651 char name_buff[PATH_MAX]; 652 char name_buff[PATH_MAX];
652 struct map *map; 653 struct map *map = machine__kernel_map(machine);
653 struct kmap *kmap; 654 struct kmap *kmap;
654 int err; 655 int err;
655 union perf_event *event; 656 union perf_event *event;
656 657
657 if (machine->vmlinux_maps[0] == NULL) 658 if (map == NULL)
658 return -1; 659 return -1;
659 660
660 /* 661 /*
@@ -680,7 +681,6 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
680 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 681 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
681 } 682 }
682 683
683 map = machine->vmlinux_maps[MAP__FUNCTION];
684 kmap = map__kmap(map); 684 kmap = map__kmap(map);
685 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 685 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
686 "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; 686 "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1;
@@ -1008,7 +1008,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
1008 * it now. 1008 * it now.
1009 */ 1009 */
1010 if (cpumode == PERF_RECORD_MISC_KERNEL && 1010 if (cpumode == PERF_RECORD_MISC_KERNEL &&
1011 machine->vmlinux_maps[MAP__FUNCTION] == NULL) 1011 machine__kernel_map(machine) == NULL)
1012 machine__create_kernel_maps(machine); 1012 machine__create_kernel_maps(machine);
1013 1013
1014 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al); 1014 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al);
@@ -1021,6 +1021,14 @@ int perf_event__preprocess_sample(const union perf_event *event,
1021 1021
1022 al->sym = NULL; 1022 al->sym = NULL;
1023 al->cpu = sample->cpu; 1023 al->cpu = sample->cpu;
1024 al->socket = -1;
1025
1026 if (al->cpu >= 0) {
1027 struct perf_env *env = machine->env;
1028
1029 if (env && env->cpu)
1030 al->socket = env->cpu[al->cpu].socket_id;
1031 }
1024 1032
1025 if (al->map) { 1033 if (al->map) {
1026 struct dso *dso = al->map->dso; 1034 struct dso *dso = al->map->dso;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index f729df5e25e6..a0dbcbd4f6d8 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -257,6 +257,7 @@ struct events_stats {
257 u64 total_non_filtered_period; 257 u64 total_non_filtered_period;
258 u64 total_lost; 258 u64 total_lost;
259 u64 total_lost_samples; 259 u64 total_lost_samples;
260 u64 total_aux_lost;
260 u64 total_invalid_chains; 261 u64 total_invalid_chains;
261 u32 nr_events[PERF_RECORD_HEADER_MAX]; 262 u32 nr_events[PERF_RECORD_HEADER_MAX];
262 u32 nr_non_filtered_samples; 263 u32 nr_non_filtered_samples;
@@ -478,6 +479,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
478 const struct perf_sample *sample, 479 const struct perf_sample *sample,
479 bool swapped); 480 bool swapped);
480 481
482pid_t perf_event__synthesize_comm(struct perf_tool *tool,
483 union perf_event *event, pid_t pid,
484 perf_event__handler_t process,
485 struct machine *machine);
486
481int perf_event__synthesize_mmap_events(struct perf_tool *tool, 487int perf_event__synthesize_mmap_events(struct perf_tool *tool,
482 union perf_event *event, 488 union perf_event *event,
483 pid_t pid, pid_t tgid, 489 pid_t pid, pid_t tgid,
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index c8fc8a258f42..d1392194a9a9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,6 +25,7 @@
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26#include <linux/hash.h> 26#include <linux/hash.h>
27#include <linux/log2.h> 27#include <linux/log2.h>
28#include <linux/err.h>
28 29
29static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); 30static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
30static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); 31static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
@@ -164,6 +165,13 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
164 __perf_evlist__propagate_maps(evlist, entry); 165 __perf_evlist__propagate_maps(evlist, entry);
165} 166}
166 167
168void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel)
169{
170 evsel->evlist = NULL;
171 list_del_init(&evsel->node);
172 evlist->nr_entries -= 1;
173}
174
167void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 175void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
168 struct list_head *list) 176 struct list_head *list)
169{ 177{
@@ -197,6 +205,20 @@ void perf_evlist__set_leader(struct perf_evlist *evlist)
197 } 205 }
198} 206}
199 207
208void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
209{
210 attr->precise_ip = 3;
211
212 while (attr->precise_ip != 0) {
213 int fd = sys_perf_event_open(attr, 0, -1, -1, 0);
214 if (fd != -1) {
215 close(fd);
216 break;
217 }
218 --attr->precise_ip;
219 }
220}
221
200int perf_evlist__add_default(struct perf_evlist *evlist) 222int perf_evlist__add_default(struct perf_evlist *evlist)
201{ 223{
202 struct perf_event_attr attr = { 224 struct perf_event_attr attr = {
@@ -207,13 +229,15 @@ int perf_evlist__add_default(struct perf_evlist *evlist)
207 229
208 event_attr_init(&attr); 230 event_attr_init(&attr);
209 231
232 perf_event_attr__set_max_precise_ip(&attr);
233
210 evsel = perf_evsel__new(&attr); 234 evsel = perf_evsel__new(&attr);
211 if (evsel == NULL) 235 if (evsel == NULL)
212 goto error; 236 goto error;
213 237
214 /* use strdup() because free(evsel) assumes name is allocated */ 238 /* use asprintf() because free(evsel) assumes name is allocated */
215 evsel->name = strdup("cycles"); 239 if (asprintf(&evsel->name, "cycles%.*s",
216 if (!evsel->name) 240 attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0)
217 goto error_free; 241 goto error_free;
218 242
219 perf_evlist__add(evlist, evsel); 243 perf_evlist__add(evlist, evsel);
@@ -293,7 +317,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
293{ 317{
294 struct perf_evsel *evsel = perf_evsel__newtp(sys, name); 318 struct perf_evsel *evsel = perf_evsel__newtp(sys, name);
295 319
296 if (evsel == NULL) 320 if (IS_ERR(evsel))
297 return -1; 321 return -1;
298 322
299 evsel->handler = handler; 323 evsel->handler = handler;
@@ -616,6 +640,21 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
616 return NULL; 640 return NULL;
617} 641}
618 642
643struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
644 u64 id)
645{
646 struct perf_sample_id *sid;
647
648 if (!id)
649 return NULL;
650
651 sid = perf_evlist__id2sid(evlist, id);
652 if (sid)
653 return sid->evsel;
654
655 return NULL;
656}
657
619static int perf_evlist__event2id(struct perf_evlist *evlist, 658static int perf_evlist__event2id(struct perf_evlist *evlist,
620 union perf_event *event, u64 *id) 659 union perf_event *event, u64 *id)
621{ 660{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 115d8b53c601..a459fe71b452 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -73,6 +73,7 @@ void perf_evlist__exit(struct perf_evlist *evlist);
73void perf_evlist__delete(struct perf_evlist *evlist); 73void perf_evlist__delete(struct perf_evlist *evlist);
74 74
75void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 75void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
76void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel);
76int perf_evlist__add_default(struct perf_evlist *evlist); 77int perf_evlist__add_default(struct perf_evlist *evlist);
77int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 78int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
78 struct perf_event_attr *attrs, size_t nr_attrs); 79 struct perf_event_attr *attrs, size_t nr_attrs);
@@ -104,6 +105,8 @@ int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mas
104int perf_evlist__poll(struct perf_evlist *evlist, int timeout); 105int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
105 106
106struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 107struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
108struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
109 u64 id);
107 110
108struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); 111struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
109 112
@@ -287,4 +290,6 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
287 290
288void perf_evlist__set_tracking_event(struct perf_evlist *evlist, 291void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
289 struct perf_evsel *tracking_evsel); 292 struct perf_evsel *tracking_evsel);
293
294void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr);
290#endif /* __PERF_EVLIST_H */ 295#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 5410483d5219..397fb4ed3c97 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -9,10 +9,11 @@
9 9
10#include <byteswap.h> 10#include <byteswap.h>
11#include <linux/bitops.h> 11#include <linux/bitops.h>
12#include <api/fs/debugfs.h> 12#include <api/fs/tracing_path.h>
13#include <traceevent/event-parse.h> 13#include <traceevent/event-parse.h>
14#include <linux/hw_breakpoint.h> 14#include <linux/hw_breakpoint.h>
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
16#include <linux/err.h>
16#include <sys/resource.h> 17#include <sys/resource.h>
17#include "asm/bug.h" 18#include "asm/bug.h"
18#include "callchain.h" 19#include "callchain.h"
@@ -207,6 +208,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
207 evsel->unit = ""; 208 evsel->unit = "";
208 evsel->scale = 1.0; 209 evsel->scale = 1.0;
209 evsel->evlist = NULL; 210 evsel->evlist = NULL;
211 evsel->bpf_fd = -1;
210 INIT_LIST_HEAD(&evsel->node); 212 INIT_LIST_HEAD(&evsel->node);
211 INIT_LIST_HEAD(&evsel->config_terms); 213 INIT_LIST_HEAD(&evsel->config_terms);
212 perf_evsel__object.init(evsel); 214 perf_evsel__object.init(evsel);
@@ -225,11 +227,17 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
225 return evsel; 227 return evsel;
226} 228}
227 229
230/*
231 * Returns pointer with encoded error via <linux/err.h> interface.
232 */
228struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) 233struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
229{ 234{
230 struct perf_evsel *evsel = zalloc(perf_evsel__object.size); 235 struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
236 int err = -ENOMEM;
231 237
232 if (evsel != NULL) { 238 if (evsel == NULL) {
239 goto out_err;
240 } else {
233 struct perf_event_attr attr = { 241 struct perf_event_attr attr = {
234 .type = PERF_TYPE_TRACEPOINT, 242 .type = PERF_TYPE_TRACEPOINT,
235 .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | 243 .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
@@ -240,8 +248,10 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
240 goto out_free; 248 goto out_free;
241 249
242 evsel->tp_format = trace_event__tp_format(sys, name); 250 evsel->tp_format = trace_event__tp_format(sys, name);
243 if (evsel->tp_format == NULL) 251 if (IS_ERR(evsel->tp_format)) {
252 err = PTR_ERR(evsel->tp_format);
244 goto out_free; 253 goto out_free;
254 }
245 255
246 event_attr_init(&attr); 256 event_attr_init(&attr);
247 attr.config = evsel->tp_format->id; 257 attr.config = evsel->tp_format->id;
@@ -254,7 +264,8 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
254out_free: 264out_free:
255 zfree(&evsel->name); 265 zfree(&evsel->name);
256 free(evsel); 266 free(evsel);
257 return NULL; 267out_err:
268 return ERR_PTR(err);
258} 269}
259 270
260const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { 271const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
@@ -642,6 +653,15 @@ static void apply_config_terms(struct perf_evsel *evsel,
642 case PERF_EVSEL__CONFIG_TERM_STACK_USER: 653 case PERF_EVSEL__CONFIG_TERM_STACK_USER:
643 dump_size = term->val.stack_user; 654 dump_size = term->val.stack_user;
644 break; 655 break;
656 case PERF_EVSEL__CONFIG_TERM_INHERIT:
657 /*
658 * attr->inherit should has already been set by
659 * perf_evsel__config. If user explicitly set
660 * inherit using config terms, override global
661 * opt->no_inherit setting.
662 */
663 attr->inherit = term->val.inherit ? 1 : 0;
664 break;
645 default: 665 default:
646 break; 666 break;
647 } 667 }
@@ -872,6 +892,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
872 attr->clockid = opts->clockid; 892 attr->clockid = opts->clockid;
873 } 893 }
874 894
895 if (evsel->precise_max)
896 perf_event_attr__set_max_precise_ip(attr);
897
875 /* 898 /*
876 * Apply event specific term settings, 899 * Apply event specific term settings,
877 * it overloads any global configuration. 900 * it overloads any global configuration.
@@ -1168,7 +1191,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1168 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), 1191 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1169 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1192 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1170 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1193 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1171 bit_name(IDENTIFIER), bit_name(REGS_INTR), 1194 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
1172 { .name = NULL, } 1195 { .name = NULL, }
1173 }; 1196 };
1174#undef bit_name 1197#undef bit_name
@@ -1249,6 +1272,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1249 PRINT_ATTRf(bp_type, p_unsigned); 1272 PRINT_ATTRf(bp_type, p_unsigned);
1250 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); 1273 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
1251 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); 1274 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
1275 PRINT_ATTRf(branch_sample_type, p_unsigned);
1252 PRINT_ATTRf(sample_regs_user, p_hex); 1276 PRINT_ATTRf(sample_regs_user, p_hex);
1253 PRINT_ATTRf(sample_stack_user, p_unsigned); 1277 PRINT_ATTRf(sample_stack_user, p_unsigned);
1254 PRINT_ATTRf(clockid, p_signed); 1278 PRINT_ATTRf(clockid, p_signed);
@@ -1333,6 +1357,22 @@ retry_open:
1333 err); 1357 err);
1334 goto try_fallback; 1358 goto try_fallback;
1335 } 1359 }
1360
1361 if (evsel->bpf_fd >= 0) {
1362 int evt_fd = FD(evsel, cpu, thread);
1363 int bpf_fd = evsel->bpf_fd;
1364
1365 err = ioctl(evt_fd,
1366 PERF_EVENT_IOC_SET_BPF,
1367 bpf_fd);
1368 if (err && errno != EEXIST) {
1369 pr_err("failed to attach bpf fd %d: %s\n",
1370 bpf_fd, strerror(errno));
1371 err = -EINVAL;
1372 goto out_close;
1373 }
1374 }
1375
1336 set_rlimit = NO_CHANGE; 1376 set_rlimit = NO_CHANGE;
1337 1377
1338 /* 1378 /*
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index ef8925f7211a..0e49bd742c63 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -43,6 +43,7 @@ enum {
43 PERF_EVSEL__CONFIG_TERM_TIME, 43 PERF_EVSEL__CONFIG_TERM_TIME,
44 PERF_EVSEL__CONFIG_TERM_CALLGRAPH, 44 PERF_EVSEL__CONFIG_TERM_CALLGRAPH,
45 PERF_EVSEL__CONFIG_TERM_STACK_USER, 45 PERF_EVSEL__CONFIG_TERM_STACK_USER,
46 PERF_EVSEL__CONFIG_TERM_INHERIT,
46 PERF_EVSEL__CONFIG_TERM_MAX, 47 PERF_EVSEL__CONFIG_TERM_MAX,
47}; 48};
48 49
@@ -55,6 +56,7 @@ struct perf_evsel_config_term {
55 bool time; 56 bool time;
56 char *callgraph; 57 char *callgraph;
57 u64 stack_user; 58 u64 stack_user;
59 bool inherit;
58 } val; 60 } val;
59}; 61};
60 62
@@ -90,9 +92,9 @@ struct perf_evsel {
90 double scale; 92 double scale;
91 const char *unit; 93 const char *unit;
92 struct event_format *tp_format; 94 struct event_format *tp_format;
95 off_t id_offset;
93 union { 96 union {
94 void *priv; 97 void *priv;
95 off_t id_offset;
96 u64 db_id; 98 u64 db_id;
97 }; 99 };
98 struct cgroup_sel *cgrp; 100 struct cgroup_sel *cgrp;
@@ -111,6 +113,7 @@ struct perf_evsel {
111 bool system_wide; 113 bool system_wide;
112 bool tracking; 114 bool tracking;
113 bool per_pkg; 115 bool per_pkg;
116 bool precise_max;
114 /* parse modifier helper */ 117 /* parse modifier helper */
115 int exclude_GH; 118 int exclude_GH;
116 int nr_members; 119 int nr_members;
@@ -120,6 +123,7 @@ struct perf_evsel {
120 char *group_name; 123 char *group_name;
121 bool cmdline_group_boundary; 124 bool cmdline_group_boundary;
122 struct list_head config_terms; 125 struct list_head config_terms;
126 int bpf_fd;
123}; 127};
124 128
125union u64_swap { 129union u64_swap {
@@ -130,7 +134,6 @@ union u64_swap {
130struct cpu_map; 134struct cpu_map;
131struct target; 135struct target;
132struct thread_map; 136struct thread_map;
133struct perf_evlist;
134struct record_opts; 137struct record_opts;
135 138
136static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) 139static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
@@ -162,6 +165,9 @@ static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
162 165
163struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx); 166struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx);
164 167
168/*
169 * Returns pointer with encoded error via <linux/err.h> interface.
170 */
165static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name) 171static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name)
166{ 172{
167 return perf_evsel__newtp_idx(sys, name, 0); 173 return perf_evsel__newtp_idx(sys, name, 0);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index fce6634aebe2..43838003c1a1 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -24,9 +24,6 @@
24#include "build-id.h" 24#include "build-id.h"
25#include "data.h" 25#include "data.h"
26 26
27static u32 header_argc;
28static const char **header_argv;
29
30/* 27/*
31 * magic2 = "PERFILE2" 28 * magic2 = "PERFILE2"
32 * must be a numerical value to let the endianness 29 * must be a numerical value to let the endianness
@@ -88,6 +85,9 @@ int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
88 return err; 85 return err;
89} 86}
90 87
88#define string_size(str) \
89 (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32))
90
91static int do_write_string(int fd, const char *str) 91static int do_write_string(int fd, const char *str)
92{ 92{
93 u32 len, olen; 93 u32 len, olen;
@@ -135,37 +135,6 @@ static char *do_read_string(int fd, struct perf_header *ph)
135 return NULL; 135 return NULL;
136} 136}
137 137
138int
139perf_header__set_cmdline(int argc, const char **argv)
140{
141 int i;
142
143 /*
144 * If header_argv has already been set, do not override it.
145 * This allows a command to set the cmdline, parse args and
146 * then call another builtin function that implements a
147 * command -- e.g, cmd_kvm calling cmd_record.
148 */
149 if (header_argv)
150 return 0;
151
152 header_argc = (u32)argc;
153
154 /* do not include NULL termination */
155 header_argv = calloc(argc, sizeof(char *));
156 if (!header_argv)
157 return -ENOMEM;
158
159 /*
160 * must copy argv contents because it gets moved
161 * around during option parsing
162 */
163 for (i = 0; i < argc ; i++)
164 header_argv[i] = argv[i];
165
166 return 0;
167}
168
169static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, 138static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
170 struct perf_evlist *evlist) 139 struct perf_evlist *evlist)
171{ 140{
@@ -402,8 +371,8 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
402{ 371{
403 char buf[MAXPATHLEN]; 372 char buf[MAXPATHLEN];
404 char proc[32]; 373 char proc[32];
405 u32 i, n; 374 u32 n;
406 int ret; 375 int i, ret;
407 376
408 /* 377 /*
409 * actual atual path to perf binary 378 * actual atual path to perf binary
@@ -417,7 +386,7 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
417 buf[ret] = '\0'; 386 buf[ret] = '\0';
418 387
419 /* account for binary path */ 388 /* account for binary path */
420 n = header_argc + 1; 389 n = perf_env.nr_cmdline + 1;
421 390
422 ret = do_write(fd, &n, sizeof(n)); 391 ret = do_write(fd, &n, sizeof(n));
423 if (ret < 0) 392 if (ret < 0)
@@ -427,8 +396,8 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
427 if (ret < 0) 396 if (ret < 0)
428 return ret; 397 return ret;
429 398
430 for (i = 0 ; i < header_argc; i++) { 399 for (i = 0 ; i < perf_env.nr_cmdline; i++) {
431 ret = do_write_string(fd, header_argv[i]); 400 ret = do_write_string(fd, perf_env.cmdline_argv[i]);
432 if (ret < 0) 401 if (ret < 0)
433 return ret; 402 return ret;
434 } 403 }
@@ -441,6 +410,7 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
441 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list" 410 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
442 411
443struct cpu_topo { 412struct cpu_topo {
413 u32 cpu_nr;
444 u32 core_sib; 414 u32 core_sib;
445 u32 thread_sib; 415 u32 thread_sib;
446 char **core_siblings; 416 char **core_siblings;
@@ -551,7 +521,7 @@ static struct cpu_topo *build_cpu_topology(void)
551 return NULL; 521 return NULL;
552 522
553 tp = addr; 523 tp = addr;
554 524 tp->cpu_nr = nr;
555 addr += sizeof(*tp); 525 addr += sizeof(*tp);
556 tp->core_siblings = addr; 526 tp->core_siblings = addr;
557 addr += sz; 527 addr += sz;
@@ -574,7 +544,7 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
574{ 544{
575 struct cpu_topo *tp; 545 struct cpu_topo *tp;
576 u32 i; 546 u32 i;
577 int ret; 547 int ret, j;
578 548
579 tp = build_cpu_topology(); 549 tp = build_cpu_topology();
580 if (!tp) 550 if (!tp)
@@ -598,6 +568,21 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
598 if (ret < 0) 568 if (ret < 0)
599 break; 569 break;
600 } 570 }
571
572 ret = perf_env__read_cpu_topology_map(&perf_env);
573 if (ret < 0)
574 goto done;
575
576 for (j = 0; j < perf_env.nr_cpus_avail; j++) {
577 ret = do_write(fd, &perf_env.cpu[j].core_id,
578 sizeof(perf_env.cpu[j].core_id));
579 if (ret < 0)
580 return ret;
581 ret = do_write(fd, &perf_env.cpu[j].socket_id,
582 sizeof(perf_env.cpu[j].socket_id));
583 if (ret < 0)
584 return ret;
585 }
601done: 586done:
602 free_cpu_topo(tp); 587 free_cpu_topo(tp);
603 return ret; 588 return ret;
@@ -938,6 +923,7 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
938{ 923{
939 int nr, i; 924 int nr, i;
940 char *str; 925 char *str;
926 int cpu_nr = ph->env.nr_cpus_online;
941 927
942 nr = ph->env.nr_sibling_cores; 928 nr = ph->env.nr_sibling_cores;
943 str = ph->env.sibling_cores; 929 str = ph->env.sibling_cores;
@@ -954,6 +940,13 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
954 fprintf(fp, "# sibling threads : %s\n", str); 940 fprintf(fp, "# sibling threads : %s\n", str);
955 str += strlen(str) + 1; 941 str += strlen(str) + 1;
956 } 942 }
943
944 if (ph->env.cpu != NULL) {
945 for (i = 0; i < cpu_nr; i++)
946 fprintf(fp, "# CPU %d: Core ID %d, Socket ID %d\n", i,
947 ph->env.cpu[i].core_id, ph->env.cpu[i].socket_id);
948 } else
949 fprintf(fp, "# Core ID and Socket ID information is not available\n");
957} 950}
958 951
959static void free_event_desc(struct perf_evsel *events) 952static void free_event_desc(struct perf_evsel *events)
@@ -1582,7 +1575,7 @@ error:
1582 return -1; 1575 return -1;
1583} 1576}
1584 1577
1585static int process_cpu_topology(struct perf_file_section *section __maybe_unused, 1578static int process_cpu_topology(struct perf_file_section *section,
1586 struct perf_header *ph, int fd, 1579 struct perf_header *ph, int fd,
1587 void *data __maybe_unused) 1580 void *data __maybe_unused)
1588{ 1581{
@@ -1590,15 +1583,22 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
1590 u32 nr, i; 1583 u32 nr, i;
1591 char *str; 1584 char *str;
1592 struct strbuf sb; 1585 struct strbuf sb;
1586 int cpu_nr = ph->env.nr_cpus_online;
1587 u64 size = 0;
1588
1589 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
1590 if (!ph->env.cpu)
1591 return -1;
1593 1592
1594 ret = readn(fd, &nr, sizeof(nr)); 1593 ret = readn(fd, &nr, sizeof(nr));
1595 if (ret != sizeof(nr)) 1594 if (ret != sizeof(nr))
1596 return -1; 1595 goto free_cpu;
1597 1596
1598 if (ph->needs_swap) 1597 if (ph->needs_swap)
1599 nr = bswap_32(nr); 1598 nr = bswap_32(nr);
1600 1599
1601 ph->env.nr_sibling_cores = nr; 1600 ph->env.nr_sibling_cores = nr;
1601 size += sizeof(u32);
1602 strbuf_init(&sb, 128); 1602 strbuf_init(&sb, 128);
1603 1603
1604 for (i = 0; i < nr; i++) { 1604 for (i = 0; i < nr; i++) {
@@ -1608,6 +1608,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
1608 1608
1609 /* include a NULL character at the end */ 1609 /* include a NULL character at the end */
1610 strbuf_add(&sb, str, strlen(str) + 1); 1610 strbuf_add(&sb, str, strlen(str) + 1);
1611 size += string_size(str);
1611 free(str); 1612 free(str);
1612 } 1613 }
1613 ph->env.sibling_cores = strbuf_detach(&sb, NULL); 1614 ph->env.sibling_cores = strbuf_detach(&sb, NULL);
@@ -1620,6 +1621,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
1620 nr = bswap_32(nr); 1621 nr = bswap_32(nr);
1621 1622
1622 ph->env.nr_sibling_threads = nr; 1623 ph->env.nr_sibling_threads = nr;
1624 size += sizeof(u32);
1623 1625
1624 for (i = 0; i < nr; i++) { 1626 for (i = 0; i < nr; i++) {
1625 str = do_read_string(fd, ph); 1627 str = do_read_string(fd, ph);
@@ -1628,13 +1630,57 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
1628 1630
1629 /* include a NULL character at the end */ 1631 /* include a NULL character at the end */
1630 strbuf_add(&sb, str, strlen(str) + 1); 1632 strbuf_add(&sb, str, strlen(str) + 1);
1633 size += string_size(str);
1631 free(str); 1634 free(str);
1632 } 1635 }
1633 ph->env.sibling_threads = strbuf_detach(&sb, NULL); 1636 ph->env.sibling_threads = strbuf_detach(&sb, NULL);
1637
1638 /*
1639 * The header may be from old perf,
1640 * which doesn't include core id and socket id information.
1641 */
1642 if (section->size <= size) {
1643 zfree(&ph->env.cpu);
1644 return 0;
1645 }
1646
1647 for (i = 0; i < (u32)cpu_nr; i++) {
1648 ret = readn(fd, &nr, sizeof(nr));
1649 if (ret != sizeof(nr))
1650 goto free_cpu;
1651
1652 if (ph->needs_swap)
1653 nr = bswap_32(nr);
1654
1655 if (nr > (u32)cpu_nr) {
1656 pr_debug("core_id number is too big."
1657 "You may need to upgrade the perf tool.\n");
1658 goto free_cpu;
1659 }
1660 ph->env.cpu[i].core_id = nr;
1661
1662 ret = readn(fd, &nr, sizeof(nr));
1663 if (ret != sizeof(nr))
1664 goto free_cpu;
1665
1666 if (ph->needs_swap)
1667 nr = bswap_32(nr);
1668
1669 if (nr > (u32)cpu_nr) {
1670 pr_debug("socket_id number is too big."
1671 "You may need to upgrade the perf tool.\n");
1672 goto free_cpu;
1673 }
1674
1675 ph->env.cpu[i].socket_id = nr;
1676 }
1677
1634 return 0; 1678 return 0;
1635 1679
1636error: 1680error:
1637 strbuf_release(&sb); 1681 strbuf_release(&sb);
1682free_cpu:
1683 zfree(&ph->env.cpu);
1638 return -1; 1684 return -1;
1639} 1685}
1640 1686
@@ -1737,6 +1783,9 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
1737 /* include a NULL character at the end */ 1783 /* include a NULL character at the end */
1738 strbuf_add(&sb, "", 1); 1784 strbuf_add(&sb, "", 1);
1739 1785
1786 if (!strcmp(name, "msr"))
1787 ph->env.msr_pmu_type = type;
1788
1740 free(name); 1789 free(name);
1741 pmu_num--; 1790 pmu_num--;
1742 } 1791 }
@@ -2515,6 +2564,7 @@ int perf_session__read_header(struct perf_session *session)
2515 return -ENOMEM; 2564 return -ENOMEM;
2516 2565
2517 session->evlist->env = &header->env; 2566 session->evlist->env = &header->env;
2567 session->machines.host.env = &header->env;
2518 if (perf_data_file__is_pipe(file)) 2568 if (perf_data_file__is_pipe(file))
2519 return perf_header__read_pipe(session); 2569 return perf_header__read_pipe(session);
2520 2570
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 396e4965f0c9..05f27cb6b7e3 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -7,7 +7,7 @@
7#include <linux/bitmap.h> 7#include <linux/bitmap.h>
8#include <linux/types.h> 8#include <linux/types.h>
9#include "event.h" 9#include "event.h"
10 10#include "env.h"
11 11
12enum { 12enum {
13 HEADER_RESERVED = 0, /* always cleared */ 13 HEADER_RESERVED = 0, /* always cleared */
@@ -66,31 +66,6 @@ struct perf_header;
66int perf_file_header__read(struct perf_file_header *header, 66int perf_file_header__read(struct perf_file_header *header,
67 struct perf_header *ph, int fd); 67 struct perf_header *ph, int fd);
68 68
69struct perf_env {
70 char *hostname;
71 char *os_release;
72 char *version;
73 char *arch;
74 int nr_cpus_online;
75 int nr_cpus_avail;
76 char *cpu_desc;
77 char *cpuid;
78 unsigned long long total_mem;
79
80 int nr_cmdline;
81 int nr_sibling_cores;
82 int nr_sibling_threads;
83 int nr_numa_nodes;
84 int nr_pmu_mappings;
85 int nr_groups;
86 char *cmdline;
87 const char **cmdline_argv;
88 char *sibling_cores;
89 char *sibling_threads;
90 char *numa_nodes;
91 char *pmu_mappings;
92};
93
94struct perf_header { 69struct perf_header {
95 enum perf_header_version version; 70 enum perf_header_version version;
96 bool needs_swap; 71 bool needs_swap;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 08b6cd945f1e..4fd37d6708cb 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -15,6 +15,8 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
15 struct hist_entry *he); 15 struct hist_entry *he);
16static bool hists__filter_entry_by_symbol(struct hists *hists, 16static bool hists__filter_entry_by_symbol(struct hists *hists,
17 struct hist_entry *he); 17 struct hist_entry *he);
18static bool hists__filter_entry_by_socket(struct hists *hists,
19 struct hist_entry *he);
18 20
19u16 hists__col_len(struct hists *hists, enum hist_column col) 21u16 hists__col_len(struct hists *hists, enum hist_column col)
20{ 22{
@@ -130,6 +132,18 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
130 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, 132 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
131 symlen); 133 symlen);
132 } 134 }
135
136 if (h->mem_info->iaddr.sym) {
137 symlen = (int)h->mem_info->iaddr.sym->namelen + 4
138 + unresolved_col_width + 2;
139 hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL,
140 symlen);
141 } else {
142 symlen = unresolved_col_width + 4 + 2;
143 hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL,
144 symlen);
145 }
146
133 if (h->mem_info->daddr.map) { 147 if (h->mem_info->daddr.map) {
134 symlen = dso__name_len(h->mem_info->daddr.map->dso); 148 symlen = dso__name_len(h->mem_info->daddr.map->dso);
135 hists__new_col_len(hists, HISTC_MEM_DADDR_DSO, 149 hists__new_col_len(hists, HISTC_MEM_DADDR_DSO,
@@ -141,9 +155,12 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
141 } else { 155 } else {
142 symlen = unresolved_col_width + 4 + 2; 156 symlen = unresolved_col_width + 4 + 2;
143 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen); 157 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
158 hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL, symlen);
144 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); 159 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
145 } 160 }
146 161
162 hists__new_col_len(hists, HISTC_CPU, 3);
163 hists__new_col_len(hists, HISTC_SOCKET, 6);
147 hists__new_col_len(hists, HISTC_MEM_LOCKED, 6); 164 hists__new_col_len(hists, HISTC_MEM_LOCKED, 6);
148 hists__new_col_len(hists, HISTC_MEM_TLB, 22); 165 hists__new_col_len(hists, HISTC_MEM_TLB, 22);
149 hists__new_col_len(hists, HISTC_MEM_SNOOP, 12); 166 hists__new_col_len(hists, HISTC_MEM_SNOOP, 12);
@@ -452,6 +469,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
452 .map = al->map, 469 .map = al->map,
453 .sym = al->sym, 470 .sym = al->sym,
454 }, 471 },
472 .socket = al->socket,
455 .cpu = al->cpu, 473 .cpu = al->cpu,
456 .cpumode = al->cpumode, 474 .cpumode = al->cpumode,
457 .ip = al->addr, 475 .ip = al->addr,
@@ -690,7 +708,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter,
690} 708}
691 709
692static int 710static int
693iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused, 711iter_prepare_cumulative_entry(struct hist_entry_iter *iter,
694 struct addr_location *al __maybe_unused) 712 struct addr_location *al __maybe_unused)
695{ 713{
696 struct hist_entry **he_cache; 714 struct hist_entry **he_cache;
@@ -702,7 +720,7 @@ iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused,
702 * cumulated only one time to prevent entries more than 100% 720 * cumulated only one time to prevent entries more than 100%
703 * overhead. 721 * overhead.
704 */ 722 */
705 he_cache = malloc(sizeof(*he_cache) * (PERF_MAX_STACK_DEPTH + 1)); 723 he_cache = malloc(sizeof(*he_cache) * (iter->max_stack + 1));
706 if (he_cache == NULL) 724 if (he_cache == NULL)
707 return -ENOMEM; 725 return -ENOMEM;
708 726
@@ -863,6 +881,8 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
863 if (err) 881 if (err)
864 return err; 882 return err;
865 883
884 iter->max_stack = max_stack_depth;
885
866 err = iter->ops->prepare_entry(iter, al); 886 err = iter->ops->prepare_entry(iter, al);
867 if (err) 887 if (err)
868 goto out; 888 goto out;
@@ -1024,6 +1044,7 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
1024 hists__filter_entry_by_dso(hists, he); 1044 hists__filter_entry_by_dso(hists, he);
1025 hists__filter_entry_by_thread(hists, he); 1045 hists__filter_entry_by_thread(hists, he);
1026 hists__filter_entry_by_symbol(hists, he); 1046 hists__filter_entry_by_symbol(hists, he);
1047 hists__filter_entry_by_socket(hists, he);
1027} 1048}
1028 1049
1029void hists__collapse_resort(struct hists *hists, struct ui_progress *prog) 1050void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
@@ -1143,7 +1164,7 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog)
1143 struct perf_evsel *evsel = hists_to_evsel(hists); 1164 struct perf_evsel *evsel = hists_to_evsel(hists);
1144 bool use_callchain; 1165 bool use_callchain;
1145 1166
1146 if (evsel && !symbol_conf.show_ref_callgraph) 1167 if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph)
1147 use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN; 1168 use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN;
1148 else 1169 else
1149 use_callchain = symbol_conf.use_callchain; 1170 use_callchain = symbol_conf.use_callchain;
@@ -1292,6 +1313,37 @@ void hists__filter_by_symbol(struct hists *hists)
1292 } 1313 }
1293} 1314}
1294 1315
1316static bool hists__filter_entry_by_socket(struct hists *hists,
1317 struct hist_entry *he)
1318{
1319 if ((hists->socket_filter > -1) &&
1320 (he->socket != hists->socket_filter)) {
1321 he->filtered |= (1 << HIST_FILTER__SOCKET);
1322 return true;
1323 }
1324
1325 return false;
1326}
1327
1328void hists__filter_by_socket(struct hists *hists)
1329{
1330 struct rb_node *nd;
1331
1332 hists->stats.nr_non_filtered_samples = 0;
1333
1334 hists__reset_filter_stats(hists);
1335 hists__reset_col_len(hists);
1336
1337 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
1338 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
1339
1340 if (hists__filter_entry_by_socket(hists, h))
1341 continue;
1342
1343 hists__remove_entry_filter(hists, h, HIST_FILTER__SOCKET);
1344 }
1345}
1346
1295void events_stats__inc(struct events_stats *stats, u32 type) 1347void events_stats__inc(struct events_stats *stats, u32 type)
1296{ 1348{
1297 ++stats->nr_events[0]; 1349 ++stats->nr_events[0];
@@ -1517,6 +1569,7 @@ static int hists_evsel__init(struct perf_evsel *evsel)
1517 hists->entries_collapsed = RB_ROOT; 1569 hists->entries_collapsed = RB_ROOT;
1518 hists->entries = RB_ROOT; 1570 hists->entries = RB_ROOT;
1519 pthread_mutex_init(&hists->lock, NULL); 1571 pthread_mutex_init(&hists->lock, NULL);
1572 hists->socket_filter = -1;
1520 return 0; 1573 return 0;
1521} 1574}
1522 1575
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index de6d58e7f0d5..a48a2078d288 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -20,6 +20,7 @@ enum hist_filter {
20 HIST_FILTER__SYMBOL, 20 HIST_FILTER__SYMBOL,
21 HIST_FILTER__GUEST, 21 HIST_FILTER__GUEST,
22 HIST_FILTER__HOST, 22 HIST_FILTER__HOST,
23 HIST_FILTER__SOCKET,
23}; 24};
24 25
25enum hist_column { 26enum hist_column {
@@ -29,6 +30,7 @@ enum hist_column {
29 HISTC_COMM, 30 HISTC_COMM,
30 HISTC_PARENT, 31 HISTC_PARENT,
31 HISTC_CPU, 32 HISTC_CPU,
33 HISTC_SOCKET,
32 HISTC_SRCLINE, 34 HISTC_SRCLINE,
33 HISTC_SRCFILE, 35 HISTC_SRCFILE,
34 HISTC_MISPREDICT, 36 HISTC_MISPREDICT,
@@ -47,6 +49,7 @@ enum hist_column {
47 HISTC_MEM_LVL, 49 HISTC_MEM_LVL,
48 HISTC_MEM_SNOOP, 50 HISTC_MEM_SNOOP,
49 HISTC_MEM_DCACHELINE, 51 HISTC_MEM_DCACHELINE,
52 HISTC_MEM_IADDR_SYMBOL,
50 HISTC_TRANSACTION, 53 HISTC_TRANSACTION,
51 HISTC_CYCLES, 54 HISTC_CYCLES,
52 HISTC_NR_COLS, /* Last entry */ 55 HISTC_NR_COLS, /* Last entry */
@@ -70,6 +73,7 @@ struct hists {
70 struct events_stats stats; 73 struct events_stats stats;
71 u64 event_stream; 74 u64 event_stream;
72 u16 col_len[HISTC_NR_COLS]; 75 u16 col_len[HISTC_NR_COLS];
76 int socket_filter;
73}; 77};
74 78
75struct hist_entry_iter; 79struct hist_entry_iter;
@@ -87,6 +91,7 @@ struct hist_entry_iter {
87 int curr; 91 int curr;
88 92
89 bool hide_unresolved; 93 bool hide_unresolved;
94 int max_stack;
90 95
91 struct perf_evsel *evsel; 96 struct perf_evsel *evsel;
92 struct perf_sample *sample; 97 struct perf_sample *sample;
@@ -144,11 +149,12 @@ size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp);
144void hists__filter_by_dso(struct hists *hists); 149void hists__filter_by_dso(struct hists *hists);
145void hists__filter_by_thread(struct hists *hists); 150void hists__filter_by_thread(struct hists *hists);
146void hists__filter_by_symbol(struct hists *hists); 151void hists__filter_by_symbol(struct hists *hists);
152void hists__filter_by_socket(struct hists *hists);
147 153
148static inline bool hists__has_filter(struct hists *hists) 154static inline bool hists__has_filter(struct hists *hists)
149{ 155{
150 return hists->thread_filter || hists->dso_filter || 156 return hists->thread_filter || hists->dso_filter ||
151 hists->symbol_filter_str; 157 hists->symbol_filter_str || (hists->socket_filter > -1);
152} 158}
153 159
154u16 hists__col_len(struct hists *hists, enum hist_column col); 160u16 hists__col_len(struct hists *hists, enum hist_column col);
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index 8f149655f497..07c644ed64c4 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -5,4 +5,12 @@
5const char *get_arch_regstr(unsigned int n); 5const char *get_arch_regstr(unsigned int n);
6#endif 6#endif
7 7
8#ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
9/*
10 * Arch should support fetching the offset of a register in pt_regs
11 * by its name. See kernel's regs_query_register_offset in
12 * arch/xxx/kernel/ptrace.c.
13 */
14int regs_query_register_offset(const char *name);
15#endif
8#endif 16#endif
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build
index 2386322ece4f..0611d619a42e 100644
--- a/tools/perf/util/intel-pt-decoder/Build
+++ b/tools/perf/util/intel-pt-decoder/Build
@@ -7,6 +7,17 @@ $(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_table
7 $(call rule_mkdir) 7 $(call rule_mkdir)
8 @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@ 8 @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@
9 9
10$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c 10$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/intel-pt-insn-decoder.c util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c
11 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && (( \
12 diff -B -I'^#include' util/intel-pt-decoder/insn.c ../../arch/x86/lib/insn.c >/dev/null && \
13 diff -B -I'^#include' util/intel-pt-decoder/inat.c ../../arch/x86/lib/inat.c >/dev/null && \
14 diff -B util/intel-pt-decoder/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \
15 diff -B util/intel-pt-decoder/gen-insn-attr-x86.awk ../../arch/x86/tools/gen-insn-attr-x86.awk >/dev/null && \
16 diff -B -I'^#include' util/intel-pt-decoder/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \
17 diff -B -I'^#include' util/intel-pt-decoder/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \
18 diff -B -I'^#include' util/intel-pt-decoder/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \
19 || echo "Warning: Intel PT: x86 instruction decoder differs from kernel" >&2 )) || true
20 $(call rule_mkdir)
21 $(call if_changed_dep,cc_o_c)
11 22
12CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder -Wno-override-init 23CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder -Wno-override-init
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 22ba50224319..9409d014b46c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -650,7 +650,7 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
650 if (data->from_mtc && timestamp < data->timestamp && 650 if (data->from_mtc && timestamp < data->timestamp &&
651 data->timestamp - timestamp < decoder->tsc_slip) 651 data->timestamp - timestamp < decoder->tsc_slip)
652 return 1; 652 return 1;
653 while (timestamp < data->timestamp) 653 if (timestamp < data->timestamp)
654 timestamp += (1ULL << 56); 654 timestamp += (1ULL << 56);
655 if (pkt_info->last_packet_type != INTEL_PT_CYC) { 655 if (pkt_info->last_packet_type != INTEL_PT_CYC) {
656 if (data->from_mtc) 656 if (data->from_mtc)
@@ -1191,7 +1191,7 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder)
1191 timestamp); 1191 timestamp);
1192 timestamp = decoder->timestamp; 1192 timestamp = decoder->timestamp;
1193 } 1193 }
1194 while (timestamp < decoder->timestamp) { 1194 if (timestamp < decoder->timestamp) {
1195 intel_pt_log_to("Wraparound timestamp", timestamp); 1195 intel_pt_log_to("Wraparound timestamp", timestamp);
1196 timestamp += (1ULL << 56); 1196 timestamp += (1ULL << 56);
1197 decoder->tsc_timestamp = timestamp; 1197 decoder->tsc_timestamp = timestamp;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index d09c7d9f9050..319bef33a64b 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -29,18 +29,18 @@
29 29
30static FILE *f; 30static FILE *f;
31static char log_name[MAX_LOG_NAME]; 31static char log_name[MAX_LOG_NAME];
32static bool enable_logging; 32bool intel_pt_enable_logging;
33 33
34void intel_pt_log_enable(void) 34void intel_pt_log_enable(void)
35{ 35{
36 enable_logging = true; 36 intel_pt_enable_logging = true;
37} 37}
38 38
39void intel_pt_log_disable(void) 39void intel_pt_log_disable(void)
40{ 40{
41 if (f) 41 if (f)
42 fflush(f); 42 fflush(f);
43 enable_logging = false; 43 intel_pt_enable_logging = false;
44} 44}
45 45
46void intel_pt_log_set_name(const char *name) 46void intel_pt_log_set_name(const char *name)
@@ -80,7 +80,7 @@ static void intel_pt_print_no_data(uint64_t pos, int indent)
80 80
81static int intel_pt_log_open(void) 81static int intel_pt_log_open(void)
82{ 82{
83 if (!enable_logging) 83 if (!intel_pt_enable_logging)
84 return -1; 84 return -1;
85 85
86 if (f) 86 if (f)
@@ -91,15 +91,15 @@ static int intel_pt_log_open(void)
91 91
92 f = fopen(log_name, "w+"); 92 f = fopen(log_name, "w+");
93 if (!f) { 93 if (!f) {
94 enable_logging = false; 94 intel_pt_enable_logging = false;
95 return -1; 95 return -1;
96 } 96 }
97 97
98 return 0; 98 return 0;
99} 99}
100 100
101void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, 101void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
102 uint64_t pos, const unsigned char *buf) 102 uint64_t pos, const unsigned char *buf)
103{ 103{
104 char desc[INTEL_PT_PKT_DESC_MAX]; 104 char desc[INTEL_PT_PKT_DESC_MAX];
105 105
@@ -111,7 +111,7 @@ void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
111 fprintf(f, "%s\n", desc); 111 fprintf(f, "%s\n", desc);
112} 112}
113 113
114void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip) 114void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
115{ 115{
116 char desc[INTEL_PT_INSN_DESC_MAX]; 116 char desc[INTEL_PT_INSN_DESC_MAX];
117 size_t len = intel_pt_insn->length; 117 size_t len = intel_pt_insn->length;
@@ -128,7 +128,8 @@ void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
128 fprintf(f, "Bad instruction!\n"); 128 fprintf(f, "Bad instruction!\n");
129} 129}
130 130
131void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip) 131void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
132 uint64_t ip)
132{ 133{
133 char desc[INTEL_PT_INSN_DESC_MAX]; 134 char desc[INTEL_PT_INSN_DESC_MAX];
134 135
@@ -142,7 +143,7 @@ void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
142 fprintf(f, "Bad instruction!\n"); 143 fprintf(f, "Bad instruction!\n");
143} 144}
144 145
145void intel_pt_log(const char *fmt, ...) 146void __intel_pt_log(const char *fmt, ...)
146{ 147{
147 va_list args; 148 va_list args;
148 149
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.h b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
index db3942f83677..debe751dc3d6 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
@@ -25,20 +25,46 @@ void intel_pt_log_enable(void);
25void intel_pt_log_disable(void); 25void intel_pt_log_disable(void);
26void intel_pt_log_set_name(const char *name); 26void intel_pt_log_set_name(const char *name);
27 27
28void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, 28void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
29 uint64_t pos, const unsigned char *buf); 29 uint64_t pos, const unsigned char *buf);
30 30
31struct intel_pt_insn; 31struct intel_pt_insn;
32 32
33void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip); 33void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip);
34void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, 34void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
35 uint64_t ip); 35 uint64_t ip);
36 36
37__attribute__((format(printf, 1, 2))) 37__attribute__((format(printf, 1, 2)))
38void intel_pt_log(const char *fmt, ...); 38void __intel_pt_log(const char *fmt, ...);
39
40#define intel_pt_log(fmt, ...) \
41 do { \
42 if (intel_pt_enable_logging) \
43 __intel_pt_log(fmt, ##__VA_ARGS__); \
44 } while (0)
45
46#define intel_pt_log_packet(arg, ...) \
47 do { \
48 if (intel_pt_enable_logging) \
49 __intel_pt_log_packet(arg, ##__VA_ARGS__); \
50 } while (0)
51
52#define intel_pt_log_insn(arg, ...) \
53 do { \
54 if (intel_pt_enable_logging) \
55 __intel_pt_log_insn(arg, ##__VA_ARGS__); \
56 } while (0)
57
58#define intel_pt_log_insn_no_data(arg, ...) \
59 do { \
60 if (intel_pt_enable_logging) \
61 __intel_pt_log_insn_no_data(arg, ##__VA_ARGS__); \
62 } while (0)
39 63
40#define x64_fmt "0x%" PRIx64 64#define x64_fmt "0x%" PRIx64
41 65
66extern bool intel_pt_enable_logging;
67
42static inline void intel_pt_log_at(const char *msg, uint64_t u) 68static inline void intel_pt_log_at(const char *msg, uint64_t u)
43{ 69{
44 intel_pt_log("%s at " x64_fmt "\n", msg, u); 70 intel_pt_log("%s at " x64_fmt "\n", msg, u);
diff --git a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
index 816488c0b97e..d388de72eaca 100644
--- a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
+++ b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
@@ -353,8 +353,12 @@ AVXcode: 1
35317: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1) 35317: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1)
35418: Grp16 (1A) 35418: Grp16 (1A)
35519: 35519:
3561a: BNDCL Ev,Gv | BNDCU Ev,Gv | BNDMOV Gv,Ev | BNDLDX Gv,Ev,Gv 356# Intel SDM opcode map does not list MPX instructions. For now using Gv for
3571b: BNDCN Ev,Gv | BNDMOV Ev,Gv | BNDMK Gv,Ev | BNDSTX Ev,GV,Gv 357# bnd registers and Ev for everything else is OK because the instruction
358# decoder does not use the information except as an indication that there is
359# a ModR/M byte.
3601a: BNDCL Gv,Ev (F3) | BNDCU Gv,Ev (F2) | BNDMOV Gv,Ev (66) | BNDLDX Gv,Ev
3611b: BNDCN Gv,Ev (F2) | BNDMOV Ev,Gv (66) | BNDMK Gv,Ev (F3) | BNDSTX Ev,Gv
3581c: 3621c:
3591d: 3631d:
3601e: 3641e:
@@ -732,6 +736,12 @@ bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
732be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) 736be: vfnmsub231ps/d Vx,Hx,Wx (66),(v)
733bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) 737bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
734# 0x0f 0x38 0xc0-0xff 738# 0x0f 0x38 0xc0-0xff
739c8: sha1nexte Vdq,Wdq
740c9: sha1msg1 Vdq,Wdq
741ca: sha1msg2 Vdq,Wdq
742cb: sha256rnds2 Vdq,Wdq
743cc: sha256msg1 Vdq,Wdq
744cd: sha256msg2 Vdq,Wdq
735db: VAESIMC Vdq,Wdq (66),(v1) 745db: VAESIMC Vdq,Wdq (66),(v1)
736dc: VAESENC Vdq,Hdq,Wdq (66),(v1) 746dc: VAESENC Vdq,Hdq,Wdq (66),(v1)
737dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) 747dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1)
@@ -790,6 +800,7 @@ AVXcode: 3
79061: vpcmpestri Vdq,Wdq,Ib (66),(v1) 80061: vpcmpestri Vdq,Wdq,Ib (66),(v1)
79162: vpcmpistrm Vdq,Wdq,Ib (66),(v1) 80162: vpcmpistrm Vdq,Wdq,Ib (66),(v1)
79263: vpcmpistri Vdq,Wdq,Ib (66),(v1) 80263: vpcmpistri Vdq,Wdq,Ib (66),(v1)
803cc: sha1rnds4 Vdq,Wdq,Ib
793df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) 804df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1)
794f0: RORX Gy,Ey,Ib (F2),(v) 805f0: RORX Gy,Ey,Ib (F2),(v)
795EndTable 806EndTable
@@ -874,7 +885,7 @@ GrpTable: Grp7
8742: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B) 8852: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B)
8753: LIDT Ms 8863: LIDT Ms
8764: SMSW Mw/Rv 8874: SMSW Mw/Rv
8775: 8885: rdpkru (110),(11B) | wrpkru (111),(11B)
8786: LMSW Ew 8896: LMSW Ew
8797: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B) 8907: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B)
880EndTable 891EndTable
@@ -888,6 +899,9 @@ EndTable
888 899
889GrpTable: Grp9 900GrpTable: Grp9
8901: CMPXCHG8B/16B Mq/Mdq 9011: CMPXCHG8B/16B Mq/Mdq
9023: xrstors
9034: xsavec
9045: xsaves
8916: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B) 9056: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B)
8927: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B) 9067: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B)
893EndTable 907EndTable
@@ -932,8 +946,8 @@ GrpTable: Grp15
9323: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) 9463: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
9334: XSAVE 9474: XSAVE
9345: XRSTOR | lfence (11B) 9485: XRSTOR | lfence (11B)
9356: XSAVEOPT | mfence (11B) 9496: XSAVEOPT | clwb (66) | mfence (11B)
9367: clflush | sfence (11B) 9507: clflush | clflushopt (66) | sfence (11B) | pcommit (66),(11B)
937EndTable 951EndTable
938 952
939GrpTable: Grp16 953GrpTable: Grp16
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 535d86f8e4d1..97f963a3dcb9 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -22,6 +22,7 @@
22#include "../perf.h" 22#include "../perf.h"
23#include "session.h" 23#include "session.h"
24#include "machine.h" 24#include "machine.h"
25#include "sort.h"
25#include "tool.h" 26#include "tool.h"
26#include "event.h" 27#include "event.h"
27#include "evlist.h" 28#include "evlist.h"
@@ -63,6 +64,7 @@ struct intel_pt {
63 bool data_queued; 64 bool data_queued;
64 bool est_tsc; 65 bool est_tsc;
65 bool sync_switch; 66 bool sync_switch;
67 bool mispred_all;
66 int have_sched_switch; 68 int have_sched_switch;
67 u32 pmu_type; 69 u32 pmu_type;
68 u64 kernel_start; 70 u64 kernel_start;
@@ -115,6 +117,9 @@ struct intel_pt_queue {
115 void *decoder; 117 void *decoder;
116 const struct intel_pt_state *state; 118 const struct intel_pt_state *state;
117 struct ip_callchain *chain; 119 struct ip_callchain *chain;
120 struct branch_stack *last_branch;
121 struct branch_stack *last_branch_rb;
122 size_t last_branch_pos;
118 union perf_event *event_buf; 123 union perf_event *event_buf;
119 bool on_heap; 124 bool on_heap;
120 bool stop; 125 bool stop;
@@ -675,6 +680,19 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
675 goto out_free; 680 goto out_free;
676 } 681 }
677 682
683 if (pt->synth_opts.last_branch) {
684 size_t sz = sizeof(struct branch_stack);
685
686 sz += pt->synth_opts.last_branch_sz *
687 sizeof(struct branch_entry);
688 ptq->last_branch = zalloc(sz);
689 if (!ptq->last_branch)
690 goto out_free;
691 ptq->last_branch_rb = zalloc(sz);
692 if (!ptq->last_branch_rb)
693 goto out_free;
694 }
695
678 ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE); 696 ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
679 if (!ptq->event_buf) 697 if (!ptq->event_buf)
680 goto out_free; 698 goto out_free;
@@ -720,7 +738,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
720 738
721 if (!params.period) { 739 if (!params.period) {
722 params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS; 740 params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS;
723 params.period = 1000; 741 params.period = 1;
724 } 742 }
725 } 743 }
726 744
@@ -732,6 +750,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
732 750
733out_free: 751out_free:
734 zfree(&ptq->event_buf); 752 zfree(&ptq->event_buf);
753 zfree(&ptq->last_branch);
754 zfree(&ptq->last_branch_rb);
735 zfree(&ptq->chain); 755 zfree(&ptq->chain);
736 free(ptq); 756 free(ptq);
737 return NULL; 757 return NULL;
@@ -746,6 +766,8 @@ static void intel_pt_free_queue(void *priv)
746 thread__zput(ptq->thread); 766 thread__zput(ptq->thread);
747 intel_pt_decoder_free(ptq->decoder); 767 intel_pt_decoder_free(ptq->decoder);
748 zfree(&ptq->event_buf); 768 zfree(&ptq->event_buf);
769 zfree(&ptq->last_branch);
770 zfree(&ptq->last_branch_rb);
749 zfree(&ptq->chain); 771 zfree(&ptq->chain);
750 free(ptq); 772 free(ptq);
751} 773}
@@ -876,6 +898,58 @@ static int intel_pt_setup_queues(struct intel_pt *pt)
876 return 0; 898 return 0;
877} 899}
878 900
901static inline void intel_pt_copy_last_branch_rb(struct intel_pt_queue *ptq)
902{
903 struct branch_stack *bs_src = ptq->last_branch_rb;
904 struct branch_stack *bs_dst = ptq->last_branch;
905 size_t nr = 0;
906
907 bs_dst->nr = bs_src->nr;
908
909 if (!bs_src->nr)
910 return;
911
912 nr = ptq->pt->synth_opts.last_branch_sz - ptq->last_branch_pos;
913 memcpy(&bs_dst->entries[0],
914 &bs_src->entries[ptq->last_branch_pos],
915 sizeof(struct branch_entry) * nr);
916
917 if (bs_src->nr >= ptq->pt->synth_opts.last_branch_sz) {
918 memcpy(&bs_dst->entries[nr],
919 &bs_src->entries[0],
920 sizeof(struct branch_entry) * ptq->last_branch_pos);
921 }
922}
923
924static inline void intel_pt_reset_last_branch_rb(struct intel_pt_queue *ptq)
925{
926 ptq->last_branch_pos = 0;
927 ptq->last_branch_rb->nr = 0;
928}
929
930static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq)
931{
932 const struct intel_pt_state *state = ptq->state;
933 struct branch_stack *bs = ptq->last_branch_rb;
934 struct branch_entry *be;
935
936 if (!ptq->last_branch_pos)
937 ptq->last_branch_pos = ptq->pt->synth_opts.last_branch_sz;
938
939 ptq->last_branch_pos -= 1;
940
941 be = &bs->entries[ptq->last_branch_pos];
942 be->from = state->from_ip;
943 be->to = state->to_ip;
944 be->flags.abort = !!(state->flags & INTEL_PT_ABORT_TX);
945 be->flags.in_tx = !!(state->flags & INTEL_PT_IN_TX);
946 /* No support for mispredict */
947 be->flags.mispred = ptq->pt->mispred_all;
948
949 if (bs->nr < ptq->pt->synth_opts.last_branch_sz)
950 bs->nr += 1;
951}
952
879static int intel_pt_inject_event(union perf_event *event, 953static int intel_pt_inject_event(union perf_event *event,
880 struct perf_sample *sample, u64 type, 954 struct perf_sample *sample, u64 type,
881 bool swapped) 955 bool swapped)
@@ -890,6 +964,13 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
890 struct intel_pt *pt = ptq->pt; 964 struct intel_pt *pt = ptq->pt;
891 union perf_event *event = ptq->event_buf; 965 union perf_event *event = ptq->event_buf;
892 struct perf_sample sample = { .ip = 0, }; 966 struct perf_sample sample = { .ip = 0, };
967 struct dummy_branch_stack {
968 u64 nr;
969 struct branch_entry entries;
970 } dummy_bs;
971
972 if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
973 return 0;
893 974
894 event->sample.header.type = PERF_RECORD_SAMPLE; 975 event->sample.header.type = PERF_RECORD_SAMPLE;
895 event->sample.header.misc = PERF_RECORD_MISC_USER; 976 event->sample.header.misc = PERF_RECORD_MISC_USER;
@@ -909,8 +990,20 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
909 sample.flags = ptq->flags; 990 sample.flags = ptq->flags;
910 sample.insn_len = ptq->insn_len; 991 sample.insn_len = ptq->insn_len;
911 992
912 if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) 993 /*
913 return 0; 994 * perf report cannot handle events without a branch stack when using
995 * SORT_MODE__BRANCH so make a dummy one.
996 */
997 if (pt->synth_opts.last_branch && sort__mode == SORT_MODE__BRANCH) {
998 dummy_bs = (struct dummy_branch_stack){
999 .nr = 1,
1000 .entries = {
1001 .from = sample.ip,
1002 .to = sample.addr,
1003 },
1004 };
1005 sample.branch_stack = (struct branch_stack *)&dummy_bs;
1006 }
914 1007
915 if (pt->synth_opts.inject) { 1008 if (pt->synth_opts.inject) {
916 ret = intel_pt_inject_event(event, &sample, 1009 ret = intel_pt_inject_event(event, &sample,
@@ -961,6 +1054,11 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
961 sample.callchain = ptq->chain; 1054 sample.callchain = ptq->chain;
962 } 1055 }
963 1056
1057 if (pt->synth_opts.last_branch) {
1058 intel_pt_copy_last_branch_rb(ptq);
1059 sample.branch_stack = ptq->last_branch;
1060 }
1061
964 if (pt->synth_opts.inject) { 1062 if (pt->synth_opts.inject) {
965 ret = intel_pt_inject_event(event, &sample, 1063 ret = intel_pt_inject_event(event, &sample,
966 pt->instructions_sample_type, 1064 pt->instructions_sample_type,
@@ -974,6 +1072,9 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
974 pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n", 1072 pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n",
975 ret); 1073 ret);
976 1074
1075 if (pt->synth_opts.last_branch)
1076 intel_pt_reset_last_branch_rb(ptq);
1077
977 return ret; 1078 return ret;
978} 1079}
979 1080
@@ -1008,6 +1109,11 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1008 sample.callchain = ptq->chain; 1109 sample.callchain = ptq->chain;
1009 } 1110 }
1010 1111
1112 if (pt->synth_opts.last_branch) {
1113 intel_pt_copy_last_branch_rb(ptq);
1114 sample.branch_stack = ptq->last_branch;
1115 }
1116
1011 if (pt->synth_opts.inject) { 1117 if (pt->synth_opts.inject) {
1012 ret = intel_pt_inject_event(event, &sample, 1118 ret = intel_pt_inject_event(event, &sample,
1013 pt->transactions_sample_type, 1119 pt->transactions_sample_type,
@@ -1021,6 +1127,9 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1021 pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n", 1127 pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n",
1022 ret); 1128 ret);
1023 1129
1130 if (pt->synth_opts.callchain)
1131 intel_pt_reset_last_branch_rb(ptq);
1132
1024 return ret; 1133 return ret;
1025} 1134}
1026 1135
@@ -1116,6 +1225,9 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1116 return err; 1225 return err;
1117 } 1226 }
1118 1227
1228 if (pt->synth_opts.last_branch)
1229 intel_pt_update_last_branch_rb(ptq);
1230
1119 if (!pt->sync_switch) 1231 if (!pt->sync_switch)
1120 return 0; 1232 return 0;
1121 1233
@@ -1145,16 +1257,18 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1145 return 0; 1257 return 0;
1146} 1258}
1147 1259
1148static u64 intel_pt_switch_ip(struct machine *machine, u64 *ptss_ip) 1260static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
1149{ 1261{
1262 struct machine *machine = pt->machine;
1150 struct map *map; 1263 struct map *map;
1151 struct symbol *sym, *start; 1264 struct symbol *sym, *start;
1152 u64 ip, switch_ip = 0; 1265 u64 ip, switch_ip = 0;
1266 const char *ptss;
1153 1267
1154 if (ptss_ip) 1268 if (ptss_ip)
1155 *ptss_ip = 0; 1269 *ptss_ip = 0;
1156 1270
1157 map = machine__kernel_map(machine, MAP__FUNCTION); 1271 map = machine__kernel_map(machine);
1158 if (!map) 1272 if (!map)
1159 return 0; 1273 return 0;
1160 1274
@@ -1177,8 +1291,13 @@ static u64 intel_pt_switch_ip(struct machine *machine, u64 *ptss_ip)
1177 if (!switch_ip || !ptss_ip) 1291 if (!switch_ip || !ptss_ip)
1178 return 0; 1292 return 0;
1179 1293
1294 if (pt->have_sched_switch == 1)
1295 ptss = "perf_trace_sched_switch";
1296 else
1297 ptss = "__perf_event_task_sched_out";
1298
1180 for (sym = start; sym; sym = dso__next_symbol(sym)) { 1299 for (sym = start; sym; sym = dso__next_symbol(sym)) {
1181 if (!strcmp(sym->name, "perf_trace_sched_switch")) { 1300 if (!strcmp(sym->name, ptss)) {
1182 ip = map->unmap_ip(map, sym->start); 1301 ip = map->unmap_ip(map, sym->start);
1183 if (ip >= map->start && ip < map->end) { 1302 if (ip >= map->start && ip < map->end) {
1184 *ptss_ip = ip; 1303 *ptss_ip = ip;
@@ -1198,11 +1317,11 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1198 1317
1199 if (!pt->kernel_start) { 1318 if (!pt->kernel_start) {
1200 pt->kernel_start = machine__kernel_start(pt->machine); 1319 pt->kernel_start = machine__kernel_start(pt->machine);
1201 if (pt->per_cpu_mmaps && pt->have_sched_switch && 1320 if (pt->per_cpu_mmaps &&
1321 (pt->have_sched_switch == 1 || pt->have_sched_switch == 3) &&
1202 !pt->timeless_decoding && intel_pt_tracing_kernel(pt) && 1322 !pt->timeless_decoding && intel_pt_tracing_kernel(pt) &&
1203 !pt->sampling_mode) { 1323 !pt->sampling_mode) {
1204 pt->switch_ip = intel_pt_switch_ip(pt->machine, 1324 pt->switch_ip = intel_pt_switch_ip(pt, &pt->ptss_ip);
1205 &pt->ptss_ip);
1206 if (pt->switch_ip) { 1325 if (pt->switch_ip) {
1207 intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n", 1326 intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n",
1208 pt->switch_ip, pt->ptss_ip); 1327 pt->switch_ip, pt->ptss_ip);
@@ -1387,31 +1506,18 @@ static struct intel_pt_queue *intel_pt_cpu_to_ptq(struct intel_pt *pt, int cpu)
1387 return NULL; 1506 return NULL;
1388} 1507}
1389 1508
1390static int intel_pt_process_switch(struct intel_pt *pt, 1509static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid,
1391 struct perf_sample *sample) 1510 u64 timestamp)
1392{ 1511{
1393 struct intel_pt_queue *ptq; 1512 struct intel_pt_queue *ptq;
1394 struct perf_evsel *evsel; 1513 int err;
1395 pid_t tid;
1396 int cpu, err;
1397
1398 evsel = perf_evlist__id2evsel(pt->session->evlist, sample->id);
1399 if (evsel != pt->switch_evsel)
1400 return 0;
1401
1402 tid = perf_evsel__intval(evsel, sample, "next_pid");
1403 cpu = sample->cpu;
1404
1405 intel_pt_log("sched_switch: cpu %d tid %d time %"PRIu64" tsc %#"PRIx64"\n",
1406 cpu, tid, sample->time, perf_time_to_tsc(sample->time,
1407 &pt->tc));
1408 1514
1409 if (!pt->sync_switch) 1515 if (!pt->sync_switch)
1410 goto out; 1516 return 1;
1411 1517
1412 ptq = intel_pt_cpu_to_ptq(pt, cpu); 1518 ptq = intel_pt_cpu_to_ptq(pt, cpu);
1413 if (!ptq) 1519 if (!ptq)
1414 goto out; 1520 return 1;
1415 1521
1416 switch (ptq->switch_state) { 1522 switch (ptq->switch_state) {
1417 case INTEL_PT_SS_NOT_TRACING: 1523 case INTEL_PT_SS_NOT_TRACING:
@@ -1424,7 +1530,7 @@ static int intel_pt_process_switch(struct intel_pt *pt,
1424 return 0; 1530 return 0;
1425 case INTEL_PT_SS_EXPECTING_SWITCH_EVENT: 1531 case INTEL_PT_SS_EXPECTING_SWITCH_EVENT:
1426 if (!ptq->on_heap) { 1532 if (!ptq->on_heap) {
1427 ptq->timestamp = perf_time_to_tsc(sample->time, 1533 ptq->timestamp = perf_time_to_tsc(timestamp,
1428 &pt->tc); 1534 &pt->tc);
1429 err = auxtrace_heap__add(&pt->heap, ptq->queue_nr, 1535 err = auxtrace_heap__add(&pt->heap, ptq->queue_nr,
1430 ptq->timestamp); 1536 ptq->timestamp);
@@ -1441,10 +1547,76 @@ static int intel_pt_process_switch(struct intel_pt *pt,
1441 default: 1547 default:
1442 break; 1548 break;
1443 } 1549 }
1444out: 1550
1551 return 1;
1552}
1553
1554static int intel_pt_process_switch(struct intel_pt *pt,
1555 struct perf_sample *sample)
1556{
1557 struct perf_evsel *evsel;
1558 pid_t tid;
1559 int cpu, ret;
1560
1561 evsel = perf_evlist__id2evsel(pt->session->evlist, sample->id);
1562 if (evsel != pt->switch_evsel)
1563 return 0;
1564
1565 tid = perf_evsel__intval(evsel, sample, "next_pid");
1566 cpu = sample->cpu;
1567
1568 intel_pt_log("sched_switch: cpu %d tid %d time %"PRIu64" tsc %#"PRIx64"\n",
1569 cpu, tid, sample->time, perf_time_to_tsc(sample->time,
1570 &pt->tc));
1571
1572 ret = intel_pt_sync_switch(pt, cpu, tid, sample->time);
1573 if (ret <= 0)
1574 return ret;
1575
1445 return machine__set_current_tid(pt->machine, cpu, -1, tid); 1576 return machine__set_current_tid(pt->machine, cpu, -1, tid);
1446} 1577}
1447 1578
1579static int intel_pt_context_switch(struct intel_pt *pt, union perf_event *event,
1580 struct perf_sample *sample)
1581{
1582 bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
1583 pid_t pid, tid;
1584 int cpu, ret;
1585
1586 cpu = sample->cpu;
1587
1588 if (pt->have_sched_switch == 3) {
1589 if (!out)
1590 return 0;
1591 if (event->header.type != PERF_RECORD_SWITCH_CPU_WIDE) {
1592 pr_err("Expecting CPU-wide context switch event\n");
1593 return -EINVAL;
1594 }
1595 pid = event->context_switch.next_prev_pid;
1596 tid = event->context_switch.next_prev_tid;
1597 } else {
1598 if (out)
1599 return 0;
1600 pid = sample->pid;
1601 tid = sample->tid;
1602 }
1603
1604 if (tid == -1) {
1605 pr_err("context_switch event has no tid\n");
1606 return -EINVAL;
1607 }
1608
1609 intel_pt_log("context_switch: cpu %d pid %d tid %d time %"PRIu64" tsc %#"PRIx64"\n",
1610 cpu, pid, tid, sample->time, perf_time_to_tsc(sample->time,
1611 &pt->tc));
1612
1613 ret = intel_pt_sync_switch(pt, cpu, tid, sample->time);
1614 if (ret <= 0)
1615 return ret;
1616
1617 return machine__set_current_tid(pt->machine, cpu, pid, tid);
1618}
1619
1448static int intel_pt_process_itrace_start(struct intel_pt *pt, 1620static int intel_pt_process_itrace_start(struct intel_pt *pt,
1449 union perf_event *event, 1621 union perf_event *event,
1450 struct perf_sample *sample) 1622 struct perf_sample *sample)
@@ -1515,6 +1687,9 @@ static int intel_pt_process_event(struct perf_session *session,
1515 err = intel_pt_process_switch(pt, sample); 1687 err = intel_pt_process_switch(pt, sample);
1516 else if (event->header.type == PERF_RECORD_ITRACE_START) 1688 else if (event->header.type == PERF_RECORD_ITRACE_START)
1517 err = intel_pt_process_itrace_start(pt, event, sample); 1689 err = intel_pt_process_itrace_start(pt, event, sample);
1690 else if (event->header.type == PERF_RECORD_SWITCH ||
1691 event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)
1692 err = intel_pt_context_switch(pt, event, sample);
1518 1693
1519 intel_pt_log("event %s (%u): cpu %d time %"PRIu64" tsc %#"PRIx64"\n", 1694 intel_pt_log("event %s (%u): cpu %d time %"PRIu64" tsc %#"PRIx64"\n",
1520 perf_event__name(event->header.type), event->header.type, 1695 perf_event__name(event->header.type), event->header.type,
@@ -1700,6 +1875,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1700 pt->instructions_sample_period = attr.sample_period; 1875 pt->instructions_sample_period = attr.sample_period;
1701 if (pt->synth_opts.callchain) 1876 if (pt->synth_opts.callchain)
1702 attr.sample_type |= PERF_SAMPLE_CALLCHAIN; 1877 attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
1878 if (pt->synth_opts.last_branch)
1879 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
1703 pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", 1880 pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
1704 id, (u64)attr.sample_type); 1881 id, (u64)attr.sample_type);
1705 err = intel_pt_synth_event(session, &attr, id); 1882 err = intel_pt_synth_event(session, &attr, id);
@@ -1719,6 +1896,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1719 attr.sample_period = 1; 1896 attr.sample_period = 1;
1720 if (pt->synth_opts.callchain) 1897 if (pt->synth_opts.callchain)
1721 attr.sample_type |= PERF_SAMPLE_CALLCHAIN; 1898 attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
1899 if (pt->synth_opts.last_branch)
1900 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
1722 pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", 1901 pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
1723 id, (u64)attr.sample_type); 1902 id, (u64)attr.sample_type);
1724 err = intel_pt_synth_event(session, &attr, id); 1903 err = intel_pt_synth_event(session, &attr, id);
@@ -1745,6 +1924,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1745 attr.sample_period = 1; 1924 attr.sample_period = 1;
1746 attr.sample_type |= PERF_SAMPLE_ADDR; 1925 attr.sample_type |= PERF_SAMPLE_ADDR;
1747 attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN; 1926 attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN;
1927 attr.sample_type &= ~(u64)PERF_SAMPLE_BRANCH_STACK;
1748 pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n", 1928 pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
1749 id, (u64)attr.sample_type); 1929 id, (u64)attr.sample_type);
1750 err = intel_pt_synth_event(session, &attr, id); 1930 err = intel_pt_synth_event(session, &attr, id);
@@ -1777,6 +1957,28 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist)
1777 return NULL; 1957 return NULL;
1778} 1958}
1779 1959
1960static bool intel_pt_find_switch(struct perf_evlist *evlist)
1961{
1962 struct perf_evsel *evsel;
1963
1964 evlist__for_each(evlist, evsel) {
1965 if (evsel->attr.context_switch)
1966 return true;
1967 }
1968
1969 return false;
1970}
1971
1972static int intel_pt_perf_config(const char *var, const char *value, void *data)
1973{
1974 struct intel_pt *pt = data;
1975
1976 if (!strcmp(var, "intel-pt.mispred-all"))
1977 pt->mispred_all = perf_config_bool(var, value);
1978
1979 return 0;
1980}
1981
1780static const char * const intel_pt_info_fmts[] = { 1982static const char * const intel_pt_info_fmts[] = {
1781 [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", 1983 [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n",
1782 [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", 1984 [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n",
@@ -1821,6 +2023,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
1821 if (!pt) 2023 if (!pt)
1822 return -ENOMEM; 2024 return -ENOMEM;
1823 2025
2026 perf_config(intel_pt_perf_config, pt);
2027
1824 err = auxtrace_queues__init(&pt->queues); 2028 err = auxtrace_queues__init(&pt->queues);
1825 if (err) 2029 if (err)
1826 goto err_free; 2030 goto err_free;
@@ -1888,6 +2092,10 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
1888 pr_err("%s: missing sched_switch event\n", __func__); 2092 pr_err("%s: missing sched_switch event\n", __func__);
1889 goto err_delete_thread; 2093 goto err_delete_thread;
1890 } 2094 }
2095 } else if (pt->have_sched_switch == 2 &&
2096 !intel_pt_find_switch(session->evlist)) {
2097 pr_err("%s: missing context_switch attribute flag\n", __func__);
2098 goto err_delete_thread;
1891 } 2099 }
1892 2100
1893 if (session->itrace_synth_opts && session->itrace_synth_opts->set) { 2101 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 4f6a4780bd5f..00724d496d38 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -4,17 +4,18 @@
4 */ 4 */
5 5
6#include <stdio.h> 6#include <stdio.h>
7#include <sys/utsname.h>
8#include "util.h" 7#include "util.h"
9#include "debug.h" 8#include "debug.h"
10#include "llvm-utils.h" 9#include "llvm-utils.h"
11#include "cache.h" 10#include "cache.h"
12 11
13#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ 12#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \
14 "$CLANG_EXEC -D__KERNEL__ $CLANG_OPTIONS " \ 13 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
15 "$KERNEL_INC_OPTIONS -Wno-unused-value " \ 14 "-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE " \
16 "-Wno-pointer-sign -working-directory " \ 15 "$CLANG_OPTIONS $KERNEL_INC_OPTIONS " \
17 "$WORKING_DIR -c \"$CLANG_SOURCE\" -target bpf -O2 -o -" 16 "-Wno-unused-value -Wno-pointer-sign " \
17 "-working-directory $WORKING_DIR " \
18 "-c \"$CLANG_SOURCE\" -target bpf -O2 -o -"
18 19
19struct llvm_param llvm_param = { 20struct llvm_param llvm_param = {
20 .clang_path = "clang", 21 .clang_path = "clang",
@@ -214,18 +215,19 @@ static int detect_kbuild_dir(char **kbuild_dir)
214 const char *suffix_dir = ""; 215 const char *suffix_dir = "";
215 216
216 char *autoconf_path; 217 char *autoconf_path;
217 struct utsname utsname;
218 218
219 int err; 219 int err;
220 220
221 if (!test_dir) { 221 if (!test_dir) {
222 err = uname(&utsname); 222 /* _UTSNAME_LENGTH is 65 */
223 if (err) { 223 char release[128];
224 pr_warning("uname failed: %s\n", strerror(errno)); 224
225 err = fetch_kernel_version(NULL, release,
226 sizeof(release));
227 if (err)
225 return -EINVAL; 228 return -EINVAL;
226 }
227 229
228 test_dir = utsname.release; 230 test_dir = release;
229 prefix_dir = "/lib/modules/"; 231 prefix_dir = "/lib/modules/";
230 suffix_dir = "/build"; 232 suffix_dir = "/build";
231 } 233 }
@@ -326,13 +328,15 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
326int llvm__compile_bpf(const char *path, void **p_obj_buf, 328int llvm__compile_bpf(const char *path, void **p_obj_buf,
327 size_t *p_obj_buf_sz) 329 size_t *p_obj_buf_sz)
328{ 330{
329 int err; 331 size_t obj_buf_sz;
330 char clang_path[PATH_MAX]; 332 void *obj_buf = NULL;
333 int err, nr_cpus_avail;
334 unsigned int kernel_version;
335 char linux_version_code_str[64];
331 const char *clang_opt = llvm_param.clang_opt; 336 const char *clang_opt = llvm_param.clang_opt;
332 const char *template = llvm_param.clang_bpf_cmd_template; 337 char clang_path[PATH_MAX], nr_cpus_avail_str[64];
333 char *kbuild_dir = NULL, *kbuild_include_opts = NULL; 338 char *kbuild_dir = NULL, *kbuild_include_opts = NULL;
334 void *obj_buf = NULL; 339 const char *template = llvm_param.clang_bpf_cmd_template;
335 size_t obj_buf_sz;
336 340
337 if (!template) 341 if (!template)
338 template = CLANG_BPF_CMD_DEFAULT_TEMPLATE; 342 template = CLANG_BPF_CMD_DEFAULT_TEMPLATE;
@@ -354,6 +358,24 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
354 */ 358 */
355 get_kbuild_opts(&kbuild_dir, &kbuild_include_opts); 359 get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
356 360
361 nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
362 if (nr_cpus_avail <= 0) {
363 pr_err(
364"WARNING:\tunable to get available CPUs in this system: %s\n"
365" \tUse 128 instead.\n", strerror(errno));
366 nr_cpus_avail = 128;
367 }
368 snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
369 nr_cpus_avail);
370
371 if (fetch_kernel_version(&kernel_version, NULL, 0))
372 kernel_version = 0;
373
374 snprintf(linux_version_code_str, sizeof(linux_version_code_str),
375 "0x%x", kernel_version);
376
377 force_set_env("NR_CPUS", nr_cpus_avail_str);
378 force_set_env("LINUX_VERSION_CODE", linux_version_code_str);
357 force_set_env("CLANG_EXEC", clang_path); 379 force_set_env("CLANG_EXEC", clang_path);
358 force_set_env("CLANG_OPTIONS", clang_opt); 380 force_set_env("CLANG_OPTIONS", clang_opt);
359 force_set_env("KERNEL_INC_OPTIONS", kbuild_include_opts); 381 force_set_env("KERNEL_INC_OPTIONS", kbuild_include_opts);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 6309f7ceb08f..8b303ff20289 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -35,6 +35,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
35 machine->last_match = NULL; 35 machine->last_match = NULL;
36 36
37 machine->vdso_info = NULL; 37 machine->vdso_info = NULL;
38 machine->env = NULL;
38 39
39 machine->pid = pid; 40 machine->pid = pid;
40 41
@@ -90,6 +91,7 @@ static void dsos__purge(struct dsos *dsos)
90 91
91 list_for_each_entry_safe(pos, n, &dsos->head, node) { 92 list_for_each_entry_safe(pos, n, &dsos->head, node) {
92 RB_CLEAR_NODE(&pos->rb_node); 93 RB_CLEAR_NODE(&pos->rb_node);
94 pos->root = NULL;
93 list_del_init(&pos->node); 95 list_del_init(&pos->node);
94 dso__put(pos); 96 dso__put(pos);
95 } 97 }
@@ -624,7 +626,7 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
624{ 626{
625 int i; 627 int i;
626 size_t printed = 0; 628 size_t printed = 0;
627 struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso; 629 struct dso *kdso = machine__kernel_map(machine)->dso;
628 630
629 if (kdso->has_build_id) { 631 if (kdso->has_build_id) {
630 char filename[PATH_MAX]; 632 char filename[PATH_MAX];
@@ -740,6 +742,7 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
740 742
741 for (type = 0; type < MAP__NR_TYPES; ++type) { 743 for (type = 0; type < MAP__NR_TYPES; ++type) {
742 struct kmap *kmap; 744 struct kmap *kmap;
745 struct map *map;
743 746
744 machine->vmlinux_maps[type] = map__new2(start, kernel, type); 747 machine->vmlinux_maps[type] = map__new2(start, kernel, type);
745 if (machine->vmlinux_maps[type] == NULL) 748 if (machine->vmlinux_maps[type] == NULL)
@@ -748,13 +751,13 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
748 machine->vmlinux_maps[type]->map_ip = 751 machine->vmlinux_maps[type]->map_ip =
749 machine->vmlinux_maps[type]->unmap_ip = 752 machine->vmlinux_maps[type]->unmap_ip =
750 identity__map_ip; 753 identity__map_ip;
751 kmap = map__kmap(machine->vmlinux_maps[type]); 754 map = __machine__kernel_map(machine, type);
755 kmap = map__kmap(map);
752 if (!kmap) 756 if (!kmap)
753 return -1; 757 return -1;
754 758
755 kmap->kmaps = &machine->kmaps; 759 kmap->kmaps = &machine->kmaps;
756 map_groups__insert(&machine->kmaps, 760 map_groups__insert(&machine->kmaps, map);
757 machine->vmlinux_maps[type]);
758 } 761 }
759 762
760 return 0; 763 return 0;
@@ -766,13 +769,13 @@ void machine__destroy_kernel_maps(struct machine *machine)
766 769
767 for (type = 0; type < MAP__NR_TYPES; ++type) { 770 for (type = 0; type < MAP__NR_TYPES; ++type) {
768 struct kmap *kmap; 771 struct kmap *kmap;
772 struct map *map = __machine__kernel_map(machine, type);
769 773
770 if (machine->vmlinux_maps[type] == NULL) 774 if (map == NULL)
771 continue; 775 continue;
772 776
773 kmap = map__kmap(machine->vmlinux_maps[type]); 777 kmap = map__kmap(map);
774 map_groups__remove(&machine->kmaps, 778 map_groups__remove(&machine->kmaps, map);
775 machine->vmlinux_maps[type]);
776 if (kmap && kmap->ref_reloc_sym) { 779 if (kmap && kmap->ref_reloc_sym) {
777 /* 780 /*
778 * ref_reloc_sym is shared among all maps, so free just 781 * ref_reloc_sym is shared among all maps, so free just
@@ -866,7 +869,7 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
866int machine__load_kallsyms(struct machine *machine, const char *filename, 869int machine__load_kallsyms(struct machine *machine, const char *filename,
867 enum map_type type, symbol_filter_t filter) 870 enum map_type type, symbol_filter_t filter)
868{ 871{
869 struct map *map = machine->vmlinux_maps[type]; 872 struct map *map = machine__kernel_map(machine);
870 int ret = dso__load_kallsyms(map->dso, filename, map, filter); 873 int ret = dso__load_kallsyms(map->dso, filename, map, filter);
871 874
872 if (ret > 0) { 875 if (ret > 0) {
@@ -885,7 +888,7 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
885int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 888int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
886 symbol_filter_t filter) 889 symbol_filter_t filter)
887{ 890{
888 struct map *map = machine->vmlinux_maps[type]; 891 struct map *map = machine__kernel_map(machine);
889 int ret = dso__load_vmlinux_path(map->dso, map, filter); 892 int ret = dso__load_vmlinux_path(map->dso, map, filter);
890 893
891 if (ret > 0) 894 if (ret > 0)
@@ -1243,8 +1246,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1243 /* 1246 /*
1244 * preload dso of guest kernel and modules 1247 * preload dso of guest kernel and modules
1245 */ 1248 */
1246 dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], 1249 dso__load(kernel, machine__kernel_map(machine), NULL);
1247 NULL);
1248 } 1250 }
1249 } 1251 }
1250 return 0; 1252 return 0;
@@ -1830,7 +1832,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1830 } 1832 }
1831 1833
1832check_calls: 1834check_calls:
1833 if (chain->nr > PERF_MAX_STACK_DEPTH) { 1835 if (chain->nr > PERF_MAX_STACK_DEPTH && (int)chain->nr > max_stack) {
1834 pr_warning("corrupted callchain. skipping...\n"); 1836 pr_warning("corrupted callchain. skipping...\n");
1835 return 0; 1837 return 0;
1836 } 1838 }
@@ -1996,7 +1998,7 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
1996 1998
1997int machine__get_kernel_start(struct machine *machine) 1999int machine__get_kernel_start(struct machine *machine)
1998{ 2000{
1999 struct map *map = machine__kernel_map(machine, MAP__FUNCTION); 2001 struct map *map = machine__kernel_map(machine);
2000 int err = 0; 2002 int err = 0;
2001 2003
2002 /* 2004 /*
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index ea5cb4a621db..2c2b443df5ba 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -34,6 +34,7 @@ struct machine {
34 struct list_head dead_threads; 34 struct list_head dead_threads;
35 struct thread *last_match; 35 struct thread *last_match;
36 struct vdso_info *vdso_info; 36 struct vdso_info *vdso_info;
37 struct perf_env *env;
37 struct dsos dsos; 38 struct dsos dsos;
38 struct map_groups kmaps; 39 struct map_groups kmaps;
39 struct map *vmlinux_maps[MAP__NR_TYPES]; 40 struct map *vmlinux_maps[MAP__NR_TYPES];
@@ -47,11 +48,17 @@ struct machine {
47}; 48};
48 49
49static inline 50static inline
50struct map *machine__kernel_map(struct machine *machine, enum map_type type) 51struct map *__machine__kernel_map(struct machine *machine, enum map_type type)
51{ 52{
52 return machine->vmlinux_maps[type]; 53 return machine->vmlinux_maps[type];
53} 54}
54 55
56static inline
57struct map *machine__kernel_map(struct machine *machine)
58{
59 return __machine__kernel_map(machine, MAP__FUNCTION);
60}
61
55int machine__get_kernel_start(struct machine *machine); 62int machine__get_kernel_start(struct machine *machine);
56 63
57static inline u64 machine__kernel_start(struct machine *machine) 64static inline u64 machine__kernel_start(struct machine *machine)
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index b1c475d9b240..afc6b56cf749 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -235,7 +235,7 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
235 */ 235 */
236bool __map__is_kernel(const struct map *map) 236bool __map__is_kernel(const struct map *map)
237{ 237{
238 return map->groups->machine->vmlinux_maps[map->type] == map; 238 return __machine__kernel_map(map->groups->machine, map->type) == map;
239} 239}
240 240
241static void map__exit(struct map *map) 241static void map__exit(struct map *map)
@@ -553,13 +553,9 @@ struct symbol *map_groups__find_symbol(struct map_groups *mg,
553 return NULL; 553 return NULL;
554} 554}
555 555
556struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 556struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
557 enum map_type type, 557 struct map **mapp, symbol_filter_t filter)
558 const char *name,
559 struct map **mapp,
560 symbol_filter_t filter)
561{ 558{
562 struct maps *maps = &mg->maps[type];
563 struct symbol *sym; 559 struct symbol *sym;
564 struct rb_node *nd; 560 struct rb_node *nd;
565 561
@@ -583,6 +579,17 @@ out:
583 return sym; 579 return sym;
584} 580}
585 581
582struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
583 enum map_type type,
584 const char *name,
585 struct map **mapp,
586 symbol_filter_t filter)
587{
588 struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp, filter);
589
590 return sym;
591}
592
586int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) 593int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
587{ 594{
588 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { 595 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
@@ -637,6 +644,12 @@ size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
637 return printed; 644 return printed;
638} 645}
639 646
647static void __map_groups__insert(struct map_groups *mg, struct map *map)
648{
649 __maps__insert(&mg->maps[map->type], map);
650 map->groups = mg;
651}
652
640static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) 653static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
641{ 654{
642 struct rb_root *root; 655 struct rb_root *root;
@@ -675,7 +688,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
675 } 688 }
676 689
677 before->end = map->start; 690 before->end = map->start;
678 __maps__insert(maps, before); 691 __map_groups__insert(pos->groups, before);
679 if (verbose >= 2) 692 if (verbose >= 2)
680 map__fprintf(before, fp); 693 map__fprintf(before, fp);
681 } 694 }
@@ -689,7 +702,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
689 } 702 }
690 703
691 after->start = map->end; 704 after->start = map->end;
692 __maps__insert(maps, after); 705 __map_groups__insert(pos->groups, after);
693 if (verbose >= 2) 706 if (verbose >= 2)
694 map__fprintf(after, fp); 707 map__fprintf(after, fp);
695 } 708 }
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 57829e89b78b..7309d64ce39e 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -190,6 +190,8 @@ void maps__remove(struct maps *maps, struct map *map);
190struct map *maps__find(struct maps *maps, u64 addr); 190struct map *maps__find(struct maps *maps, u64 addr);
191struct map *maps__first(struct maps *maps); 191struct map *maps__first(struct maps *maps);
192struct map *map__next(struct map *map); 192struct map *map__next(struct map *map);
193struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
194 struct map **mapp, symbol_filter_t filter);
193void map_groups__init(struct map_groups *mg, struct machine *machine); 195void map_groups__init(struct map_groups *mg, struct machine *machine);
194void map_groups__exit(struct map_groups *mg); 196void map_groups__exit(struct map_groups *mg);
195int map_groups__clone(struct map_groups *mg, 197int map_groups__clone(struct map_groups *mg,
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
index a3b1e13a05c0..355eecf6bf59 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -27,6 +27,7 @@ static const struct branch_mode branch_modes[] = {
27 BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), 27 BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
28 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND), 28 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
29 BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP), 29 BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP),
30 BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL),
30 BRANCH_END 31 BRANCH_END
31}; 32};
32 33
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 21ed6ee63da9..e48d9da75707 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,4 +1,5 @@
1#include <linux/hw_breakpoint.h> 1#include <linux/hw_breakpoint.h>
2#include <linux/err.h>
2#include "util.h" 3#include "util.h"
3#include "../perf.h" 4#include "../perf.h"
4#include "evlist.h" 5#include "evlist.h"
@@ -10,8 +11,9 @@
10#include "symbol.h" 11#include "symbol.h"
11#include "cache.h" 12#include "cache.h"
12#include "header.h" 13#include "header.h"
14#include "bpf-loader.h"
13#include "debug.h" 15#include "debug.h"
14#include <api/fs/debugfs.h> 16#include <api/fs/tracing_path.h>
15#include "parse-events-bison.h" 17#include "parse-events-bison.h"
16#define YY_EXTRA_TYPE int 18#define YY_EXTRA_TYPE int
17#include "parse-events-flex.h" 19#include "parse-events-flex.h"
@@ -26,6 +28,8 @@
26extern int parse_events_debug; 28extern int parse_events_debug;
27#endif 29#endif
28int parse_events_parse(void *data, void *scanner); 30int parse_events_parse(void *data, void *scanner);
31static int get_config_terms(struct list_head *head_config,
32 struct list_head *head_terms __maybe_unused);
29 33
30static struct perf_pmu_event_symbol *perf_pmu_events_list; 34static struct perf_pmu_event_symbol *perf_pmu_events_list;
31/* 35/*
@@ -386,32 +390,72 @@ int parse_events_add_cache(struct list_head *list, int *idx,
386 return add_event(list, idx, &attr, name, NULL); 390 return add_event(list, idx, &attr, name, NULL);
387} 391}
388 392
393static void tracepoint_error(struct parse_events_error *e, int err,
394 char *sys, char *name)
395{
396 char help[BUFSIZ];
397
398 /*
399 * We get error directly from syscall errno ( > 0),
400 * or from encoded pointer's error ( < 0).
401 */
402 err = abs(err);
403
404 switch (err) {
405 case EACCES:
406 e->str = strdup("can't access trace events");
407 break;
408 case ENOENT:
409 e->str = strdup("unknown tracepoint");
410 break;
411 default:
412 e->str = strdup("failed to add tracepoint");
413 break;
414 }
415
416 tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name);
417 e->help = strdup(help);
418}
419
389static int add_tracepoint(struct list_head *list, int *idx, 420static int add_tracepoint(struct list_head *list, int *idx,
390 char *sys_name, char *evt_name) 421 char *sys_name, char *evt_name,
422 struct parse_events_error *err,
423 struct list_head *head_config)
391{ 424{
392 struct perf_evsel *evsel; 425 struct perf_evsel *evsel;
393 426
394 evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); 427 evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
395 if (!evsel) 428 if (IS_ERR(evsel)) {
396 return -ENOMEM; 429 tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name);
430 return PTR_ERR(evsel);
431 }
397 432
398 list_add_tail(&evsel->node, list); 433 if (head_config) {
434 LIST_HEAD(config_terms);
399 435
436 if (get_config_terms(head_config, &config_terms))
437 return -ENOMEM;
438 list_splice(&config_terms, &evsel->config_terms);
439 }
440
441 list_add_tail(&evsel->node, list);
400 return 0; 442 return 0;
401} 443}
402 444
403static int add_tracepoint_multi_event(struct list_head *list, int *idx, 445static int add_tracepoint_multi_event(struct list_head *list, int *idx,
404 char *sys_name, char *evt_name) 446 char *sys_name, char *evt_name,
447 struct parse_events_error *err,
448 struct list_head *head_config)
405{ 449{
406 char evt_path[MAXPATHLEN]; 450 char evt_path[MAXPATHLEN];
407 struct dirent *evt_ent; 451 struct dirent *evt_ent;
408 DIR *evt_dir; 452 DIR *evt_dir;
409 int ret = 0; 453 int ret = 0, found = 0;
410 454
411 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); 455 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
412 evt_dir = opendir(evt_path); 456 evt_dir = opendir(evt_path);
413 if (!evt_dir) { 457 if (!evt_dir) {
414 perror("Can't open event dir"); 458 tracepoint_error(err, errno, sys_name, evt_name);
415 return -1; 459 return -1;
416 } 460 }
417 461
@@ -425,7 +469,15 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
425 if (!strglobmatch(evt_ent->d_name, evt_name)) 469 if (!strglobmatch(evt_ent->d_name, evt_name))
426 continue; 470 continue;
427 471
428 ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name); 472 found++;
473
474 ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name,
475 err, head_config);
476 }
477
478 if (!found) {
479 tracepoint_error(err, ENOENT, sys_name, evt_name);
480 ret = -1;
429 } 481 }
430 482
431 closedir(evt_dir); 483 closedir(evt_dir);
@@ -433,15 +485,21 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
433} 485}
434 486
435static int add_tracepoint_event(struct list_head *list, int *idx, 487static int add_tracepoint_event(struct list_head *list, int *idx,
436 char *sys_name, char *evt_name) 488 char *sys_name, char *evt_name,
489 struct parse_events_error *err,
490 struct list_head *head_config)
437{ 491{
438 return strpbrk(evt_name, "*?") ? 492 return strpbrk(evt_name, "*?") ?
439 add_tracepoint_multi_event(list, idx, sys_name, evt_name) : 493 add_tracepoint_multi_event(list, idx, sys_name, evt_name,
440 add_tracepoint(list, idx, sys_name, evt_name); 494 err, head_config) :
495 add_tracepoint(list, idx, sys_name, evt_name,
496 err, head_config);
441} 497}
442 498
443static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 499static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
444 char *sys_name, char *evt_name) 500 char *sys_name, char *evt_name,
501 struct parse_events_error *err,
502 struct list_head *head_config)
445{ 503{
446 struct dirent *events_ent; 504 struct dirent *events_ent;
447 DIR *events_dir; 505 DIR *events_dir;
@@ -449,7 +507,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
449 507
450 events_dir = opendir(tracing_events_path); 508 events_dir = opendir(tracing_events_path);
451 if (!events_dir) { 509 if (!events_dir) {
452 perror("Can't open event dir"); 510 tracepoint_error(err, errno, sys_name, evt_name);
453 return -1; 511 return -1;
454 } 512 }
455 513
@@ -465,20 +523,136 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
465 continue; 523 continue;
466 524
467 ret = add_tracepoint_event(list, idx, events_ent->d_name, 525 ret = add_tracepoint_event(list, idx, events_ent->d_name,
468 evt_name); 526 evt_name, err, head_config);
469 } 527 }
470 528
471 closedir(events_dir); 529 closedir(events_dir);
472 return ret; 530 return ret;
473} 531}
474 532
475int parse_events_add_tracepoint(struct list_head *list, int *idx, 533struct __add_bpf_event_param {
476 char *sys, char *event) 534 struct parse_events_evlist *data;
535 struct list_head *list;
536};
537
538static int add_bpf_event(struct probe_trace_event *tev, int fd,
539 void *_param)
477{ 540{
478 if (strpbrk(sys, "*?")) 541 LIST_HEAD(new_evsels);
479 return add_tracepoint_multi_sys(list, idx, sys, event); 542 struct __add_bpf_event_param *param = _param;
480 else 543 struct parse_events_evlist *evlist = param->data;
481 return add_tracepoint_event(list, idx, sys, event); 544 struct list_head *list = param->list;
545 struct perf_evsel *pos;
546 int err;
547
548 pr_debug("add bpf event %s:%s and attach bpf program %d\n",
549 tev->group, tev->event, fd);
550
551 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group,
552 tev->event, evlist->error, NULL);
553 if (err) {
554 struct perf_evsel *evsel, *tmp;
555
556 pr_debug("Failed to add BPF event %s:%s\n",
557 tev->group, tev->event);
558 list_for_each_entry_safe(evsel, tmp, &new_evsels, node) {
559 list_del(&evsel->node);
560 perf_evsel__delete(evsel);
561 }
562 return err;
563 }
564 pr_debug("adding %s:%s\n", tev->group, tev->event);
565
566 list_for_each_entry(pos, &new_evsels, node) {
567 pr_debug("adding %s:%s to %p\n",
568 tev->group, tev->event, pos);
569 pos->bpf_fd = fd;
570 }
571 list_splice(&new_evsels, list);
572 return 0;
573}
574
575int parse_events_load_bpf_obj(struct parse_events_evlist *data,
576 struct list_head *list,
577 struct bpf_object *obj)
578{
579 int err;
580 char errbuf[BUFSIZ];
581 struct __add_bpf_event_param param = {data, list};
582 static bool registered_unprobe_atexit = false;
583
584 if (IS_ERR(obj) || !obj) {
585 snprintf(errbuf, sizeof(errbuf),
586 "Internal error: load bpf obj with NULL");
587 err = -EINVAL;
588 goto errout;
589 }
590
591 /*
592 * Register atexit handler before calling bpf__probe() so
593 * bpf__probe() don't need to unprobe probe points its already
594 * created when failure.
595 */
596 if (!registered_unprobe_atexit) {
597 atexit(bpf__clear);
598 registered_unprobe_atexit = true;
599 }
600
601 err = bpf__probe(obj);
602 if (err) {
603 bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf));
604 goto errout;
605 }
606
607 err = bpf__load(obj);
608 if (err) {
609 bpf__strerror_load(obj, err, errbuf, sizeof(errbuf));
610 goto errout;
611 }
612
613 err = bpf__foreach_tev(obj, add_bpf_event, &param);
614 if (err) {
615 snprintf(errbuf, sizeof(errbuf),
616 "Attach events in BPF object failed");
617 goto errout;
618 }
619
620 return 0;
621errout:
622 data->error->help = strdup("(add -v to see detail)");
623 data->error->str = strdup(errbuf);
624 return err;
625}
626
627int parse_events_load_bpf(struct parse_events_evlist *data,
628 struct list_head *list,
629 char *bpf_file_name,
630 bool source)
631{
632 struct bpf_object *obj;
633
634 obj = bpf__prepare_load(bpf_file_name, source);
635 if (IS_ERR(obj)) {
636 char errbuf[BUFSIZ];
637 int err;
638
639 err = PTR_ERR(obj);
640
641 if (err == -ENOTSUP)
642 snprintf(errbuf, sizeof(errbuf),
643 "BPF support is not compiled");
644 else
645 bpf__strerror_prepare_load(bpf_file_name,
646 source,
647 -err, errbuf,
648 sizeof(errbuf));
649
650 data->error->help = strdup("(add -v to see detail)");
651 data->error->str = strdup(errbuf);
652 return err;
653 }
654
655 return parse_events_load_bpf_obj(data, list, obj);
482} 656}
483 657
484static int 658static int
@@ -565,9 +739,13 @@ static int check_type_val(struct parse_events_term *term,
565 return -EINVAL; 739 return -EINVAL;
566} 740}
567 741
568static int config_term(struct perf_event_attr *attr, 742typedef int config_term_func_t(struct perf_event_attr *attr,
569 struct parse_events_term *term, 743 struct parse_events_term *term,
570 struct parse_events_error *err) 744 struct parse_events_error *err);
745
746static int config_term_common(struct perf_event_attr *attr,
747 struct parse_events_term *term,
748 struct parse_events_error *err)
571{ 749{
572#define CHECK_TYPE_VAL(type) \ 750#define CHECK_TYPE_VAL(type) \
573do { \ 751do { \
@@ -576,12 +754,6 @@ do { \
576} while (0) 754} while (0)
577 755
578 switch (term->type_term) { 756 switch (term->type_term) {
579 case PARSE_EVENTS__TERM_TYPE_USER:
580 /*
581 * Always succeed for sysfs terms, as we dont know
582 * at this point what type they need to have.
583 */
584 return 0;
585 case PARSE_EVENTS__TERM_TYPE_CONFIG: 757 case PARSE_EVENTS__TERM_TYPE_CONFIG:
586 CHECK_TYPE_VAL(NUM); 758 CHECK_TYPE_VAL(NUM);
587 attr->config = term->val.num; 759 attr->config = term->val.num;
@@ -620,10 +792,19 @@ do { \
620 case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 792 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
621 CHECK_TYPE_VAL(NUM); 793 CHECK_TYPE_VAL(NUM);
622 break; 794 break;
795 case PARSE_EVENTS__TERM_TYPE_INHERIT:
796 CHECK_TYPE_VAL(NUM);
797 break;
798 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
799 CHECK_TYPE_VAL(NUM);
800 break;
623 case PARSE_EVENTS__TERM_TYPE_NAME: 801 case PARSE_EVENTS__TERM_TYPE_NAME:
624 CHECK_TYPE_VAL(STR); 802 CHECK_TYPE_VAL(STR);
625 break; 803 break;
626 default: 804 default:
805 err->str = strdup("unknown term");
806 err->idx = term->err_term;
807 err->help = parse_events_formats_error_string(NULL);
627 return -EINVAL; 808 return -EINVAL;
628 } 809 }
629 810
@@ -631,9 +812,46 @@ do { \
631#undef CHECK_TYPE_VAL 812#undef CHECK_TYPE_VAL
632} 813}
633 814
815static int config_term_pmu(struct perf_event_attr *attr,
816 struct parse_events_term *term,
817 struct parse_events_error *err)
818{
819 if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER)
820 /*
821 * Always succeed for sysfs terms, as we dont know
822 * at this point what type they need to have.
823 */
824 return 0;
825 else
826 return config_term_common(attr, term, err);
827}
828
829static int config_term_tracepoint(struct perf_event_attr *attr,
830 struct parse_events_term *term,
831 struct parse_events_error *err)
832{
833 switch (term->type_term) {
834 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
835 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
836 case PARSE_EVENTS__TERM_TYPE_INHERIT:
837 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
838 return config_term_common(attr, term, err);
839 default:
840 if (err) {
841 err->idx = term->err_term;
842 err->str = strdup("unknown term");
843 err->help = strdup("valid terms: call-graph,stack-size\n");
844 }
845 return -EINVAL;
846 }
847
848 return 0;
849}
850
634static int config_attr(struct perf_event_attr *attr, 851static int config_attr(struct perf_event_attr *attr,
635 struct list_head *head, 852 struct list_head *head,
636 struct parse_events_error *err) 853 struct parse_events_error *err,
854 config_term_func_t config_term)
637{ 855{
638 struct parse_events_term *term; 856 struct parse_events_term *term;
639 857
@@ -680,6 +898,12 @@ do { \
680 case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 898 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
681 ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); 899 ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
682 break; 900 break;
901 case PARSE_EVENTS__TERM_TYPE_INHERIT:
902 ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 1 : 0);
903 break;
904 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
905 ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1);
906 break;
683 default: 907 default:
684 break; 908 break;
685 } 909 }
@@ -688,6 +912,27 @@ do { \
688 return 0; 912 return 0;
689} 913}
690 914
915int parse_events_add_tracepoint(struct list_head *list, int *idx,
916 char *sys, char *event,
917 struct parse_events_error *err,
918 struct list_head *head_config)
919{
920 if (head_config) {
921 struct perf_event_attr attr;
922
923 if (config_attr(&attr, head_config, err,
924 config_term_tracepoint))
925 return -EINVAL;
926 }
927
928 if (strpbrk(sys, "*?"))
929 return add_tracepoint_multi_sys(list, idx, sys, event,
930 err, head_config);
931 else
932 return add_tracepoint_event(list, idx, sys, event,
933 err, head_config);
934}
935
691int parse_events_add_numeric(struct parse_events_evlist *data, 936int parse_events_add_numeric(struct parse_events_evlist *data,
692 struct list_head *list, 937 struct list_head *list,
693 u32 type, u64 config, 938 u32 type, u64 config,
@@ -701,7 +946,8 @@ int parse_events_add_numeric(struct parse_events_evlist *data,
701 attr.config = config; 946 attr.config = config;
702 947
703 if (head_config) { 948 if (head_config) {
704 if (config_attr(&attr, head_config, data->error)) 949 if (config_attr(&attr, head_config, data->error,
950 config_term_common))
705 return -EINVAL; 951 return -EINVAL;
706 952
707 if (get_config_terms(head_config, &config_terms)) 953 if (get_config_terms(head_config, &config_terms))
@@ -761,7 +1007,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
761 * Configure hardcoded terms first, no need to check 1007 * Configure hardcoded terms first, no need to check
762 * return value when called with fail == 0 ;) 1008 * return value when called with fail == 0 ;)
763 */ 1009 */
764 if (config_attr(&attr, head_config, data->error)) 1010 if (config_attr(&attr, head_config, data->error, config_term_pmu))
765 return -EINVAL; 1011 return -EINVAL;
766 1012
767 if (get_config_terms(head_config, &config_terms)) 1013 if (get_config_terms(head_config, &config_terms))
@@ -793,6 +1039,11 @@ void parse_events__set_leader(char *name, struct list_head *list)
793{ 1039{
794 struct perf_evsel *leader; 1040 struct perf_evsel *leader;
795 1041
1042 if (list_empty(list)) {
1043 WARN_ONCE(true, "WARNING: failed to set leader: empty list");
1044 return;
1045 }
1046
796 __perf_evlist__set_leader(list); 1047 __perf_evlist__set_leader(list);
797 leader = list_entry(list->next, struct perf_evsel, node); 1048 leader = list_entry(list->next, struct perf_evsel, node);
798 leader->group_name = name ? strdup(name) : NULL; 1049 leader->group_name = name ? strdup(name) : NULL;
@@ -819,6 +1070,7 @@ struct event_modifier {
819 int eG; 1070 int eG;
820 int eI; 1071 int eI;
821 int precise; 1072 int precise;
1073 int precise_max;
822 int exclude_GH; 1074 int exclude_GH;
823 int sample_read; 1075 int sample_read;
824 int pinned; 1076 int pinned;
@@ -834,6 +1086,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
834 int eG = evsel ? evsel->attr.exclude_guest : 0; 1086 int eG = evsel ? evsel->attr.exclude_guest : 0;
835 int eI = evsel ? evsel->attr.exclude_idle : 0; 1087 int eI = evsel ? evsel->attr.exclude_idle : 0;
836 int precise = evsel ? evsel->attr.precise_ip : 0; 1088 int precise = evsel ? evsel->attr.precise_ip : 0;
1089 int precise_max = 0;
837 int sample_read = 0; 1090 int sample_read = 0;
838 int pinned = evsel ? evsel->attr.pinned : 0; 1091 int pinned = evsel ? evsel->attr.pinned : 0;
839 1092
@@ -870,6 +1123,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
870 /* use of precise requires exclude_guest */ 1123 /* use of precise requires exclude_guest */
871 if (!exclude_GH) 1124 if (!exclude_GH)
872 eG = 1; 1125 eG = 1;
1126 } else if (*str == 'P') {
1127 precise_max = 1;
873 } else if (*str == 'S') { 1128 } else if (*str == 'S') {
874 sample_read = 1; 1129 sample_read = 1;
875 } else if (*str == 'D') { 1130 } else if (*str == 'D') {
@@ -900,6 +1155,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
900 mod->eG = eG; 1155 mod->eG = eG;
901 mod->eI = eI; 1156 mod->eI = eI;
902 mod->precise = precise; 1157 mod->precise = precise;
1158 mod->precise_max = precise_max;
903 mod->exclude_GH = exclude_GH; 1159 mod->exclude_GH = exclude_GH;
904 mod->sample_read = sample_read; 1160 mod->sample_read = sample_read;
905 mod->pinned = pinned; 1161 mod->pinned = pinned;
@@ -916,7 +1172,7 @@ static int check_modifier(char *str)
916 char *p = str; 1172 char *p = str;
917 1173
918 /* The sizeof includes 0 byte as well. */ 1174 /* The sizeof includes 0 byte as well. */
919 if (strlen(str) > (sizeof("ukhGHpppSDI") - 1)) 1175 if (strlen(str) > (sizeof("ukhGHpppPSDI") - 1))
920 return -1; 1176 return -1;
921 1177
922 while (*p) { 1178 while (*p) {
@@ -955,6 +1211,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
955 evsel->attr.exclude_idle = mod.eI; 1211 evsel->attr.exclude_idle = mod.eI;
956 evsel->exclude_GH = mod.exclude_GH; 1212 evsel->exclude_GH = mod.exclude_GH;
957 evsel->sample_read = mod.sample_read; 1213 evsel->sample_read = mod.sample_read;
1214 evsel->precise_max = mod.precise_max;
958 1215
959 if (perf_evsel__is_group_leader(evsel)) 1216 if (perf_evsel__is_group_leader(evsel))
960 evsel->attr.pinned = mod.pinned; 1217 evsel->attr.pinned = mod.pinned;
@@ -1142,6 +1399,11 @@ int parse_events(struct perf_evlist *evlist, const char *str,
1142 if (!ret) { 1399 if (!ret) {
1143 struct perf_evsel *last; 1400 struct perf_evsel *last;
1144 1401
1402 if (list_empty(&data.list)) {
1403 WARN_ONCE(true, "WARNING: event parser found nothing");
1404 return -1;
1405 }
1406
1145 perf_evlist__splice_list_tail(evlist, &data.list); 1407 perf_evlist__splice_list_tail(evlist, &data.list);
1146 evlist->nr_groups += data.nr_groups; 1408 evlist->nr_groups += data.nr_groups;
1147 last = perf_evlist__last(evlist); 1409 last = perf_evlist__last(evlist);
@@ -1251,6 +1513,12 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist,
1251 struct perf_evsel *last = NULL; 1513 struct perf_evsel *last = NULL;
1252 int err; 1514 int err;
1253 1515
1516 /*
1517 * Don't return when list_empty, give func a chance to report
1518 * error when it found last == NULL.
1519 *
1520 * So no need to WARN here, let *func do this.
1521 */
1254 if (evlist->nr_entries > 0) 1522 if (evlist->nr_entries > 0)
1255 last = perf_evlist__last(evlist); 1523 last = perf_evlist__last(evlist);
1256 1524
@@ -1419,7 +1687,7 @@ restart:
1419 printf(" %-50s [%s]\n", evt_list[evt_i++], 1687 printf(" %-50s [%s]\n", evt_list[evt_i++],
1420 event_type_descriptors[PERF_TYPE_TRACEPOINT]); 1688 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1421 } 1689 }
1422 if (evt_num) 1690 if (evt_num && pager_in_use())
1423 printf("\n"); 1691 printf("\n");
1424 1692
1425out_free: 1693out_free:
@@ -1575,7 +1843,7 @@ restart:
1575 printf(" %-50s [%s]\n", evt_list[evt_i++], 1843 printf(" %-50s [%s]\n", evt_list[evt_i++],
1576 event_type_descriptors[PERF_TYPE_HW_CACHE]); 1844 event_type_descriptors[PERF_TYPE_HW_CACHE]);
1577 } 1845 }
1578 if (evt_num) 1846 if (evt_num && pager_in_use())
1579 printf("\n"); 1847 printf("\n");
1580 1848
1581out_free: 1849out_free:
@@ -1648,7 +1916,7 @@ restart:
1648 } 1916 }
1649 printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); 1917 printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
1650 } 1918 }
1651 if (evt_num) 1919 if (evt_num && pager_in_use())
1652 printf("\n"); 1920 printf("\n");
1653 1921
1654out_free: 1922out_free:
@@ -1689,13 +1957,14 @@ void print_events(const char *event_glob, bool name_only)
1689 printf(" %-50s [%s]\n", 1957 printf(" %-50s [%s]\n",
1690 "cpu/t1=v1[,t2=v2,t3 ...]/modifier", 1958 "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
1691 event_type_descriptors[PERF_TYPE_RAW]); 1959 event_type_descriptors[PERF_TYPE_RAW]);
1692 printf(" (see 'man perf-list' on how to encode it)\n"); 1960 if (pager_in_use())
1693 printf("\n"); 1961 printf(" (see 'man perf-list' on how to encode it)\n\n");
1694 1962
1695 printf(" %-50s [%s]\n", 1963 printf(" %-50s [%s]\n",
1696 "mem:<addr>[/len][:access]", 1964 "mem:<addr>[/len][:access]",
1697 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1965 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
1698 printf("\n"); 1966 if (pager_in_use())
1967 printf("\n");
1699 } 1968 }
1700 1969
1701 print_tracepoint_events(NULL, NULL, name_only); 1970 print_tracepoint_events(NULL, NULL, name_only);
@@ -1811,3 +2080,29 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
1811 err->str = strdup(str); 2080 err->str = strdup(str);
1812 WARN_ONCE(!err->str, "WARNING: failed to allocate error string"); 2081 WARN_ONCE(!err->str, "WARNING: failed to allocate error string");
1813} 2082}
2083
2084/*
2085 * Return string contains valid config terms of an event.
2086 * @additional_terms: For terms such as PMU sysfs terms.
2087 */
2088char *parse_events_formats_error_string(char *additional_terms)
2089{
2090 char *str;
2091 static const char *static_terms = "config,config1,config2,name,"
2092 "period,freq,branch_type,time,"
2093 "call-graph,stack-size\n";
2094
2095 /* valid terms */
2096 if (additional_terms) {
2097 if (!asprintf(&str, "valid terms: %s,%s",
2098 additional_terms, static_terms))
2099 goto fail;
2100 } else {
2101 if (!asprintf(&str, "valid terms: %s", static_terms))
2102 goto fail;
2103 }
2104 return str;
2105
2106fail:
2107 return NULL;
2108}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index a09b0e210997..f1a6db107241 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -67,6 +67,8 @@ enum {
67 PARSE_EVENTS__TERM_TYPE_TIME, 67 PARSE_EVENTS__TERM_TYPE_TIME,
68 PARSE_EVENTS__TERM_TYPE_CALLGRAPH, 68 PARSE_EVENTS__TERM_TYPE_CALLGRAPH,
69 PARSE_EVENTS__TERM_TYPE_STACKSIZE, 69 PARSE_EVENTS__TERM_TYPE_STACKSIZE,
70 PARSE_EVENTS__TERM_TYPE_NOINHERIT,
71 PARSE_EVENTS__TERM_TYPE_INHERIT
70}; 72};
71 73
72struct parse_events_term { 74struct parse_events_term {
@@ -118,7 +120,18 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add);
118int parse_events__modifier_group(struct list_head *list, char *event_mod); 120int parse_events__modifier_group(struct list_head *list, char *event_mod);
119int parse_events_name(struct list_head *list, char *name); 121int parse_events_name(struct list_head *list, char *name);
120int parse_events_add_tracepoint(struct list_head *list, int *idx, 122int parse_events_add_tracepoint(struct list_head *list, int *idx,
121 char *sys, char *event); 123 char *sys, char *event,
124 struct parse_events_error *error,
125 struct list_head *head_config);
126int parse_events_load_bpf(struct parse_events_evlist *data,
127 struct list_head *list,
128 char *bpf_file_name,
129 bool source);
130/* Provide this function for perf test */
131struct bpf_object;
132int parse_events_load_bpf_obj(struct parse_events_evlist *data,
133 struct list_head *list,
134 struct bpf_object *obj);
122int parse_events_add_numeric(struct parse_events_evlist *data, 135int parse_events_add_numeric(struct parse_events_evlist *data,
123 struct list_head *list, 136 struct list_head *list,
124 u32 type, u64 config, 137 u32 type, u64 config,
@@ -155,5 +168,6 @@ int print_hwcache_events(const char *event_glob, bool name_only);
155extern int is_valid_tracepoint(const char *event_string); 168extern int is_valid_tracepoint(const char *event_string);
156 169
157int valid_event_mount(const char *eventfs); 170int valid_event_mount(const char *eventfs);
171char *parse_events_formats_error_string(char *additional_terms);
158 172
159#endif /* __PERF_PARSE_EVENTS_H */ 173#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 936d566f48d8..58c5831ffd5c 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -115,6 +115,8 @@ do { \
115group [^,{}/]*[{][^}]*[}][^,{}/]* 115group [^,{}/]*[{][^}]*[}][^,{}/]*
116event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* 116event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
117event [^,{}/]+ 117event [^,{}/]+
118bpf_object .*\.(o|bpf)
119bpf_source .*\.c
118 120
119num_dec [0-9]+ 121num_dec [0-9]+
120num_hex 0x[a-fA-F0-9]+ 122num_hex 0x[a-fA-F0-9]+
@@ -122,7 +124,7 @@ num_raw_hex [a-fA-F0-9]+
122name [a-zA-Z_*?][a-zA-Z0-9_*?.]* 124name [a-zA-Z_*?][a-zA-Z0-9_*?.]*
123name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]* 125name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]*
124/* If you add a modifier you need to update check_modifier() */ 126/* If you add a modifier you need to update check_modifier() */
125modifier_event [ukhpGHSDI]+ 127modifier_event [ukhpPGHSDI]+
126modifier_bp [rwx]{1,3} 128modifier_bp [rwx]{1,3}
127 129
128%% 130%%
@@ -159,6 +161,8 @@ modifier_bp [rwx]{1,3}
159 } 161 }
160 162
161{event_pmu} | 163{event_pmu} |
164{bpf_object} |
165{bpf_source} |
162{event} { 166{event} {
163 BEGIN(INITIAL); 167 BEGIN(INITIAL);
164 REWIND(1); 168 REWIND(1);
@@ -174,7 +178,7 @@ modifier_bp [rwx]{1,3}
174 178
175<config>{ 179<config>{
176 /* 180 /*
177 * Please update formats_error_string any time 181 * Please update parse_events_formats_error_string any time
178 * new static term is added. 182 * new static term is added.
179 */ 183 */
180config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } 184config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
@@ -187,6 +191,8 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE
187time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } 191time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
188call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } 192call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
189stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } 193stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
194inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
195no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
190, { return ','; } 196, { return ','; }
191"/" { BEGIN(INITIAL); return '/'; } 197"/" { BEGIN(INITIAL); return '/'; }
192{name_minus} { return str(yyscanner, PE_NAME); } 198{name_minus} { return str(yyscanner, PE_NAME); }
@@ -264,6 +270,8 @@ r{num_raw_hex} { return raw(yyscanner); }
264{num_hex} { return value(yyscanner, 16); } 270{num_hex} { return value(yyscanner, 16); }
265 271
266{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 272{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
273{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); }
274{bpf_source} { return str(yyscanner, PE_BPF_SOURCE); }
267{name} { return pmu_str_check(yyscanner); } 275{name} { return pmu_str_check(yyscanner); }
268"/" { BEGIN(config); return '/'; } 276"/" { BEGIN(config); return '/'; }
269- { return '-'; } 277- { return '-'; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 9cd70819c795..ad379968d4c1 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -42,6 +42,7 @@ static inc_group_count(struct list_head *list,
42%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 42%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
43%token PE_EVENT_NAME 43%token PE_EVENT_NAME
44%token PE_NAME 44%token PE_NAME
45%token PE_BPF_OBJECT PE_BPF_SOURCE
45%token PE_MODIFIER_EVENT PE_MODIFIER_BP 46%token PE_MODIFIER_EVENT PE_MODIFIER_BP
46%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
47%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
@@ -53,6 +54,8 @@ static inc_group_count(struct list_head *list,
53%type <num> PE_RAW 54%type <num> PE_RAW
54%type <num> PE_TERM 55%type <num> PE_TERM
55%type <str> PE_NAME 56%type <str> PE_NAME
57%type <str> PE_BPF_OBJECT
58%type <str> PE_BPF_SOURCE
56%type <str> PE_NAME_CACHE_TYPE 59%type <str> PE_NAME_CACHE_TYPE
57%type <str> PE_NAME_CACHE_OP_RESULT 60%type <str> PE_NAME_CACHE_OP_RESULT
58%type <str> PE_MODIFIER_EVENT 61%type <str> PE_MODIFIER_EVENT
@@ -67,8 +70,10 @@ static inc_group_count(struct list_head *list,
67%type <head> event_legacy_cache 70%type <head> event_legacy_cache
68%type <head> event_legacy_mem 71%type <head> event_legacy_mem
69%type <head> event_legacy_tracepoint 72%type <head> event_legacy_tracepoint
73%type <tracepoint_name> tracepoint_name
70%type <head> event_legacy_numeric 74%type <head> event_legacy_numeric
71%type <head> event_legacy_raw 75%type <head> event_legacy_raw
76%type <head> event_bpf_file
72%type <head> event_def 77%type <head> event_def
73%type <head> event_mod 78%type <head> event_mod
74%type <head> event_name 79%type <head> event_name
@@ -84,6 +89,10 @@ static inc_group_count(struct list_head *list,
84 u64 num; 89 u64 num;
85 struct list_head *head; 90 struct list_head *head;
86 struct parse_events_term *term; 91 struct parse_events_term *term;
92 struct tracepoint_name {
93 char *sys;
94 char *event;
95 } tracepoint_name;
87} 96}
88%% 97%%
89 98
@@ -198,7 +207,8 @@ event_def: event_pmu |
198 event_legacy_mem | 207 event_legacy_mem |
199 event_legacy_tracepoint sep_dc | 208 event_legacy_tracepoint sep_dc |
200 event_legacy_numeric sep_dc | 209 event_legacy_numeric sep_dc |
201 event_legacy_raw sep_dc 210 event_legacy_raw sep_dc |
211 event_bpf_file
202 212
203event_pmu: 213event_pmu:
204PE_NAME '/' event_config '/' 214PE_NAME '/' event_config '/'
@@ -368,36 +378,60 @@ PE_PREFIX_MEM PE_VALUE sep_dc
368} 378}
369 379
370event_legacy_tracepoint: 380event_legacy_tracepoint:
371PE_NAME '-' PE_NAME ':' PE_NAME 381tracepoint_name
372{ 382{
373 struct parse_events_evlist *data = _data; 383 struct parse_events_evlist *data = _data;
384 struct parse_events_error *error = data->error;
374 struct list_head *list; 385 struct list_head *list;
375 char sys_name[128];
376 snprintf(&sys_name, 128, "%s-%s", $1, $3);
377 386
378 ALLOC_LIST(list); 387 ALLOC_LIST(list);
379 ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5)); 388 if (error)
389 error->idx = @1.first_column;
390
391 if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
392 error, NULL))
393 return -1;
394
380 $$ = list; 395 $$ = list;
381} 396}
382| 397|
383PE_NAME ':' PE_NAME 398tracepoint_name '/' event_config '/'
384{ 399{
385 struct parse_events_evlist *data = _data; 400 struct parse_events_evlist *data = _data;
401 struct parse_events_error *error = data->error;
386 struct list_head *list; 402 struct list_head *list;
387 403
388 ALLOC_LIST(list); 404 ALLOC_LIST(list);
389 if (parse_events_add_tracepoint(list, &data->idx, $1, $3)) { 405 if (error)
390 struct parse_events_error *error = data->error; 406 error->idx = @1.first_column;
391 407
392 if (error) { 408 if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
393 error->idx = @1.first_column; 409 error, $3))
394 error->str = strdup("unknown tracepoint");
395 }
396 return -1; 410 return -1;
397 } 411
398 $$ = list; 412 $$ = list;
399} 413}
400 414
415tracepoint_name:
416PE_NAME '-' PE_NAME ':' PE_NAME
417{
418 char sys_name[128];
419 struct tracepoint_name tracepoint;
420
421 snprintf(&sys_name, 128, "%s-%s", $1, $3);
422 tracepoint.sys = &sys_name;
423 tracepoint.event = $5;
424
425 $$ = tracepoint;
426}
427|
428PE_NAME ':' PE_NAME
429{
430 struct tracepoint_name tracepoint = {$1, $3};
431
432 $$ = tracepoint;
433}
434
401event_legacy_numeric: 435event_legacy_numeric:
402PE_VALUE ':' PE_VALUE 436PE_VALUE ':' PE_VALUE
403{ 437{
@@ -420,6 +454,28 @@ PE_RAW
420 $$ = list; 454 $$ = list;
421} 455}
422 456
457event_bpf_file:
458PE_BPF_OBJECT
459{
460 struct parse_events_evlist *data = _data;
461 struct parse_events_error *error = data->error;
462 struct list_head *list;
463
464 ALLOC_LIST(list);
465 ABORT_ON(parse_events_load_bpf(data, list, $1, false));
466 $$ = list;
467}
468|
469PE_BPF_SOURCE
470{
471 struct parse_events_evlist *data = _data;
472 struct list_head *list;
473
474 ALLOC_LIST(list);
475 ABORT_ON(parse_events_load_bpf(data, list, $1, true));
476 $$ = list;
477}
478
423start_terms: event_config 479start_terms: event_config
424{ 480{
425 struct parse_events_terms *data = _data; 481 struct parse_events_terms *data = _data;
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 01626be2a8eb..9fca09296eb3 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -2,10 +2,13 @@
2#include "parse-options.h" 2#include "parse-options.h"
3#include "cache.h" 3#include "cache.h"
4#include "header.h" 4#include "header.h"
5#include <linux/string.h>
5 6
6#define OPT_SHORT 1 7#define OPT_SHORT 1
7#define OPT_UNSET 2 8#define OPT_UNSET 2
8 9
10static struct strbuf error_buf = STRBUF_INIT;
11
9static int opterror(const struct option *opt, const char *reason, int flags) 12static int opterror(const struct option *opt, const char *reason, int flags)
10{ 13{
11 if (flags & OPT_SHORT) 14 if (flags & OPT_SHORT)
@@ -372,7 +375,8 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
372} 375}
373 376
374static int usage_with_options_internal(const char * const *, 377static int usage_with_options_internal(const char * const *,
375 const struct option *, int); 378 const struct option *, int,
379 struct parse_opt_ctx_t *);
376 380
377int parse_options_step(struct parse_opt_ctx_t *ctx, 381int parse_options_step(struct parse_opt_ctx_t *ctx,
378 const struct option *options, 382 const struct option *options,
@@ -396,8 +400,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
396 400
397 if (arg[1] != '-') { 401 if (arg[1] != '-') {
398 ctx->opt = ++arg; 402 ctx->opt = ++arg;
399 if (internal_help && *ctx->opt == 'h') 403 if (internal_help && *ctx->opt == 'h') {
400 return usage_with_options_internal(usagestr, options, 0); 404 return usage_with_options_internal(usagestr, options, 0, ctx);
405 }
401 switch (parse_short_opt(ctx, options)) { 406 switch (parse_short_opt(ctx, options)) {
402 case -1: 407 case -1:
403 return parse_options_usage(usagestr, options, arg, 1); 408 return parse_options_usage(usagestr, options, arg, 1);
@@ -412,7 +417,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
412 check_typos(arg, options); 417 check_typos(arg, options);
413 while (ctx->opt) { 418 while (ctx->opt) {
414 if (internal_help && *ctx->opt == 'h') 419 if (internal_help && *ctx->opt == 'h')
415 return usage_with_options_internal(usagestr, options, 0); 420 return usage_with_options_internal(usagestr, options, 0, ctx);
416 arg = ctx->opt; 421 arg = ctx->opt;
417 switch (parse_short_opt(ctx, options)) { 422 switch (parse_short_opt(ctx, options)) {
418 case -1: 423 case -1:
@@ -445,9 +450,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
445 450
446 arg += 2; 451 arg += 2;
447 if (internal_help && !strcmp(arg, "help-all")) 452 if (internal_help && !strcmp(arg, "help-all"))
448 return usage_with_options_internal(usagestr, options, 1); 453 return usage_with_options_internal(usagestr, options, 1, ctx);
449 if (internal_help && !strcmp(arg, "help")) 454 if (internal_help && !strcmp(arg, "help"))
450 return usage_with_options_internal(usagestr, options, 0); 455 return usage_with_options_internal(usagestr, options, 0, ctx);
451 if (!strcmp(arg, "list-opts")) 456 if (!strcmp(arg, "list-opts"))
452 return PARSE_OPT_LIST_OPTS; 457 return PARSE_OPT_LIST_OPTS;
453 if (!strcmp(arg, "list-cmds")) 458 if (!strcmp(arg, "list-cmds"))
@@ -496,7 +501,7 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
496{ 501{
497 struct parse_opt_ctx_t ctx; 502 struct parse_opt_ctx_t ctx;
498 503
499 perf_header__set_cmdline(argc, argv); 504 perf_env__set_cmdline(&perf_env, argc, argv);
500 505
501 /* build usage string if it's not provided */ 506 /* build usage string if it's not provided */
502 if (subcommands && !usagestr[0]) { 507 if (subcommands && !usagestr[0]) {
@@ -537,9 +542,11 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
537 exit(130); 542 exit(130);
538 default: /* PARSE_OPT_UNKNOWN */ 543 default: /* PARSE_OPT_UNKNOWN */
539 if (ctx.argv[0][1] == '-') { 544 if (ctx.argv[0][1] == '-') {
540 error("unknown option `%s'", ctx.argv[0] + 2); 545 strbuf_addf(&error_buf, "unknown option `%s'",
546 ctx.argv[0] + 2);
541 } else { 547 } else {
542 error("unknown switch `%c'", *ctx.opt); 548 strbuf_addf(&error_buf, "unknown switch `%c'",
549 *ctx.opt);
543 } 550 }
544 usage_with_options(usagestr, options); 551 usage_with_options(usagestr, options);
545 } 552 }
@@ -642,13 +649,93 @@ static void print_option_help(const struct option *opts, int full)
642 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); 649 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
643} 650}
644 651
652static int option__cmp(const void *va, const void *vb)
653{
654 const struct option *a = va, *b = vb;
655 int sa = tolower(a->short_name), sb = tolower(b->short_name), ret;
656
657 if (sa == 0)
658 sa = 'z' + 1;
659 if (sb == 0)
660 sb = 'z' + 1;
661
662 ret = sa - sb;
663
664 if (ret == 0) {
665 const char *la = a->long_name ?: "",
666 *lb = b->long_name ?: "";
667 ret = strcmp(la, lb);
668 }
669
670 return ret;
671}
672
673static struct option *options__order(const struct option *opts)
674{
675 int nr_opts = 0;
676 const struct option *o = opts;
677 struct option *ordered;
678
679 for (o = opts; o->type != OPTION_END; o++)
680 ++nr_opts;
681
682 ordered = memdup(opts, sizeof(*o) * (nr_opts + 1));
683 if (ordered == NULL)
684 goto out;
685
686 qsort(ordered, nr_opts, sizeof(*o), option__cmp);
687out:
688 return ordered;
689}
690
691static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx)
692{
693 int i;
694
695 for (i = 1; i < ctx->argc; ++i) {
696 const char *arg = ctx->argv[i];
697
698 if (arg[0] != '-') {
699 if (arg[1] == '\0') {
700 if (arg[0] == opt->short_name)
701 return true;
702 continue;
703 }
704
705 if (opt->long_name && strcmp(opt->long_name, arg) == 0)
706 return true;
707
708 if (opt->help && strcasestr(opt->help, arg) != NULL)
709 return true;
710
711 continue;
712 }
713
714 if (arg[1] == opt->short_name ||
715 (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0))
716 return true;
717 }
718
719 return false;
720}
721
645int usage_with_options_internal(const char * const *usagestr, 722int usage_with_options_internal(const char * const *usagestr,
646 const struct option *opts, int full) 723 const struct option *opts, int full,
724 struct parse_opt_ctx_t *ctx)
647{ 725{
726 struct option *ordered;
727
648 if (!usagestr) 728 if (!usagestr)
649 return PARSE_OPT_HELP; 729 return PARSE_OPT_HELP;
650 730
651 fprintf(stderr, "\n usage: %s\n", *usagestr++); 731 setup_pager();
732
733 if (strbuf_avail(&error_buf)) {
734 fprintf(stderr, " Error: %s\n", error_buf.buf);
735 strbuf_release(&error_buf);
736 }
737
738 fprintf(stderr, "\n Usage: %s\n", *usagestr++);
652 while (*usagestr && **usagestr) 739 while (*usagestr && **usagestr)
653 fprintf(stderr, " or: %s\n", *usagestr++); 740 fprintf(stderr, " or: %s\n", *usagestr++);
654 while (*usagestr) { 741 while (*usagestr) {
@@ -661,11 +748,20 @@ int usage_with_options_internal(const char * const *usagestr,
661 if (opts->type != OPTION_GROUP) 748 if (opts->type != OPTION_GROUP)
662 fputc('\n', stderr); 749 fputc('\n', stderr);
663 750
664 for ( ; opts->type != OPTION_END; opts++) 751 ordered = options__order(opts);
752 if (ordered)
753 opts = ordered;
754
755 for ( ; opts->type != OPTION_END; opts++) {
756 if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx))
757 continue;
665 print_option_help(opts, full); 758 print_option_help(opts, full);
759 }
666 760
667 fputc('\n', stderr); 761 fputc('\n', stderr);
668 762
763 free(ordered);
764
669 return PARSE_OPT_HELP; 765 return PARSE_OPT_HELP;
670} 766}
671 767
@@ -673,7 +769,22 @@ void usage_with_options(const char * const *usagestr,
673 const struct option *opts) 769 const struct option *opts)
674{ 770{
675 exit_browser(false); 771 exit_browser(false);
676 usage_with_options_internal(usagestr, opts, 0); 772 usage_with_options_internal(usagestr, opts, 0, NULL);
773 exit(129);
774}
775
776void usage_with_options_msg(const char * const *usagestr,
777 const struct option *opts, const char *fmt, ...)
778{
779 va_list ap;
780
781 exit_browser(false);
782
783 va_start(ap, fmt);
784 strbuf_addv(&error_buf, fmt, ap);
785 va_end(ap);
786
787 usage_with_options_internal(usagestr, opts, 0, NULL);
677 exit(129); 788 exit(129);
678} 789}
679 790
@@ -684,7 +795,7 @@ int parse_options_usage(const char * const *usagestr,
684 if (!usagestr) 795 if (!usagestr)
685 goto opt; 796 goto opt;
686 797
687 fprintf(stderr, "\n usage: %s\n", *usagestr++); 798 fprintf(stderr, "\n Usage: %s\n", *usagestr++);
688 while (*usagestr && **usagestr) 799 while (*usagestr && **usagestr)
689 fprintf(stderr, " or: %s\n", *usagestr++); 800 fprintf(stderr, " or: %s\n", *usagestr++);
690 while (*usagestr) { 801 while (*usagestr) {
@@ -698,24 +809,23 @@ int parse_options_usage(const char * const *usagestr,
698opt: 809opt:
699 for ( ; opts->type != OPTION_END; opts++) { 810 for ( ; opts->type != OPTION_END; opts++) {
700 if (short_opt) { 811 if (short_opt) {
701 if (opts->short_name == *optstr) 812 if (opts->short_name == *optstr) {
813 print_option_help(opts, 0);
702 break; 814 break;
815 }
703 continue; 816 continue;
704 } 817 }
705 818
706 if (opts->long_name == NULL) 819 if (opts->long_name == NULL)
707 continue; 820 continue;
708 821
709 if (!prefixcmp(optstr, opts->long_name)) 822 if (!prefixcmp(opts->long_name, optstr))
710 break; 823 print_option_help(opts, 0);
711 if (!prefixcmp(optstr, "no-") && 824 if (!prefixcmp("no-", optstr) &&
712 !prefixcmp(optstr + 3, opts->long_name)) 825 !prefixcmp(opts->long_name, optstr + 3))
713 break; 826 print_option_help(opts, 0);
714 } 827 }
715 828
716 if (opts->type != OPTION_END)
717 print_option_help(opts, 0);
718
719 return PARSE_OPT_HELP; 829 return PARSE_OPT_HELP;
720} 830}
721 831
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 367d8b816cc7..a8e407bc251e 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -111,6 +111,7 @@ struct option {
111#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } 111#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) }
112#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } 112#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
113#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } 113#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) }
114#define OPT_BOOLEAN_FLAG(s, l, v, h, f) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h), .flags = (f) }
114#define OPT_BOOLEAN_SET(s, l, v, os, h) \ 115#define OPT_BOOLEAN_SET(s, l, v, os, h) \
115 { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ 116 { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \
116 .value = check_vtype(v, bool *), .help = (h), \ 117 .value = check_vtype(v, bool *), .help = (h), \
@@ -160,6 +161,10 @@ extern int parse_options_subcommand(int argc, const char **argv,
160 161
161extern NORETURN void usage_with_options(const char * const *usagestr, 162extern NORETURN void usage_with_options(const char * const *usagestr,
162 const struct option *options); 163 const struct option *options);
164extern NORETURN __attribute__((format(printf,3,4)))
165void usage_with_options_msg(const char * const *usagestr,
166 const struct option *options,
167 const char *fmt, ...);
163 168
164/*----- incremantal advanced APIs -----*/ 169/*----- incremantal advanced APIs -----*/
165 170
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 89c91a1a67e7..e4b173dec4b9 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -626,38 +626,26 @@ static int pmu_resolve_param_term(struct parse_events_term *term,
626 return -1; 626 return -1;
627} 627}
628 628
629static char *formats_error_string(struct list_head *formats) 629static char *pmu_formats_string(struct list_head *formats)
630{ 630{
631 struct perf_pmu_format *format; 631 struct perf_pmu_format *format;
632 char *err, *str; 632 char *str;
633 static const char *static_terms = "config,config1,config2,name," 633 struct strbuf buf;
634 "period,freq,branch_type,time,"
635 "call-graph,stack-size\n";
636 unsigned i = 0; 634 unsigned i = 0;
637 635
638 if (!asprintf(&str, "valid terms:")) 636 if (!formats)
639 return NULL; 637 return NULL;
640 638
639 strbuf_init(&buf, 0);
641 /* sysfs exported terms */ 640 /* sysfs exported terms */
642 list_for_each_entry(format, formats, list) { 641 list_for_each_entry(format, formats, list)
643 char c = i++ ? ',' : ' '; 642 strbuf_addf(&buf, i++ ? ",%s" : "%s",
644 643 format->name);
645 err = str;
646 if (!asprintf(&str, "%s%c%s", err, c, format->name))
647 goto fail;
648 free(err);
649 }
650 644
651 /* static terms */ 645 str = strbuf_detach(&buf, NULL);
652 err = str; 646 strbuf_release(&buf);
653 if (!asprintf(&str, "%s,%s", err, static_terms))
654 goto fail;
655 647
656 free(err);
657 return str; 648 return str;
658fail:
659 free(err);
660 return NULL;
661} 649}
662 650
663/* 651/*
@@ -693,9 +681,12 @@ static int pmu_config_term(struct list_head *formats,
693 if (verbose) 681 if (verbose)
694 printf("Invalid event/parameter '%s'\n", term->config); 682 printf("Invalid event/parameter '%s'\n", term->config);
695 if (err) { 683 if (err) {
684 char *pmu_term = pmu_formats_string(formats);
685
696 err->idx = term->err_term; 686 err->idx = term->err_term;
697 err->str = strdup("unknown term"); 687 err->str = strdup("unknown term");
698 err->help = formats_error_string(formats); 688 err->help = parse_events_formats_error_string(pmu_term);
689 free(pmu_term);
699 } 690 }
700 return -EINVAL; 691 return -EINVAL;
701 } 692 }
@@ -1017,7 +1008,8 @@ void print_pmu_events(const char *event_glob, bool name_only)
1017 goto out_enomem; 1008 goto out_enomem;
1018 j++; 1009 j++;
1019 } 1010 }
1020 if (pmu->selectable) { 1011 if (pmu->selectable &&
1012 (event_glob == NULL || strglobmatch(pmu->name, event_glob))) {
1021 char *s; 1013 char *s;
1022 if (asprintf(&s, "%s//", pmu->name) < 0) 1014 if (asprintf(&s, "%s//", pmu->name) < 0)
1023 goto out_enomem; 1015 goto out_enomem;
@@ -1035,7 +1027,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
1035 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 1027 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
1036 printed++; 1028 printed++;
1037 } 1029 }
1038 if (printed) 1030 if (printed && pager_in_use())
1039 printf("\n"); 1031 printf("\n");
1040out_free: 1032out_free:
1041 for (j = 0; j < len; j++) 1033 for (j = 0; j < len; j++)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index c6f9af78f6f5..03875f9154e7 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -40,8 +40,7 @@
40#include "color.h" 40#include "color.h"
41#include "symbol.h" 41#include "symbol.h"
42#include "thread.h" 42#include "thread.h"
43#include <api/fs/debugfs.h> 43#include <api/fs/fs.h>
44#include <api/fs/tracefs.h>
45#include "trace-event.h" /* For __maybe_unused */ 44#include "trace-event.h" /* For __maybe_unused */
46#include "probe-event.h" 45#include "probe-event.h"
47#include "probe-finder.h" 46#include "probe-finder.h"
@@ -72,7 +71,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
72static struct machine *host_machine; 71static struct machine *host_machine;
73 72
74/* Initialize symbol maps and path of vmlinux/modules */ 73/* Initialize symbol maps and path of vmlinux/modules */
75static int init_symbol_maps(bool user_only) 74int init_probe_symbol_maps(bool user_only)
76{ 75{
77 int ret; 76 int ret;
78 77
@@ -102,7 +101,7 @@ out:
102 return ret; 101 return ret;
103} 102}
104 103
105static void exit_symbol_maps(void) 104void exit_probe_symbol_maps(void)
106{ 105{
107 if (host_machine) { 106 if (host_machine) {
108 machine__delete(host_machine); 107 machine__delete(host_machine);
@@ -127,17 +126,19 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
127{ 126{
128 /* kmap->ref_reloc_sym should be set if host_machine is initialized */ 127 /* kmap->ref_reloc_sym should be set if host_machine is initialized */
129 struct kmap *kmap; 128 struct kmap *kmap;
129 struct map *map = machine__kernel_map(host_machine);
130 130
131 if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0) 131 if (map__load(map, NULL) < 0)
132 return NULL; 132 return NULL;
133 133
134 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); 134 kmap = map__kmap(map);
135 if (!kmap) 135 if (!kmap)
136 return NULL; 136 return NULL;
137 return kmap->ref_reloc_sym; 137 return kmap->ref_reloc_sym;
138} 138}
139 139
140static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc) 140static int kernel_get_symbol_address_by_name(const char *name, u64 *addr,
141 bool reloc, bool reladdr)
141{ 142{
142 struct ref_reloc_sym *reloc_sym; 143 struct ref_reloc_sym *reloc_sym;
143 struct symbol *sym; 144 struct symbol *sym;
@@ -146,12 +147,14 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
146 /* ref_reloc_sym is just a label. Need a special fix*/ 147 /* ref_reloc_sym is just a label. Need a special fix*/
147 reloc_sym = kernel_get_ref_reloc_sym(); 148 reloc_sym = kernel_get_ref_reloc_sym();
148 if (reloc_sym && strcmp(name, reloc_sym->name) == 0) 149 if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
149 return (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr; 150 *addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
150 else { 151 else {
151 sym = __find_kernel_function_by_name(name, &map); 152 sym = __find_kernel_function_by_name(name, &map);
152 if (sym) 153 if (!sym)
153 return map->unmap_ip(map, sym->start) - 154 return -ENOENT;
154 ((reloc) ? 0 : map->reloc); 155 *addr = map->unmap_ip(map, sym->start) -
156 ((reloc) ? 0 : map->reloc) -
157 ((reladdr) ? map->start : 0);
155 } 158 }
156 return 0; 159 return 0;
157} 160}
@@ -245,12 +248,14 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
245static bool kprobe_blacklist__listed(unsigned long address); 248static bool kprobe_blacklist__listed(unsigned long address);
246static bool kprobe_warn_out_range(const char *symbol, unsigned long address) 249static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
247{ 250{
248 u64 etext_addr; 251 u64 etext_addr = 0;
252 int ret;
249 253
250 /* Get the address of _etext for checking non-probable text symbol */ 254 /* Get the address of _etext for checking non-probable text symbol */
251 etext_addr = kernel_get_symbol_address_by_name("_etext", false); 255 ret = kernel_get_symbol_address_by_name("_etext", &etext_addr,
256 false, false);
252 257
253 if (etext_addr != 0 && etext_addr < address) 258 if (ret == 0 && etext_addr < address)
254 pr_warning("%s is out of .text, skip it.\n", symbol); 259 pr_warning("%s is out of .text, skip it.\n", symbol);
255 else if (kprobe_blacklist__listed(address)) 260 else if (kprobe_blacklist__listed(address))
256 pr_warning("%s is blacklisted function, skip it.\n", symbol); 261 pr_warning("%s is blacklisted function, skip it.\n", symbol);
@@ -282,7 +287,7 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso)
282 return -ENOENT; 287 return -ENOENT;
283 } 288 }
284 289
285 map = host_machine->vmlinux_maps[MAP__FUNCTION]; 290 map = machine__kernel_map(host_machine);
286 dso = map->dso; 291 dso = map->dso;
287 292
288 vmlinux_name = symbol_conf.vmlinux_name; 293 vmlinux_name = symbol_conf.vmlinux_name;
@@ -436,19 +441,22 @@ static char *debuginfo_cache_path;
436 441
437static struct debuginfo *debuginfo_cache__open(const char *module, bool silent) 442static struct debuginfo *debuginfo_cache__open(const char *module, bool silent)
438{ 443{
439 if ((debuginfo_cache_path && !strcmp(debuginfo_cache_path, module)) || 444 const char *path = module;
440 (!debuginfo_cache_path && !module && debuginfo_cache)) 445
446 /* If the module is NULL, it should be the kernel. */
447 if (!module)
448 path = "kernel";
449
450 if (debuginfo_cache_path && !strcmp(debuginfo_cache_path, path))
441 goto out; 451 goto out;
442 452
443 /* Copy module path */ 453 /* Copy module path */
444 free(debuginfo_cache_path); 454 free(debuginfo_cache_path);
445 if (module) { 455 debuginfo_cache_path = strdup(path);
446 debuginfo_cache_path = strdup(module); 456 if (!debuginfo_cache_path) {
447 if (!debuginfo_cache_path) { 457 debuginfo__delete(debuginfo_cache);
448 debuginfo__delete(debuginfo_cache); 458 debuginfo_cache = NULL;
449 debuginfo_cache = NULL; 459 goto out;
450 goto out;
451 }
452 } 460 }
453 461
454 debuginfo_cache = open_debuginfo(module, silent); 462 debuginfo_cache = open_debuginfo(module, silent);
@@ -517,8 +525,10 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
517 goto error; 525 goto error;
518 addr += stext; 526 addr += stext;
519 } else if (tp->symbol) { 527 } else if (tp->symbol) {
520 addr = kernel_get_symbol_address_by_name(tp->symbol, false); 528 /* If the module is given, this returns relative address */
521 if (addr == 0) 529 ret = kernel_get_symbol_address_by_name(tp->symbol, &addr,
530 false, !!tp->module);
531 if (ret != 0)
522 goto error; 532 goto error;
523 addr += tp->offset; 533 addr += tp->offset;
524 } 534 }
@@ -861,11 +871,11 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
861{ 871{
862 int ret; 872 int ret;
863 873
864 ret = init_symbol_maps(user); 874 ret = init_probe_symbol_maps(user);
865 if (ret < 0) 875 if (ret < 0)
866 return ret; 876 return ret;
867 ret = __show_line_range(lr, module, user); 877 ret = __show_line_range(lr, module, user);
868 exit_symbol_maps(); 878 exit_probe_symbol_maps();
869 879
870 return ret; 880 return ret;
871} 881}
@@ -943,7 +953,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
943 int i, ret = 0; 953 int i, ret = 0;
944 struct debuginfo *dinfo; 954 struct debuginfo *dinfo;
945 955
946 ret = init_symbol_maps(pevs->uprobes); 956 ret = init_probe_symbol_maps(pevs->uprobes);
947 if (ret < 0) 957 if (ret < 0)
948 return ret; 958 return ret;
949 959
@@ -960,7 +970,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
960 970
961 debuginfo__delete(dinfo); 971 debuginfo__delete(dinfo);
962out: 972out:
963 exit_symbol_maps(); 973 exit_probe_symbol_maps();
964 return ret; 974 return ret;
965} 975}
966 976
@@ -1884,13 +1894,17 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
1884 goto out; 1894 goto out;
1885 sym = map__find_symbol(map, addr, NULL); 1895 sym = map__find_symbol(map, addr, NULL);
1886 } else { 1896 } else {
1887 if (tp->symbol) 1897 if (tp->symbol && !addr) {
1888 addr = kernel_get_symbol_address_by_name(tp->symbol, true); 1898 if (kernel_get_symbol_address_by_name(tp->symbol,
1899 &addr, true, false) < 0)
1900 goto out;
1901 }
1889 if (addr) { 1902 if (addr) {
1890 addr += tp->offset; 1903 addr += tp->offset;
1891 sym = __find_kernel_function(addr, &map); 1904 sym = __find_kernel_function(addr, &map);
1892 } 1905 }
1893 } 1906 }
1907
1894 if (!sym) 1908 if (!sym)
1895 goto out; 1909 goto out;
1896 1910
@@ -2055,7 +2069,7 @@ static void kprobe_blacklist__delete(struct list_head *blacklist)
2055static int kprobe_blacklist__load(struct list_head *blacklist) 2069static int kprobe_blacklist__load(struct list_head *blacklist)
2056{ 2070{
2057 struct kprobe_blacklist_node *node; 2071 struct kprobe_blacklist_node *node;
2058 const char *__debugfs = debugfs_find_mountpoint(); 2072 const char *__debugfs = debugfs__mountpoint();
2059 char buf[PATH_MAX], *p; 2073 char buf[PATH_MAX], *p;
2060 FILE *fp; 2074 FILE *fp;
2061 int ret; 2075 int ret;
@@ -2181,9 +2195,9 @@ out:
2181} 2195}
2182 2196
2183/* Show an event */ 2197/* Show an event */
2184static int show_perf_probe_event(const char *group, const char *event, 2198int show_perf_probe_event(const char *group, const char *event,
2185 struct perf_probe_event *pev, 2199 struct perf_probe_event *pev,
2186 const char *module, bool use_stdout) 2200 const char *module, bool use_stdout)
2187{ 2201{
2188 struct strbuf buf = STRBUF_INIT; 2202 struct strbuf buf = STRBUF_INIT;
2189 int ret; 2203 int ret;
@@ -2264,7 +2278,7 @@ int show_perf_probe_events(struct strfilter *filter)
2264 2278
2265 setup_pager(); 2279 setup_pager();
2266 2280
2267 ret = init_symbol_maps(false); 2281 ret = init_probe_symbol_maps(false);
2268 if (ret < 0) 2282 if (ret < 0)
2269 return ret; 2283 return ret;
2270 2284
@@ -2280,7 +2294,7 @@ int show_perf_probe_events(struct strfilter *filter)
2280 close(kp_fd); 2294 close(kp_fd);
2281 if (up_fd > 0) 2295 if (up_fd > 0)
2282 close(up_fd); 2296 close(up_fd);
2283 exit_symbol_maps(); 2297 exit_probe_symbol_maps();
2284 2298
2285 return ret; 2299 return ret;
2286} 2300}
@@ -2289,36 +2303,41 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2289 struct strlist *namelist, bool allow_suffix) 2303 struct strlist *namelist, bool allow_suffix)
2290{ 2304{
2291 int i, ret; 2305 int i, ret;
2292 char *p; 2306 char *p, *nbase;
2293 2307
2294 if (*base == '.') 2308 if (*base == '.')
2295 base++; 2309 base++;
2310 nbase = strdup(base);
2311 if (!nbase)
2312 return -ENOMEM;
2313
2314 /* Cut off the dot suffixes (e.g. .const, .isra)*/
2315 p = strchr(nbase, '.');
2316 if (p && p != nbase)
2317 *p = '\0';
2296 2318
2297 /* Try no suffix */ 2319 /* Try no suffix number */
2298 ret = e_snprintf(buf, len, "%s", base); 2320 ret = e_snprintf(buf, len, "%s", nbase);
2299 if (ret < 0) { 2321 if (ret < 0) {
2300 pr_debug("snprintf() failed: %d\n", ret); 2322 pr_debug("snprintf() failed: %d\n", ret);
2301 return ret; 2323 goto out;
2302 } 2324 }
2303 /* Cut off the postfixes (e.g. .const, .isra)*/
2304 p = strchr(buf, '.');
2305 if (p && p != buf)
2306 *p = '\0';
2307 if (!strlist__has_entry(namelist, buf)) 2325 if (!strlist__has_entry(namelist, buf))
2308 return 0; 2326 goto out;
2309 2327
2310 if (!allow_suffix) { 2328 if (!allow_suffix) {
2311 pr_warning("Error: event \"%s\" already exists. " 2329 pr_warning("Error: event \"%s\" already exists. "
2312 "(Use -f to force duplicates.)\n", base); 2330 "(Use -f to force duplicates.)\n", buf);
2313 return -EEXIST; 2331 ret = -EEXIST;
2332 goto out;
2314 } 2333 }
2315 2334
2316 /* Try to add suffix */ 2335 /* Try to add suffix */
2317 for (i = 1; i < MAX_EVENT_INDEX; i++) { 2336 for (i = 1; i < MAX_EVENT_INDEX; i++) {
2318 ret = e_snprintf(buf, len, "%s_%d", base, i); 2337 ret = e_snprintf(buf, len, "%s_%d", nbase, i);
2319 if (ret < 0) { 2338 if (ret < 0) {
2320 pr_debug("snprintf() failed: %d\n", ret); 2339 pr_debug("snprintf() failed: %d\n", ret);
2321 return ret; 2340 goto out;
2322 } 2341 }
2323 if (!strlist__has_entry(namelist, buf)) 2342 if (!strlist__has_entry(namelist, buf))
2324 break; 2343 break;
@@ -2328,6 +2347,8 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2328 ret = -ERANGE; 2347 ret = -ERANGE;
2329 } 2348 }
2330 2349
2350out:
2351 free(nbase);
2331 return ret; 2352 return ret;
2332} 2353}
2333 2354
@@ -2400,7 +2421,6 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2400{ 2421{
2401 int i, fd, ret; 2422 int i, fd, ret;
2402 struct probe_trace_event *tev = NULL; 2423 struct probe_trace_event *tev = NULL;
2403 const char *event = NULL, *group = NULL;
2404 struct strlist *namelist; 2424 struct strlist *namelist;
2405 2425
2406 fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0)); 2426 fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0));
@@ -2416,7 +2436,6 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2416 } 2436 }
2417 2437
2418 ret = 0; 2438 ret = 0;
2419 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2420 for (i = 0; i < ntevs; i++) { 2439 for (i = 0; i < ntevs; i++) {
2421 tev = &tevs[i]; 2440 tev = &tevs[i];
2422 /* Skip if the symbol is out of .text or blacklisted */ 2441 /* Skip if the symbol is out of .text or blacklisted */
@@ -2433,13 +2452,6 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2433 if (ret < 0) 2452 if (ret < 0)
2434 break; 2453 break;
2435 2454
2436 /* We use tev's name for showing new events */
2437 show_perf_probe_event(tev->group, tev->event, pev,
2438 tev->point.module, false);
2439 /* Save the last valid name */
2440 event = tev->event;
2441 group = tev->group;
2442
2443 /* 2455 /*
2444 * Probes after the first probe which comes from same 2456 * Probes after the first probe which comes from same
2445 * user input are always allowed to add suffix, because 2457 * user input are always allowed to add suffix, because
@@ -2451,13 +2463,6 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2451 if (ret == -EINVAL && pev->uprobes) 2463 if (ret == -EINVAL && pev->uprobes)
2452 warn_uprobe_event_compat(tev); 2464 warn_uprobe_event_compat(tev);
2453 2465
2454 /* Note that it is possible to skip all events because of blacklist */
2455 if (ret >= 0 && event) {
2456 /* Show how to use the event. */
2457 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2458 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
2459 }
2460
2461 strlist__delete(namelist); 2466 strlist__delete(namelist);
2462close_out: 2467close_out:
2463 close(fd); 2468 close(fd);
@@ -2538,7 +2543,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2538 goto out; 2543 goto out;
2539 } 2544 }
2540 2545
2541 if (!pev->uprobes && !pp->retprobe) { 2546 /* Note that the symbols in the kmodule are not relocated */
2547 if (!pev->uprobes && !pp->retprobe && !pev->target) {
2542 reloc_sym = kernel_get_ref_reloc_sym(); 2548 reloc_sym = kernel_get_ref_reloc_sym();
2543 if (!reloc_sym) { 2549 if (!reloc_sym) {
2544 pr_warning("Relocated base symbol is not found!\n"); 2550 pr_warning("Relocated base symbol is not found!\n");
@@ -2575,8 +2581,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2575 } 2581 }
2576 /* Add one probe point */ 2582 /* Add one probe point */
2577 tp->address = map->unmap_ip(map, sym->start) + pp->offset; 2583 tp->address = map->unmap_ip(map, sym->start) + pp->offset;
2578 /* If we found a wrong one, mark it by NULL symbol */ 2584
2579 if (!pev->uprobes && 2585 /* Check the kprobe (not in module) is within .text */
2586 if (!pev->uprobes && !pev->target &&
2580 kprobe_warn_out_range(sym->name, tp->address)) { 2587 kprobe_warn_out_range(sym->name, tp->address)) {
2581 tp->symbol = NULL; /* Skip it */ 2588 tp->symbol = NULL; /* Skip it */
2582 skipped++; 2589 skipped++;
@@ -2760,63 +2767,71 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2760 return find_probe_trace_events_from_map(pev, tevs); 2767 return find_probe_trace_events_from_map(pev, tevs);
2761} 2768}
2762 2769
2763struct __event_package { 2770int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2764 struct perf_probe_event *pev;
2765 struct probe_trace_event *tevs;
2766 int ntevs;
2767};
2768
2769int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2770{ 2771{
2771 int i, j, ret; 2772 int i, ret;
2772 struct __event_package *pkgs;
2773
2774 ret = 0;
2775 pkgs = zalloc(sizeof(struct __event_package) * npevs);
2776
2777 if (pkgs == NULL)
2778 return -ENOMEM;
2779
2780 ret = init_symbol_maps(pevs->uprobes);
2781 if (ret < 0) {
2782 free(pkgs);
2783 return ret;
2784 }
2785 2773
2786 /* Loop 1: convert all events */ 2774 /* Loop 1: convert all events */
2787 for (i = 0; i < npevs; i++) { 2775 for (i = 0; i < npevs; i++) {
2788 pkgs[i].pev = &pevs[i];
2789 /* Init kprobe blacklist if needed */ 2776 /* Init kprobe blacklist if needed */
2790 if (!pkgs[i].pev->uprobes) 2777 if (!pevs[i].uprobes)
2791 kprobe_blacklist__init(); 2778 kprobe_blacklist__init();
2792 /* Convert with or without debuginfo */ 2779 /* Convert with or without debuginfo */
2793 ret = convert_to_probe_trace_events(pkgs[i].pev, 2780 ret = convert_to_probe_trace_events(&pevs[i], &pevs[i].tevs);
2794 &pkgs[i].tevs);
2795 if (ret < 0) 2781 if (ret < 0)
2796 goto end; 2782 return ret;
2797 pkgs[i].ntevs = ret; 2783 pevs[i].ntevs = ret;
2798 } 2784 }
2799 /* This just release blacklist only if allocated */ 2785 /* This just release blacklist only if allocated */
2800 kprobe_blacklist__release(); 2786 kprobe_blacklist__release();
2801 2787
2788 return 0;
2789}
2790
2791int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2792{
2793 int i, ret = 0;
2794
2802 /* Loop 2: add all events */ 2795 /* Loop 2: add all events */
2803 for (i = 0; i < npevs; i++) { 2796 for (i = 0; i < npevs; i++) {
2804 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 2797 ret = __add_probe_trace_events(&pevs[i], pevs[i].tevs,
2805 pkgs[i].ntevs, 2798 pevs[i].ntevs,
2806 probe_conf.force_add); 2799 probe_conf.force_add);
2807 if (ret < 0) 2800 if (ret < 0)
2808 break; 2801 break;
2809 } 2802 }
2810end: 2803 return ret;
2804}
2805
2806void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2807{
2808 int i, j;
2809
2811 /* Loop 3: cleanup and free trace events */ 2810 /* Loop 3: cleanup and free trace events */
2812 for (i = 0; i < npevs; i++) { 2811 for (i = 0; i < npevs; i++) {
2813 for (j = 0; j < pkgs[i].ntevs; j++) 2812 for (j = 0; j < pevs[i].ntevs; j++)
2814 clear_probe_trace_event(&pkgs[i].tevs[j]); 2813 clear_probe_trace_event(&pevs[i].tevs[j]);
2815 zfree(&pkgs[i].tevs); 2814 zfree(&pevs[i].tevs);
2815 pevs[i].ntevs = 0;
2816 clear_perf_probe_event(&pevs[i]);
2816 } 2817 }
2817 free(pkgs); 2818}
2818 exit_symbol_maps();
2819 2819
2820int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2821{
2822 int ret;
2823
2824 ret = init_probe_symbol_maps(pevs->uprobes);
2825 if (ret < 0)
2826 return ret;
2827
2828 ret = convert_perf_probe_events(pevs, npevs);
2829 if (ret == 0)
2830 ret = apply_perf_probe_events(pevs, npevs);
2831
2832 cleanup_perf_probe_events(pevs, npevs);
2833
2834 exit_probe_symbol_maps();
2820 return ret; 2835 return ret;
2821} 2836}
2822 2837
@@ -2828,8 +2843,6 @@ int del_perf_probe_events(struct strfilter *filter)
2828 if (!str) 2843 if (!str)
2829 return -EINVAL; 2844 return -EINVAL;
2830 2845
2831 pr_debug("Delete filter: \'%s\'\n", str);
2832
2833 /* Get current event names */ 2846 /* Get current event names */
2834 ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); 2847 ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW);
2835 if (ret < 0) 2848 if (ret < 0)
@@ -2844,9 +2857,6 @@ int del_perf_probe_events(struct strfilter *filter)
2844 ret = ret2; 2857 ret = ret2;
2845 goto error; 2858 goto error;
2846 } 2859 }
2847 if (ret == -ENOENT && ret2 == -ENOENT)
2848 pr_debug("\"%s\" does not hit any event.\n", str);
2849 /* Note that this is silently ignored */
2850 ret = 0; 2860 ret = 0;
2851 2861
2852error: 2862error:
@@ -2881,7 +2891,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
2881 struct map *map; 2891 struct map *map;
2882 int ret; 2892 int ret;
2883 2893
2884 ret = init_symbol_maps(user); 2894 ret = init_probe_symbol_maps(user);
2885 if (ret < 0) 2895 if (ret < 0)
2886 return ret; 2896 return ret;
2887 2897
@@ -2911,7 +2921,7 @@ end:
2911 if (user) { 2921 if (user) {
2912 map__put(map); 2922 map__put(map);
2913 } 2923 }
2914 exit_symbol_maps(); 2924 exit_probe_symbol_maps();
2915 2925
2916 return ret; 2926 return ret;
2917} 2927}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 6e7ec68a4aa8..ba926c30f8cd 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -87,6 +87,8 @@ struct perf_probe_event {
87 bool uprobes; /* Uprobe event flag */ 87 bool uprobes; /* Uprobe event flag */
88 char *target; /* Target binary */ 88 char *target; /* Target binary */
89 struct perf_probe_arg *args; /* Arguments */ 89 struct perf_probe_arg *args; /* Arguments */
90 struct probe_trace_event *tevs;
91 int ntevs;
90}; 92};
91 93
92/* Line range */ 94/* Line range */
@@ -108,6 +110,8 @@ struct variable_list {
108}; 110};
109 111
110struct map; 112struct map;
113int init_probe_symbol_maps(bool user_only);
114void exit_probe_symbol_maps(void);
111 115
112/* Command string to events */ 116/* Command string to events */
113extern int parse_perf_probe_command(const char *cmd, 117extern int parse_perf_probe_command(const char *cmd,
@@ -138,7 +142,14 @@ extern void line_range__clear(struct line_range *lr);
138extern int line_range__init(struct line_range *lr); 142extern int line_range__init(struct line_range *lr);
139 143
140extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs); 144extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
145extern int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs);
146extern int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs);
147extern void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);
141extern int del_perf_probe_events(struct strfilter *filter); 148extern int del_perf_probe_events(struct strfilter *filter);
149
150extern int show_perf_probe_event(const char *group, const char *event,
151 struct perf_probe_event *pev,
152 const char *module, bool use_stdout);
142extern int show_perf_probe_events(struct strfilter *filter); 153extern int show_perf_probe_events(struct strfilter *filter);
143extern int show_line_range(struct line_range *lr, const char *module, 154extern int show_line_range(struct line_range *lr, const char *module,
144 bool user); 155 bool user);
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index bbb243717ec8..e3b3b92e4458 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -22,8 +22,7 @@
22#include "color.h" 22#include "color.h"
23#include "symbol.h" 23#include "symbol.h"
24#include "thread.h" 24#include "thread.h"
25#include <api/fs/debugfs.h> 25#include <api/fs/tracing_path.h>
26#include <api/fs/tracefs.h>
27#include "probe-event.h" 26#include "probe-event.h"
28#include "probe-file.h" 27#include "probe-file.h"
29#include "session.h" 28#include "session.h"
@@ -73,21 +72,11 @@ static void print_both_open_warning(int kerr, int uerr)
73static int open_probe_events(const char *trace_file, bool readwrite) 72static int open_probe_events(const char *trace_file, bool readwrite)
74{ 73{
75 char buf[PATH_MAX]; 74 char buf[PATH_MAX];
76 const char *__debugfs;
77 const char *tracing_dir = ""; 75 const char *tracing_dir = "";
78 int ret; 76 int ret;
79 77
80 __debugfs = tracefs_find_mountpoint();
81 if (__debugfs == NULL) {
82 tracing_dir = "tracing/";
83
84 __debugfs = debugfs_find_mountpoint();
85 if (__debugfs == NULL)
86 return -ENOTSUP;
87 }
88
89 ret = e_snprintf(buf, PATH_MAX, "%s/%s%s", 78 ret = e_snprintf(buf, PATH_MAX, "%s/%s%s",
90 __debugfs, tracing_dir, trace_file); 79 tracing_path, tracing_dir, trace_file);
91 if (ret >= 0) { 80 if (ret >= 0) {
92 pr_debug("Opening %s write=%d\n", buf, readwrite); 81 pr_debug("Opening %s write=%d\n", buf, readwrite);
93 if (readwrite && !probe_event_dry_run) 82 if (readwrite && !probe_event_dry_run)
@@ -149,6 +138,9 @@ struct strlist *probe_file__get_rawlist(int fd)
149 char *p; 138 char *p;
150 struct strlist *sl; 139 struct strlist *sl;
151 140
141 if (fd < 0)
142 return NULL;
143
152 sl = strlist__new(NULL, NULL); 144 sl = strlist__new(NULL, NULL);
153 145
154 fp = fdopen(dup(fd), "r"); 146 fp = fdopen(dup(fd), "r");
@@ -267,7 +259,6 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
267 goto error; 259 goto error;
268 } 260 }
269 261
270 pr_info("Removed event: %s\n", ent->s);
271 return 0; 262 return 0;
272error: 263error:
273 pr_warning("Failed to delete event: %s\n", 264 pr_warning("Failed to delete event: %s\n",
@@ -275,13 +266,17 @@ error:
275 return ret; 266 return ret;
276} 267}
277 268
278int probe_file__del_events(int fd, struct strfilter *filter) 269int probe_file__get_events(int fd, struct strfilter *filter,
270 struct strlist *plist)
279{ 271{
280 struct strlist *namelist; 272 struct strlist *namelist;
281 struct str_node *ent; 273 struct str_node *ent;
282 const char *p; 274 const char *p;
283 int ret = -ENOENT; 275 int ret = -ENOENT;
284 276
277 if (!plist)
278 return -EINVAL;
279
285 namelist = __probe_file__get_namelist(fd, true); 280 namelist = __probe_file__get_namelist(fd, true);
286 if (!namelist) 281 if (!namelist)
287 return -ENOENT; 282 return -ENOENT;
@@ -290,12 +285,43 @@ int probe_file__del_events(int fd, struct strfilter *filter)
290 p = strchr(ent->s, ':'); 285 p = strchr(ent->s, ':');
291 if ((p && strfilter__compare(filter, p + 1)) || 286 if ((p && strfilter__compare(filter, p + 1)) ||
292 strfilter__compare(filter, ent->s)) { 287 strfilter__compare(filter, ent->s)) {
293 ret = __del_trace_probe_event(fd, ent); 288 strlist__add(plist, ent->s);
294 if (ret < 0) 289 ret = 0;
295 break;
296 } 290 }
297 } 291 }
298 strlist__delete(namelist); 292 strlist__delete(namelist);
299 293
300 return ret; 294 return ret;
301} 295}
296
297int probe_file__del_strlist(int fd, struct strlist *namelist)
298{
299 int ret = 0;
300 struct str_node *ent;
301
302 strlist__for_each(ent, namelist) {
303 ret = __del_trace_probe_event(fd, ent);
304 if (ret < 0)
305 break;
306 }
307 return ret;
308}
309
310int probe_file__del_events(int fd, struct strfilter *filter)
311{
312 struct strlist *namelist;
313 int ret;
314
315 namelist = strlist__new(NULL, NULL);
316 if (!namelist)
317 return -ENOMEM;
318
319 ret = probe_file__get_events(fd, filter, namelist);
320 if (ret < 0)
321 return ret;
322
323 ret = probe_file__del_strlist(fd, namelist);
324 strlist__delete(namelist);
325
326 return ret;
327}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index ada94a242a17..18ac9cf51c34 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -14,5 +14,9 @@ struct strlist *probe_file__get_namelist(int fd);
14struct strlist *probe_file__get_rawlist(int fd); 14struct strlist *probe_file__get_rawlist(int fd);
15int probe_file__add_event(int fd, struct probe_trace_event *tev); 15int probe_file__add_event(int fd, struct probe_trace_event *tev);
16int probe_file__del_events(int fd, struct strfilter *filter); 16int probe_file__del_events(int fd, struct strfilter *filter);
17int probe_file__get_events(int fd, struct strfilter *filter,
18 struct strlist *plist);
19int probe_file__del_strlist(int fd, struct strlist *namelist);
20
17 21
18#endif 22#endif
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 29c43c0680a8..05012bb178d7 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -70,6 +70,7 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
70 if (!dbg->dwfl) 70 if (!dbg->dwfl)
71 goto error; 71 goto error;
72 72
73 dwfl_report_begin(dbg->dwfl);
73 dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); 74 dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
74 if (!dbg->mod) 75 if (!dbg->mod)
75 goto error; 76 goto error;
@@ -78,6 +79,8 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
78 if (!dbg->dbg) 79 if (!dbg->dbg)
79 goto error; 80 goto error;
80 81
82 dwfl_report_end(dbg->dwfl, NULL, NULL);
83
81 return 0; 84 return 0;
82error: 85error:
83 if (dbg->dwfl) 86 if (dbg->dwfl)
@@ -591,6 +594,7 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
591/* Convert subprogram DIE to trace point */ 594/* Convert subprogram DIE to trace point */
592static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, 595static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
593 Dwarf_Addr paddr, bool retprobe, 596 Dwarf_Addr paddr, bool retprobe,
597 const char *function,
594 struct probe_trace_point *tp) 598 struct probe_trace_point *tp)
595{ 599{
596 Dwarf_Addr eaddr, highaddr; 600 Dwarf_Addr eaddr, highaddr;
@@ -634,8 +638,10 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
634 /* Return probe must be on the head of a subprogram */ 638 /* Return probe must be on the head of a subprogram */
635 if (retprobe) { 639 if (retprobe) {
636 if (eaddr != paddr) { 640 if (eaddr != paddr) {
637 pr_warning("Return probe must be on the head of" 641 pr_warning("Failed to find \"%s%%return\",\n"
638 " a real function.\n"); 642 " because %s is an inlined function and"
643 " has no return point.\n", function,
644 function);
639 return -EINVAL; 645 return -EINVAL;
640 } 646 }
641 tp->retprobe = true; 647 tp->retprobe = true;
@@ -1175,8 +1181,9 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1175{ 1181{
1176 struct trace_event_finder *tf = 1182 struct trace_event_finder *tf =
1177 container_of(pf, struct trace_event_finder, pf); 1183 container_of(pf, struct trace_event_finder, pf);
1184 struct perf_probe_point *pp = &pf->pev->point;
1178 struct probe_trace_event *tev; 1185 struct probe_trace_event *tev;
1179 struct perf_probe_arg *args; 1186 struct perf_probe_arg *args = NULL;
1180 int ret, i; 1187 int ret, i;
1181 1188
1182 /* Check number of tevs */ 1189 /* Check number of tevs */
@@ -1189,21 +1196,25 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1189 1196
1190 /* Trace point should be converted from subprogram DIE */ 1197 /* Trace point should be converted from subprogram DIE */
1191 ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, 1198 ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
1192 pf->pev->point.retprobe, &tev->point); 1199 pp->retprobe, pp->function, &tev->point);
1193 if (ret < 0) 1200 if (ret < 0)
1194 return ret; 1201 goto end;
1195 1202
1196 tev->point.realname = strdup(dwarf_diename(sc_die)); 1203 tev->point.realname = strdup(dwarf_diename(sc_die));
1197 if (!tev->point.realname) 1204 if (!tev->point.realname) {
1198 return -ENOMEM; 1205 ret = -ENOMEM;
1206 goto end;
1207 }
1199 1208
1200 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 1209 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1201 tev->point.offset); 1210 tev->point.offset);
1202 1211
1203 /* Expand special probe argument if exist */ 1212 /* Expand special probe argument if exist */
1204 args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); 1213 args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
1205 if (args == NULL) 1214 if (args == NULL) {
1206 return -ENOMEM; 1215 ret = -ENOMEM;
1216 goto end;
1217 }
1207 1218
1208 ret = expand_probe_args(sc_die, pf, args); 1219 ret = expand_probe_args(sc_die, pf, args);
1209 if (ret < 0) 1220 if (ret < 0)
@@ -1227,6 +1238,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1227 } 1238 }
1228 1239
1229end: 1240end:
1241 if (ret) {
1242 clear_probe_trace_event(tev);
1243 tf->ntevs--;
1244 }
1230 free(args); 1245 free(args);
1231 return ret; 1246 return ret;
1232} 1247}
@@ -1239,7 +1254,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
1239 struct trace_event_finder tf = { 1254 struct trace_event_finder tf = {
1240 .pf = {.pev = pev, .callback = add_probe_trace_event}, 1255 .pf = {.pev = pev, .callback = add_probe_trace_event},
1241 .max_tevs = probe_conf.max_probes, .mod = dbg->mod}; 1256 .max_tevs = probe_conf.max_probes, .mod = dbg->mod};
1242 int ret; 1257 int ret, i;
1243 1258
1244 /* Allocate result tevs array */ 1259 /* Allocate result tevs array */
1245 *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs); 1260 *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
@@ -1251,6 +1266,8 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
1251 1266
1252 ret = debuginfo__find_probes(dbg, &tf.pf); 1267 ret = debuginfo__find_probes(dbg, &tf.pf);
1253 if (ret < 0) { 1268 if (ret < 0) {
1269 for (i = 0; i < tf.ntevs; i++)
1270 clear_probe_trace_event(&tf.tevs[i]);
1254 zfree(tevs); 1271 zfree(tevs);
1255 return ret; 1272 return ret;
1256 } 1273 }
@@ -1319,6 +1336,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1319{ 1336{
1320 struct available_var_finder *af = 1337 struct available_var_finder *af =
1321 container_of(pf, struct available_var_finder, pf); 1338 container_of(pf, struct available_var_finder, pf);
1339 struct perf_probe_point *pp = &pf->pev->point;
1322 struct variable_list *vl; 1340 struct variable_list *vl;
1323 Dwarf_Die die_mem; 1341 Dwarf_Die die_mem;
1324 int ret; 1342 int ret;
@@ -1332,7 +1350,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1332 1350
1333 /* Trace point should be converted from subprogram DIE */ 1351 /* Trace point should be converted from subprogram DIE */
1334 ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr, 1352 ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
1335 pf->pev->point.retprobe, &vl->point); 1353 pp->retprobe, pp->function, &vl->point);
1336 if (ret < 0) 1354 if (ret < 0)
1337 return ret; 1355 return ret;
1338 1356
@@ -1399,6 +1417,41 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1399 return (ret < 0) ? ret : af.nvls; 1417 return (ret < 0) ? ret : af.nvls;
1400} 1418}
1401 1419
1420/* For the kernel module, we need a special code to get a DIE */
1421static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs)
1422{
1423 int n, i;
1424 Elf32_Word shndx;
1425 Elf_Scn *scn;
1426 Elf *elf;
1427 GElf_Shdr mem, *shdr;
1428 const char *p;
1429
1430 elf = dwfl_module_getelf(dbg->mod, &dbg->bias);
1431 if (!elf)
1432 return -EINVAL;
1433
1434 /* Get the number of relocations */
1435 n = dwfl_module_relocations(dbg->mod);
1436 if (n < 0)
1437 return -ENOENT;
1438 /* Search the relocation related .text section */
1439 for (i = 0; i < n; i++) {
1440 p = dwfl_module_relocation_info(dbg->mod, i, &shndx);
1441 if (strcmp(p, ".text") == 0) {
1442 /* OK, get the section header */
1443 scn = elf_getscn(elf, shndx);
1444 if (!scn)
1445 return -ENOENT;
1446 shdr = gelf_getshdr(scn, &mem);
1447 if (!shdr)
1448 return -ENOENT;
1449 *offs = shdr->sh_addr;
1450 }
1451 }
1452 return 0;
1453}
1454
1402/* Reverse search */ 1455/* Reverse search */
1403int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, 1456int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1404 struct perf_probe_point *ppt) 1457 struct perf_probe_point *ppt)
@@ -1407,9 +1460,16 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1407 Dwarf_Addr _addr = 0, baseaddr = 0; 1460 Dwarf_Addr _addr = 0, baseaddr = 0;
1408 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1461 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1409 int baseline = 0, lineno = 0, ret = 0; 1462 int baseline = 0, lineno = 0, ret = 0;
1463 bool reloc = false;
1410 1464
1465retry:
1411 /* Find cu die */ 1466 /* Find cu die */
1412 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { 1467 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
1468 if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) {
1469 addr += baseaddr;
1470 reloc = true;
1471 goto retry;
1472 }
1413 pr_warning("Failed to find debug information for address %lx\n", 1473 pr_warning("Failed to find debug information for address %lx\n",
1414 addr); 1474 addr);
1415 ret = -EINVAL; 1475 ret = -EINVAL;
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 6324fe6b161e..98f127abfa42 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -67,6 +67,7 @@ static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
67static PyMemberDef pyrf_mmap_event__members[] = { 67static PyMemberDef pyrf_mmap_event__members[] = {
68 sample_members 68 sample_members
69 member_def(perf_event_header, type, T_UINT, "event type"), 69 member_def(perf_event_header, type, T_UINT, "event type"),
70 member_def(perf_event_header, misc, T_UINT, "event misc"),
70 member_def(mmap_event, pid, T_UINT, "event pid"), 71 member_def(mmap_event, pid, T_UINT, "event pid"),
71 member_def(mmap_event, tid, T_UINT, "event tid"), 72 member_def(mmap_event, tid, T_UINT, "event tid"),
72 member_def(mmap_event, start, T_ULONGLONG, "start of the map"), 73 member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
@@ -297,6 +298,43 @@ static PyTypeObject pyrf_sample_event__type = {
297 .tp_repr = (reprfunc)pyrf_sample_event__repr, 298 .tp_repr = (reprfunc)pyrf_sample_event__repr,
298}; 299};
299 300
301static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object.");
302
303static PyMemberDef pyrf_context_switch_event__members[] = {
304 sample_members
305 member_def(perf_event_header, type, T_UINT, "event type"),
306 member_def(context_switch_event, next_prev_pid, T_UINT, "next/prev pid"),
307 member_def(context_switch_event, next_prev_tid, T_UINT, "next/prev tid"),
308 { .name = NULL, },
309};
310
311static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent)
312{
313 PyObject *ret;
314 char *s;
315
316 if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }",
317 pevent->event.context_switch.next_prev_pid,
318 pevent->event.context_switch.next_prev_tid,
319 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
320 ret = PyErr_NoMemory();
321 } else {
322 ret = PyString_FromString(s);
323 free(s);
324 }
325 return ret;
326}
327
328static PyTypeObject pyrf_context_switch_event__type = {
329 PyVarObject_HEAD_INIT(NULL, 0)
330 .tp_name = "perf.context_switch_event",
331 .tp_basicsize = sizeof(struct pyrf_event),
332 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
333 .tp_doc = pyrf_context_switch_event__doc,
334 .tp_members = pyrf_context_switch_event__members,
335 .tp_repr = (reprfunc)pyrf_context_switch_event__repr,
336};
337
300static int pyrf_event__setup_types(void) 338static int pyrf_event__setup_types(void)
301{ 339{
302 int err; 340 int err;
@@ -306,6 +344,7 @@ static int pyrf_event__setup_types(void)
306 pyrf_lost_event__type.tp_new = 344 pyrf_lost_event__type.tp_new =
307 pyrf_read_event__type.tp_new = 345 pyrf_read_event__type.tp_new =
308 pyrf_sample_event__type.tp_new = 346 pyrf_sample_event__type.tp_new =
347 pyrf_context_switch_event__type.tp_new =
309 pyrf_throttle_event__type.tp_new = PyType_GenericNew; 348 pyrf_throttle_event__type.tp_new = PyType_GenericNew;
310 err = PyType_Ready(&pyrf_mmap_event__type); 349 err = PyType_Ready(&pyrf_mmap_event__type);
311 if (err < 0) 350 if (err < 0)
@@ -328,6 +367,9 @@ static int pyrf_event__setup_types(void)
328 err = PyType_Ready(&pyrf_sample_event__type); 367 err = PyType_Ready(&pyrf_sample_event__type);
329 if (err < 0) 368 if (err < 0)
330 goto out; 369 goto out;
370 err = PyType_Ready(&pyrf_context_switch_event__type);
371 if (err < 0)
372 goto out;
331out: 373out:
332 return err; 374 return err;
333} 375}
@@ -342,6 +384,8 @@ static PyTypeObject *pyrf_event__type[] = {
342 [PERF_RECORD_FORK] = &pyrf_task_event__type, 384 [PERF_RECORD_FORK] = &pyrf_task_event__type,
343 [PERF_RECORD_READ] = &pyrf_read_event__type, 385 [PERF_RECORD_READ] = &pyrf_read_event__type,
344 [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type, 386 [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type,
387 [PERF_RECORD_SWITCH] = &pyrf_context_switch_event__type,
388 [PERF_RECORD_SWITCH_CPU_WIDE] = &pyrf_context_switch_event__type,
345}; 389};
346 390
347static PyObject *pyrf_event__new(union perf_event *event) 391static PyObject *pyrf_event__new(union perf_event *event)
@@ -349,8 +393,10 @@ static PyObject *pyrf_event__new(union perf_event *event)
349 struct pyrf_event *pevent; 393 struct pyrf_event *pevent;
350 PyTypeObject *ptype; 394 PyTypeObject *ptype;
351 395
352 if (event->header.type < PERF_RECORD_MMAP || 396 if ((event->header.type < PERF_RECORD_MMAP ||
353 event->header.type > PERF_RECORD_SAMPLE) 397 event->header.type > PERF_RECORD_SAMPLE) &&
398 !(event->header.type == PERF_RECORD_SWITCH ||
399 event->header.type == PERF_RECORD_SWITCH_CPU_WIDE))
354 return NULL; 400 return NULL;
355 401
356 ptype = pyrf_event__type[event->header.type]; 402 ptype = pyrf_event__type[event->header.type];
@@ -528,6 +574,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
528 "exclude_hv", 574 "exclude_hv",
529 "exclude_idle", 575 "exclude_idle",
530 "mmap", 576 "mmap",
577 "context_switch",
531 "comm", 578 "comm",
532 "freq", 579 "freq",
533 "inherit_stat", 580 "inherit_stat",
@@ -553,6 +600,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
553 exclude_hv = 0, 600 exclude_hv = 0,
554 exclude_idle = 0, 601 exclude_idle = 0,
555 mmap = 0, 602 mmap = 0,
603 context_switch = 0,
556 comm = 0, 604 comm = 0,
557 freq = 1, 605 freq = 1,
558 inherit_stat = 0, 606 inherit_stat = 0,
@@ -565,13 +613,13 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
565 int idx = 0; 613 int idx = 0;
566 614
567 if (!PyArg_ParseTupleAndKeywords(args, kwargs, 615 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
568 "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist, 616 "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
569 &attr.type, &attr.config, &attr.sample_freq, 617 &attr.type, &attr.config, &attr.sample_freq,
570 &sample_period, &attr.sample_type, 618 &sample_period, &attr.sample_type,
571 &attr.read_format, &disabled, &inherit, 619 &attr.read_format, &disabled, &inherit,
572 &pinned, &exclusive, &exclude_user, 620 &pinned, &exclusive, &exclude_user,
573 &exclude_kernel, &exclude_hv, &exclude_idle, 621 &exclude_kernel, &exclude_hv, &exclude_idle,
574 &mmap, &comm, &freq, &inherit_stat, 622 &mmap, &context_switch, &comm, &freq, &inherit_stat,
575 &enable_on_exec, &task, &watermark, 623 &enable_on_exec, &task, &watermark,
576 &precise_ip, &mmap_data, &sample_id_all, 624 &precise_ip, &mmap_data, &sample_id_all,
577 &attr.wakeup_events, &attr.bp_type, 625 &attr.wakeup_events, &attr.bp_type,
@@ -595,6 +643,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
595 attr.exclude_hv = exclude_hv; 643 attr.exclude_hv = exclude_hv;
596 attr.exclude_idle = exclude_idle; 644 attr.exclude_idle = exclude_idle;
597 attr.mmap = mmap; 645 attr.mmap = mmap;
646 attr.context_switch = context_switch;
598 attr.comm = comm; 647 attr.comm = comm;
599 attr.freq = freq; 648 attr.freq = freq;
600 attr.inherit_stat = inherit_stat; 649 attr.inherit_stat = inherit_stat;
@@ -1019,6 +1068,8 @@ static struct {
1019 PERF_CONST(RECORD_LOST_SAMPLES), 1068 PERF_CONST(RECORD_LOST_SAMPLES),
1020 PERF_CONST(RECORD_SWITCH), 1069 PERF_CONST(RECORD_SWITCH),
1021 PERF_CONST(RECORD_SWITCH_CPU_WIDE), 1070 PERF_CONST(RECORD_SWITCH_CPU_WIDE),
1071
1072 PERF_CONST(RECORD_MISC_SWITCH_OUT),
1022 { .name = NULL, }, 1073 { .name = NULL, },
1023}; 1074};
1024 1075
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 1bd593bbf7a5..544509c159ce 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -221,6 +221,7 @@ static void define_event_symbols(struct event_format *event,
221 break; 221 break;
222 case PRINT_BSTRING: 222 case PRINT_BSTRING:
223 case PRINT_DYNAMIC_ARRAY: 223 case PRINT_DYNAMIC_ARRAY:
224 case PRINT_DYNAMIC_ARRAY_LEN:
224 case PRINT_STRING: 225 case PRINT_STRING:
225 case PRINT_BITMASK: 226 case PRINT_BITMASK:
226 break; 227 break;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index ace2484985cb..a8e825fca42a 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -251,6 +251,7 @@ static void define_event_symbols(struct event_format *event,
251 /* gcc warns for these? */ 251 /* gcc warns for these? */
252 case PRINT_BSTRING: 252 case PRINT_BSTRING:
253 case PRINT_DYNAMIC_ARRAY: 253 case PRINT_DYNAMIC_ARRAY:
254 case PRINT_DYNAMIC_ARRAY_LEN:
254 case PRINT_FUNC: 255 case PRINT_FUNC:
255 case PRINT_BITMASK: 256 case PRINT_BITMASK:
256 /* we should warn... */ 257 /* we should warn... */
@@ -318,7 +319,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
318 319
319 if (thread__resolve_callchain(al->thread, evsel, 320 if (thread__resolve_callchain(al->thread, evsel,
320 sample, NULL, NULL, 321 sample, NULL, NULL,
321 PERF_MAX_STACK_DEPTH) != 0) { 322 scripting_max_stack) != 0) {
322 pr_err("Failed to resolve callchain. Skipping\n"); 323 pr_err("Failed to resolve callchain. Skipping\n");
323 goto exit; 324 goto exit;
324 } 325 }
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index fc3f7c922f99..c35ffdd360fe 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -29,7 +29,7 @@ static int perf_session__open(struct perf_session *session)
29 struct perf_data_file *file = session->file; 29 struct perf_data_file *file = session->file;
30 30
31 if (perf_session__read_header(session) < 0) { 31 if (perf_session__read_header(session) < 0) {
32 pr_err("incompatible file format (rerun with -v to learn more)"); 32 pr_err("incompatible file format (rerun with -v to learn more)\n");
33 return -1; 33 return -1;
34 } 34 }
35 35
@@ -37,17 +37,17 @@ static int perf_session__open(struct perf_session *session)
37 return 0; 37 return 0;
38 38
39 if (!perf_evlist__valid_sample_type(session->evlist)) { 39 if (!perf_evlist__valid_sample_type(session->evlist)) {
40 pr_err("non matching sample_type"); 40 pr_err("non matching sample_type\n");
41 return -1; 41 return -1;
42 } 42 }
43 43
44 if (!perf_evlist__valid_sample_id_all(session->evlist)) { 44 if (!perf_evlist__valid_sample_id_all(session->evlist)) {
45 pr_err("non matching sample_id_all"); 45 pr_err("non matching sample_id_all\n");
46 return -1; 46 return -1;
47 } 47 }
48 48
49 if (!perf_evlist__valid_read_format(session->evlist)) { 49 if (!perf_evlist__valid_read_format(session->evlist)) {
50 pr_err("non matching read_format"); 50 pr_err("non matching read_format\n");
51 return -1; 51 return -1;
52 } 52 }
53 53
@@ -138,6 +138,8 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
138 perf_session__set_id_hdr_size(session); 138 perf_session__set_id_hdr_size(session);
139 perf_session__set_comm_exec(session); 139 perf_session__set_comm_exec(session);
140 } 140 }
141 } else {
142 session->machines.host.env = &perf_env;
141 } 143 }
142 144
143 if (!file || perf_data_file__is_write(file)) { 145 if (!file || perf_data_file__is_write(file)) {
@@ -170,30 +172,13 @@ static void perf_session__delete_threads(struct perf_session *session)
170 machine__delete_threads(&session->machines.host); 172 machine__delete_threads(&session->machines.host);
171} 173}
172 174
173static void perf_session_env__exit(struct perf_env *env)
174{
175 zfree(&env->hostname);
176 zfree(&env->os_release);
177 zfree(&env->version);
178 zfree(&env->arch);
179 zfree(&env->cpu_desc);
180 zfree(&env->cpuid);
181
182 zfree(&env->cmdline);
183 zfree(&env->cmdline_argv);
184 zfree(&env->sibling_cores);
185 zfree(&env->sibling_threads);
186 zfree(&env->numa_nodes);
187 zfree(&env->pmu_mappings);
188}
189
190void perf_session__delete(struct perf_session *session) 175void perf_session__delete(struct perf_session *session)
191{ 176{
192 auxtrace__free(session); 177 auxtrace__free(session);
193 auxtrace_index__free(&session->auxtrace_index); 178 auxtrace_index__free(&session->auxtrace_index);
194 perf_session__destroy_kernel_maps(session); 179 perf_session__destroy_kernel_maps(session);
195 perf_session__delete_threads(session); 180 perf_session__delete_threads(session);
196 perf_session_env__exit(&session->header.env); 181 perf_env__exit(&session->header.env);
197 machines__exit(&session->machines); 182 machines__exit(&session->machines);
198 if (session->file) 183 if (session->file)
199 perf_data_file__close(session->file); 184 perf_data_file__close(session->file);
@@ -1079,11 +1064,11 @@ static int machines__deliver_event(struct machines *machines,
1079 1064
1080 switch (event->header.type) { 1065 switch (event->header.type) {
1081 case PERF_RECORD_SAMPLE: 1066 case PERF_RECORD_SAMPLE:
1082 dump_sample(evsel, event, sample);
1083 if (evsel == NULL) { 1067 if (evsel == NULL) {
1084 ++evlist->stats.nr_unknown_id; 1068 ++evlist->stats.nr_unknown_id;
1085 return 0; 1069 return 0;
1086 } 1070 }
1071 dump_sample(evsel, event, sample);
1087 if (machine == NULL) { 1072 if (machine == NULL) {
1088 ++evlist->stats.nr_unprocessable_samples; 1073 ++evlist->stats.nr_unprocessable_samples;
1089 return 0; 1074 return 0;
@@ -1116,6 +1101,9 @@ static int machines__deliver_event(struct machines *machines,
1116 case PERF_RECORD_UNTHROTTLE: 1101 case PERF_RECORD_UNTHROTTLE:
1117 return tool->unthrottle(tool, event, sample, machine); 1102 return tool->unthrottle(tool, event, sample, machine);
1118 case PERF_RECORD_AUX: 1103 case PERF_RECORD_AUX:
1104 if (tool->aux == perf_event__process_aux &&
1105 (event->aux.flags & PERF_AUX_FLAG_TRUNCATED))
1106 evlist->stats.total_aux_lost += 1;
1119 return tool->aux(tool, event, sample, machine); 1107 return tool->aux(tool, event, sample, machine);
1120 case PERF_RECORD_ITRACE_START: 1108 case PERF_RECORD_ITRACE_START:
1121 return tool->itrace_start(tool, event, sample, machine); 1109 return tool->itrace_start(tool, event, sample, machine);
@@ -1323,7 +1311,7 @@ struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
1323 return machine__findnew_thread(&session->machines.host, -1, pid); 1311 return machine__findnew_thread(&session->machines.host, -1, pid);
1324} 1312}
1325 1313
1326static struct thread *perf_session__register_idle_thread(struct perf_session *session) 1314struct thread *perf_session__register_idle_thread(struct perf_session *session)
1327{ 1315{
1328 struct thread *thread; 1316 struct thread *thread;
1329 1317
@@ -1361,6 +1349,13 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1361 } 1349 }
1362 } 1350 }
1363 1351
1352 if (session->tool->aux == perf_event__process_aux &&
1353 stats->total_aux_lost != 0) {
1354 ui__warning("AUX data lost %" PRIu64 " times out of %u!\n\n",
1355 stats->total_aux_lost,
1356 stats->nr_events[PERF_RECORD_AUX]);
1357 }
1358
1364 if (stats->nr_unknown_events != 0) { 1359 if (stats->nr_unknown_events != 0) {
1365 ui__warning("Found %u unknown events!\n\n" 1360 ui__warning("Found %u unknown events!\n\n"
1366 "Is this an older tool processing a perf.data " 1361 "Is this an older tool processing a perf.data "
@@ -1805,7 +1800,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1805 1800
1806 if (thread__resolve_callchain(al->thread, evsel, 1801 if (thread__resolve_callchain(al->thread, evsel,
1807 sample, NULL, NULL, 1802 sample, NULL, NULL,
1808 PERF_MAX_STACK_DEPTH) != 0) { 1803 stack_depth) != 0) {
1809 if (verbose) 1804 if (verbose)
1810 error("Failed to resolve callchain. Skipping\n"); 1805 error("Failed to resolve callchain. Skipping\n");
1811 return; 1806 return;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index b44afc75d1cc..3e900c0efc73 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -89,6 +89,8 @@ struct machine *perf_session__findnew_machine(struct perf_session *session, pid_
89} 89}
90 90
91struct thread *perf_session__findnew(struct perf_session *session, pid_t pid); 91struct thread *perf_session__findnew(struct perf_session *session, pid_t pid);
92struct thread *perf_session__register_idle_thread(struct perf_session *session);
93
92size_t perf_session__fprintf(struct perf_session *session, FILE *fp); 94size_t perf_session__fprintf(struct perf_session *session, FILE *fp);
93 95
94size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp); 96size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 7e3871606df3..2d8ccd4d9e1b 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -21,6 +21,7 @@ int sort__need_collapse = 0;
21int sort__has_parent = 0; 21int sort__has_parent = 0;
22int sort__has_sym = 0; 22int sort__has_sym = 0;
23int sort__has_dso = 0; 23int sort__has_dso = 0;
24int sort__has_socket = 0;
24enum sort_mode sort__mode = SORT_MODE__NORMAL; 25enum sort_mode sort__mode = SORT_MODE__NORMAL;
25 26
26 27
@@ -328,8 +329,8 @@ static char *get_srcfile(struct hist_entry *e)
328 char *sf, *p; 329 char *sf, *p;
329 struct map *map = e->ms.map; 330 struct map *map = e->ms.map;
330 331
331 sf = get_srcline(map->dso, map__rip_2objdump(map, e->ip), 332 sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
332 e->ms.sym, true); 333 e->ms.sym, false, true);
333 if (!strcmp(sf, SRCLINE_UNKNOWN)) 334 if (!strcmp(sf, SRCLINE_UNKNOWN))
334 return no_srcfile; 335 return no_srcfile;
335 p = strchr(sf, ':'); 336 p = strchr(sf, ':');
@@ -421,6 +422,27 @@ struct sort_entry sort_cpu = {
421 .se_width_idx = HISTC_CPU, 422 .se_width_idx = HISTC_CPU,
422}; 423};
423 424
425/* --sort socket */
426
427static int64_t
428sort__socket_cmp(struct hist_entry *left, struct hist_entry *right)
429{
430 return right->socket - left->socket;
431}
432
433static int hist_entry__socket_snprintf(struct hist_entry *he, char *bf,
434 size_t size, unsigned int width)
435{
436 return repsep_snprintf(bf, size, "%*.*d", width, width-3, he->socket);
437}
438
439struct sort_entry sort_socket = {
440 .se_header = "Socket",
441 .se_cmp = sort__socket_cmp,
442 .se_snprintf = hist_entry__socket_snprintf,
443 .se_width_idx = HISTC_SOCKET,
444};
445
424/* sort keys for branch stacks */ 446/* sort keys for branch stacks */
425 447
426static int64_t 448static int64_t
@@ -633,6 +655,35 @@ static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
633} 655}
634 656
635static int64_t 657static int64_t
658sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right)
659{
660 uint64_t l = 0, r = 0;
661
662 if (left->mem_info)
663 l = left->mem_info->iaddr.addr;
664 if (right->mem_info)
665 r = right->mem_info->iaddr.addr;
666
667 return (int64_t)(r - l);
668}
669
670static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf,
671 size_t size, unsigned int width)
672{
673 uint64_t addr = 0;
674 struct map *map = NULL;
675 struct symbol *sym = NULL;
676
677 if (he->mem_info) {
678 addr = he->mem_info->iaddr.addr;
679 map = he->mem_info->iaddr.map;
680 sym = he->mem_info->iaddr.sym;
681 }
682 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
683 width);
684}
685
686static int64_t
636sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) 687sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
637{ 688{
638 struct map *map_l = NULL; 689 struct map *map_l = NULL;
@@ -1055,6 +1106,13 @@ struct sort_entry sort_mem_daddr_sym = {
1055 .se_width_idx = HISTC_MEM_DADDR_SYMBOL, 1106 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
1056}; 1107};
1057 1108
1109struct sort_entry sort_mem_iaddr_sym = {
1110 .se_header = "Code Symbol",
1111 .se_cmp = sort__iaddr_cmp,
1112 .se_snprintf = hist_entry__iaddr_snprintf,
1113 .se_width_idx = HISTC_MEM_IADDR_SYMBOL,
1114};
1115
1058struct sort_entry sort_mem_daddr_dso = { 1116struct sort_entry sort_mem_daddr_dso = {
1059 .se_header = "Data Object", 1117 .se_header = "Data Object",
1060 .se_cmp = sort__dso_daddr_cmp, 1118 .se_cmp = sort__dso_daddr_cmp,
@@ -1248,6 +1306,7 @@ static struct sort_dimension common_sort_dimensions[] = {
1248 DIM(SORT_SYM, "symbol", sort_sym), 1306 DIM(SORT_SYM, "symbol", sort_sym),
1249 DIM(SORT_PARENT, "parent", sort_parent), 1307 DIM(SORT_PARENT, "parent", sort_parent),
1250 DIM(SORT_CPU, "cpu", sort_cpu), 1308 DIM(SORT_CPU, "cpu", sort_cpu),
1309 DIM(SORT_SOCKET, "socket", sort_socket),
1251 DIM(SORT_SRCLINE, "srcline", sort_srcline), 1310 DIM(SORT_SRCLINE, "srcline", sort_srcline),
1252 DIM(SORT_SRCFILE, "srcfile", sort_srcfile), 1311 DIM(SORT_SRCFILE, "srcfile", sort_srcfile),
1253 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), 1312 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
@@ -1276,6 +1335,7 @@ static struct sort_dimension bstack_sort_dimensions[] = {
1276 1335
1277static struct sort_dimension memory_sort_dimensions[] = { 1336static struct sort_dimension memory_sort_dimensions[] = {
1278 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym), 1337 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
1338 DIM(SORT_MEM_IADDR_SYMBOL, "symbol_iaddr", sort_mem_iaddr_sym),
1279 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso), 1339 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
1280 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked), 1340 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
1281 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb), 1341 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
@@ -1517,6 +1577,12 @@ static int __hpp_dimension__add_output(struct hpp_dimension *hd)
1517 return 0; 1577 return 0;
1518} 1578}
1519 1579
1580int hpp_dimension__add_output(unsigned col)
1581{
1582 BUG_ON(col >= PERF_HPP__MAX_INDEX);
1583 return __hpp_dimension__add_output(&hpp_sort_dimensions[col]);
1584}
1585
1520int sort_dimension__add(const char *tok) 1586int sort_dimension__add(const char *tok)
1521{ 1587{
1522 unsigned int i; 1588 unsigned int i;
@@ -1550,6 +1616,8 @@ int sort_dimension__add(const char *tok)
1550 1616
1551 } else if (sd->entry == &sort_dso) { 1617 } else if (sd->entry == &sort_dso) {
1552 sort__has_dso = 1; 1618 sort__has_dso = 1;
1619 } else if (sd->entry == &sort_socket) {
1620 sort__has_socket = 1;
1553 } 1621 }
1554 1622
1555 return __sort_dimension__add(sd); 1623 return __sort_dimension__add(sd);
@@ -1855,8 +1923,6 @@ static int __setup_output_field(void)
1855 if (field_order == NULL) 1923 if (field_order == NULL)
1856 return 0; 1924 return 0;
1857 1925
1858 reset_dimensions();
1859
1860 strp = str = strdup(field_order); 1926 strp = str = strdup(field_order);
1861 if (str == NULL) { 1927 if (str == NULL) {
1862 error("Not enough memory to setup output fields"); 1928 error("Not enough memory to setup output fields");
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 3c2a399f8f5b..31228851e397 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -34,6 +34,7 @@ extern int have_ignore_callees;
34extern int sort__need_collapse; 34extern int sort__need_collapse;
35extern int sort__has_parent; 35extern int sort__has_parent;
36extern int sort__has_sym; 36extern int sort__has_sym;
37extern int sort__has_socket;
37extern enum sort_mode sort__mode; 38extern enum sort_mode sort__mode;
38extern struct sort_entry sort_comm; 39extern struct sort_entry sort_comm;
39extern struct sort_entry sort_dso; 40extern struct sort_entry sort_dso;
@@ -90,6 +91,7 @@ struct hist_entry {
90 struct comm *comm; 91 struct comm *comm;
91 u64 ip; 92 u64 ip;
92 u64 transaction; 93 u64 transaction;
94 s32 socket;
93 s32 cpu; 95 s32 cpu;
94 u8 cpumode; 96 u8 cpumode;
95 97
@@ -172,6 +174,7 @@ enum sort_type {
172 SORT_SYM, 174 SORT_SYM,
173 SORT_PARENT, 175 SORT_PARENT,
174 SORT_CPU, 176 SORT_CPU,
177 SORT_SOCKET,
175 SORT_SRCLINE, 178 SORT_SRCLINE,
176 SORT_SRCFILE, 179 SORT_SRCFILE,
177 SORT_LOCAL_WEIGHT, 180 SORT_LOCAL_WEIGHT,
@@ -198,6 +201,7 @@ enum sort_type {
198 SORT_MEM_LVL, 201 SORT_MEM_LVL,
199 SORT_MEM_SNOOP, 202 SORT_MEM_SNOOP,
200 SORT_MEM_DCACHELINE, 203 SORT_MEM_DCACHELINE,
204 SORT_MEM_IADDR_SYMBOL,
201}; 205};
202 206
203/* 207/*
@@ -230,4 +234,6 @@ void perf_hpp__set_elide(int idx, bool elide);
230int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); 234int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);
231 235
232bool is_strict_order(const char *order); 236bool is_strict_order(const char *order);
237
238int hpp_dimension__add_output(unsigned col);
233#endif /* __PERF_SORT_H */ 239#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index fc08248f08ca..b4db3f48e3b0 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -149,8 +149,11 @@ static void addr2line_cleanup(struct a2l_data *a2l)
149 free(a2l); 149 free(a2l);
150} 150}
151 151
152#define MAX_INLINE_NEST 1024
153
152static int addr2line(const char *dso_name, u64 addr, 154static int addr2line(const char *dso_name, u64 addr,
153 char **file, unsigned int *line, struct dso *dso) 155 char **file, unsigned int *line, struct dso *dso,
156 bool unwind_inlines)
154{ 157{
155 int ret = 0; 158 int ret = 0;
156 struct a2l_data *a2l = dso->a2l; 159 struct a2l_data *a2l = dso->a2l;
@@ -170,6 +173,15 @@ static int addr2line(const char *dso_name, u64 addr,
170 173
171 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); 174 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
172 175
176 if (a2l->found && unwind_inlines) {
177 int cnt = 0;
178
179 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
180 &a2l->funcname, &a2l->line) &&
181 cnt++ < MAX_INLINE_NEST)
182 ;
183 }
184
173 if (a2l->found && a2l->filename) { 185 if (a2l->found && a2l->filename) {
174 *file = strdup(a2l->filename); 186 *file = strdup(a2l->filename);
175 *line = a2l->line; 187 *line = a2l->line;
@@ -197,7 +209,8 @@ void dso__free_a2l(struct dso *dso)
197 209
198static int addr2line(const char *dso_name, u64 addr, 210static int addr2line(const char *dso_name, u64 addr,
199 char **file, unsigned int *line_nr, 211 char **file, unsigned int *line_nr,
200 struct dso *dso __maybe_unused) 212 struct dso *dso __maybe_unused,
213 bool unwind_inlines __maybe_unused)
201{ 214{
202 FILE *fp; 215 FILE *fp;
203 char cmd[PATH_MAX]; 216 char cmd[PATH_MAX];
@@ -254,8 +267,8 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
254 */ 267 */
255#define A2L_FAIL_LIMIT 123 268#define A2L_FAIL_LIMIT 123
256 269
257char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 270char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
258 bool show_sym) 271 bool show_sym, bool unwind_inlines)
259{ 272{
260 char *file = NULL; 273 char *file = NULL;
261 unsigned line = 0; 274 unsigned line = 0;
@@ -276,7 +289,7 @@ char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
276 if (!strncmp(dso_name, "/tmp/perf-", 10)) 289 if (!strncmp(dso_name, "/tmp/perf-", 10))
277 goto out; 290 goto out;
278 291
279 if (!addr2line(dso_name, addr, &file, &line, dso)) 292 if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines))
280 goto out; 293 goto out;
281 294
282 if (asprintf(&srcline, "%s:%u", 295 if (asprintf(&srcline, "%s:%u",
@@ -310,3 +323,9 @@ void free_srcline(char *srcline)
310 if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0) 323 if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
311 free(srcline); 324 free(srcline);
312} 325}
326
327char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
328 bool show_sym)
329{
330 return __get_srcline(dso, addr, sym, show_sym, false);
331}
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 2a5d8d7698ae..6ac03146889d 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -413,6 +413,11 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
413 ratio = total / avg; 413 ratio = total / avg;
414 414
415 fprintf(out, " # %8.0f cycles / elision ", ratio); 415 fprintf(out, " # %8.0f cycles / elision ", ratio);
416 } else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) {
417 if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
418 fprintf(out, " # %8.3f CPUs utilized ", avg / ratio);
419 else
420 fprintf(out, " ");
416 } else if (runtime_nsecs_stats[cpu].n != 0) { 421 } else if (runtime_nsecs_stats[cpu].n != 0) {
417 char unit = 'M'; 422 char unit = 'M';
418 423
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 2d065d065b67..2d9d8306dbd3 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -67,7 +67,7 @@ double rel_stddev_stats(double stddev, double avg)
67bool __perf_evsel_stat__is(struct perf_evsel *evsel, 67bool __perf_evsel_stat__is(struct perf_evsel *evsel,
68 enum perf_stat_evsel_id id) 68 enum perf_stat_evsel_id id)
69{ 69{
70 struct perf_stat *ps = evsel->priv; 70 struct perf_stat_evsel *ps = evsel->priv;
71 71
72 return ps->id == id; 72 return ps->id == id;
73} 73}
@@ -84,7 +84,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
84 84
85void perf_stat_evsel_id_init(struct perf_evsel *evsel) 85void perf_stat_evsel_id_init(struct perf_evsel *evsel)
86{ 86{
87 struct perf_stat *ps = evsel->priv; 87 struct perf_stat_evsel *ps = evsel->priv;
88 int i; 88 int i;
89 89
90 /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */ 90 /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
@@ -100,7 +100,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
100void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) 100void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
101{ 101{
102 int i; 102 int i;
103 struct perf_stat *ps = evsel->priv; 103 struct perf_stat_evsel *ps = evsel->priv;
104 104
105 for (i = 0; i < 3; i++) 105 for (i = 0; i < 3; i++)
106 init_stats(&ps->res_stats[i]); 106 init_stats(&ps->res_stats[i]);
@@ -110,7 +110,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
110 110
111int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 111int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
112{ 112{
113 evsel->priv = zalloc(sizeof(struct perf_stat)); 113 evsel->priv = zalloc(sizeof(struct perf_stat_evsel));
114 if (evsel->priv == NULL) 114 if (evsel->priv == NULL)
115 return -ENOMEM; 115 return -ENOMEM;
116 perf_evsel__reset_stat_priv(evsel); 116 perf_evsel__reset_stat_priv(evsel);
@@ -230,7 +230,7 @@ static int check_per_pkg(struct perf_evsel *counter,
230 if (!(vals->run && vals->ena)) 230 if (!(vals->run && vals->ena))
231 return 0; 231 return 0;
232 232
233 s = cpu_map__get_socket(cpus, cpu); 233 s = cpu_map__get_socket(cpus, cpu, NULL);
234 if (s < 0) 234 if (s < 0)
235 return -1; 235 return -1;
236 236
@@ -272,6 +272,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
272 aggr->ena += count->ena; 272 aggr->ena += count->ena;
273 aggr->run += count->run; 273 aggr->run += count->run;
274 } 274 }
275 case AGGR_UNSET:
275 default: 276 default:
276 break; 277 break;
277 } 278 }
@@ -304,7 +305,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
304 struct perf_evsel *counter) 305 struct perf_evsel *counter)
305{ 306{
306 struct perf_counts_values *aggr = &counter->counts->aggr; 307 struct perf_counts_values *aggr = &counter->counts->aggr;
307 struct perf_stat *ps = counter->priv; 308 struct perf_stat_evsel *ps = counter->priv;
308 u64 *count = counter->counts->aggr.values; 309 u64 *count = counter->counts->aggr.values;
309 int i, ret; 310 int i, ret;
310 311
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 62448c8175d3..da1d11c4f8c1 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -20,7 +20,7 @@ enum perf_stat_evsel_id {
20 PERF_STAT_EVSEL_ID__MAX, 20 PERF_STAT_EVSEL_ID__MAX,
21}; 21};
22 22
23struct perf_stat { 23struct perf_stat_evsel {
24 struct stats res_stats[3]; 24 struct stats res_stats[3];
25 enum perf_stat_evsel_id id; 25 enum perf_stat_evsel_id id;
26}; 26};
@@ -31,6 +31,7 @@ enum aggr_mode {
31 AGGR_SOCKET, 31 AGGR_SOCKET,
32 AGGR_CORE, 32 AGGR_CORE,
33 AGGR_THREAD, 33 AGGR_THREAD,
34 AGGR_UNSET,
34}; 35};
35 36
36struct perf_stat_config { 37struct perf_stat_config {
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 4abe23550c73..25671fa16618 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -82,23 +82,22 @@ void strbuf_add(struct strbuf *sb, const void *data, size_t len)
82 strbuf_setlen(sb, sb->len + len); 82 strbuf_setlen(sb, sb->len + len);
83} 83}
84 84
85void strbuf_addf(struct strbuf *sb, const char *fmt, ...) 85void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
86{ 86{
87 int len; 87 int len;
88 va_list ap; 88 va_list ap_saved;
89 89
90 if (!strbuf_avail(sb)) 90 if (!strbuf_avail(sb))
91 strbuf_grow(sb, 64); 91 strbuf_grow(sb, 64);
92 va_start(ap, fmt); 92
93 va_copy(ap_saved, ap);
93 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 94 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
94 va_end(ap);
95 if (len < 0) 95 if (len < 0)
96 die("your vsnprintf is broken"); 96 die("your vsnprintf is broken");
97 if (len > strbuf_avail(sb)) { 97 if (len > strbuf_avail(sb)) {
98 strbuf_grow(sb, len); 98 strbuf_grow(sb, len);
99 va_start(ap, fmt); 99 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
100 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 100 va_end(ap_saved);
101 va_end(ap);
102 if (len > strbuf_avail(sb)) { 101 if (len > strbuf_avail(sb)) {
103 die("this should not happen, your vsnprintf is broken"); 102 die("this should not happen, your vsnprintf is broken");
104 } 103 }
@@ -106,6 +105,15 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
106 strbuf_setlen(sb, sb->len + len); 105 strbuf_setlen(sb, sb->len + len);
107} 106}
108 107
108void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
109{
110 va_list ap;
111
112 va_start(ap, fmt);
113 strbuf_addv(sb, fmt, ap);
114 va_end(ap);
115}
116
109ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) 117ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
110{ 118{
111 size_t oldlen = sb->len; 119 size_t oldlen = sb->len;
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index 436ac319f6c7..529f2f035249 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -39,6 +39,7 @@
39 */ 39 */
40 40
41#include <assert.h> 41#include <assert.h>
42#include <stdarg.h>
42 43
43extern char strbuf_slopbuf[]; 44extern char strbuf_slopbuf[];
44struct strbuf { 45struct strbuf {
@@ -85,6 +86,7 @@ static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
85 86
86__attribute__((format(printf,2,3))) 87__attribute__((format(printf,2,3)))
87extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); 88extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
89extern void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap);
88 90
89/* XXX: if read fails, any partial read is undone */ 91/* XXX: if read fails, any partial read is undone */
90extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); 92extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index fd8477cacf88..48906333a858 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -337,7 +337,7 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
337 symbol_filter_t filter __maybe_unused, 337 symbol_filter_t filter __maybe_unused,
338 int kmodule __maybe_unused) 338 int kmodule __maybe_unused)
339{ 339{
340 unsigned char *build_id[BUILD_ID_SIZE]; 340 unsigned char build_id[BUILD_ID_SIZE];
341 int ret; 341 int ret;
342 342
343 ret = fd__is_64_bit(ss->fd); 343 ret = fd__is_64_bit(ss->fd);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 1f97ffb158a6..cd08027a6d2c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -624,7 +624,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
624 * symbols, setting length to 0, and rely on 624 * symbols, setting length to 0, and rely on
625 * symbols__fixup_end() to fix it up. 625 * symbols__fixup_end() to fix it up.
626 */ 626 */
627 sym = symbol__new(start, 0, kallsyms2elf_type(type), name); 627 sym = symbol__new(start, 0, kallsyms2elf_binding(type), name);
628 if (sym == NULL) 628 if (sym == NULL)
629 return -ENOMEM; 629 return -ENOMEM;
630 /* 630 /*
@@ -654,19 +654,24 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
654 struct map_groups *kmaps = map__kmaps(map); 654 struct map_groups *kmaps = map__kmaps(map);
655 struct map *curr_map; 655 struct map *curr_map;
656 struct symbol *pos; 656 struct symbol *pos;
657 int count = 0, moved = 0; 657 int count = 0;
658 struct rb_root old_root = dso->symbols[map->type];
658 struct rb_root *root = &dso->symbols[map->type]; 659 struct rb_root *root = &dso->symbols[map->type];
659 struct rb_node *next = rb_first(root); 660 struct rb_node *next = rb_first(root);
660 661
661 if (!kmaps) 662 if (!kmaps)
662 return -1; 663 return -1;
663 664
665 *root = RB_ROOT;
666
664 while (next) { 667 while (next) {
665 char *module; 668 char *module;
666 669
667 pos = rb_entry(next, struct symbol, rb_node); 670 pos = rb_entry(next, struct symbol, rb_node);
668 next = rb_next(&pos->rb_node); 671 next = rb_next(&pos->rb_node);
669 672
673 rb_erase_init(&pos->rb_node, &old_root);
674
670 module = strchr(pos->name, '\t'); 675 module = strchr(pos->name, '\t');
671 if (module) 676 if (module)
672 *module = '\0'; 677 *module = '\0';
@@ -674,28 +679,21 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
674 curr_map = map_groups__find(kmaps, map->type, pos->start); 679 curr_map = map_groups__find(kmaps, map->type, pos->start);
675 680
676 if (!curr_map || (filter && filter(curr_map, pos))) { 681 if (!curr_map || (filter && filter(curr_map, pos))) {
677 rb_erase_init(&pos->rb_node, root);
678 symbol__delete(pos); 682 symbol__delete(pos);
679 } else { 683 continue;
680 pos->start -= curr_map->start - curr_map->pgoff;
681 if (pos->end)
682 pos->end -= curr_map->start - curr_map->pgoff;
683 if (curr_map != map) {
684 rb_erase_init(&pos->rb_node, root);
685 symbols__insert(
686 &curr_map->dso->symbols[curr_map->type],
687 pos);
688 ++moved;
689 } else {
690 ++count;
691 }
692 } 684 }
685
686 pos->start -= curr_map->start - curr_map->pgoff;
687 if (pos->end)
688 pos->end -= curr_map->start - curr_map->pgoff;
689 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
690 ++count;
693 } 691 }
694 692
695 /* Symbols have been adjusted */ 693 /* Symbols have been adjusted */
696 dso->adjust_symbols = 1; 694 dso->adjust_symbols = 1;
697 695
698 return count + moved; 696 return count;
699} 697}
700 698
701/* 699/*
@@ -1406,6 +1404,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1406 struct symsrc ss_[2]; 1404 struct symsrc ss_[2];
1407 struct symsrc *syms_ss = NULL, *runtime_ss = NULL; 1405 struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
1408 bool kmod; 1406 bool kmod;
1407 unsigned char build_id[BUILD_ID_SIZE];
1409 1408
1410 pthread_mutex_lock(&dso->lock); 1409 pthread_mutex_lock(&dso->lock);
1411 1410
@@ -1437,9 +1436,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1437 if (lstat(dso->name, &st) < 0) 1436 if (lstat(dso->name, &st) < 0)
1438 goto out; 1437 goto out;
1439 1438
1440 if (st.st_uid && (st.st_uid != geteuid())) { 1439 if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) {
1441 pr_warning("File %s not owned by current user or root, " 1440 pr_warning("File %s not owned by current user or root, "
1442 "ignoring it.\n", dso->name); 1441 "ignoring it (use -f to override).\n", dso->name);
1443 goto out; 1442 goto out;
1444 } 1443 }
1445 1444
@@ -1461,6 +1460,14 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1461 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || 1460 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE ||
1462 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; 1461 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
1463 1462
1463
1464 /*
1465 * Read the build id if possible. This is required for
1466 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
1467 */
1468 if (filename__read_build_id(dso->name, build_id, BUILD_ID_SIZE) > 0)
1469 dso__set_build_id(dso, build_id);
1470
1464 /* 1471 /*
1465 * Iterate over candidate debug images. 1472 * Iterate over candidate debug images.
1466 * Keep track of "interesting" ones (those which have a symtab, dynsym, 1473 * Keep track of "interesting" ones (those which have a symtab, dynsym,
@@ -1607,6 +1614,15 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1607 int i, err = 0; 1614 int i, err = 0;
1608 char *filename = NULL; 1615 char *filename = NULL;
1609 1616
1617 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1618 vmlinux_path__nr_entries + 1);
1619
1620 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1621 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
1622 if (err > 0)
1623 goto out;
1624 }
1625
1610 if (!symbol_conf.ignore_vmlinux_buildid) 1626 if (!symbol_conf.ignore_vmlinux_buildid)
1611 filename = dso__build_id_filename(dso, NULL, 0); 1627 filename = dso__build_id_filename(dso, NULL, 0);
1612 if (filename != NULL) { 1628 if (filename != NULL) {
@@ -1615,15 +1631,6 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1615 goto out; 1631 goto out;
1616 free(filename); 1632 free(filename);
1617 } 1633 }
1618
1619 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1620 vmlinux_path__nr_entries + 1);
1621
1622 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1623 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
1624 if (err > 0)
1625 break;
1626 }
1627out: 1634out:
1628 return err; 1635 return err;
1629} 1636}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 440ba8ae888f..dcd786e364f2 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -84,6 +84,7 @@ struct symbol_conf {
84 unsigned short priv_size; 84 unsigned short priv_size;
85 unsigned short nr_events; 85 unsigned short nr_events;
86 bool try_vmlinux_path, 86 bool try_vmlinux_path,
87 force,
87 ignore_vmlinux, 88 ignore_vmlinux,
88 ignore_vmlinux_buildid, 89 ignore_vmlinux_buildid,
89 show_kernel_path, 90 show_kernel_path,
@@ -191,6 +192,7 @@ struct addr_location {
191 u8 filtered; 192 u8 filtered;
192 u8 cpumode; 193 u8 cpumode;
193 s32 cpu; 194 s32 cpu;
195 s32 socket;
194}; 196};
195 197
196struct symsrc { 198struct symsrc {
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 22245986e59e..d995743cb673 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -38,7 +38,7 @@
38 38
39#include "../perf.h" 39#include "../perf.h"
40#include "trace-event.h" 40#include "trace-event.h"
41#include <api/fs/debugfs.h> 41#include <api/fs/tracing_path.h>
42#include "evsel.h" 42#include "evsel.h"
43#include "debug.h" 43#include "debug.h"
44 44
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index b90e646c7a91..802bb868d446 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -7,7 +7,9 @@
7#include <sys/stat.h> 7#include <sys/stat.h>
8#include <fcntl.h> 8#include <fcntl.h>
9#include <linux/kernel.h> 9#include <linux/kernel.h>
10#include <linux/err.h>
10#include <traceevent/event-parse.h> 11#include <traceevent/event-parse.h>
12#include <api/fs/tracing_path.h>
11#include "trace-event.h" 13#include "trace-event.h"
12#include "machine.h" 14#include "machine.h"
13#include "util.h" 15#include "util.h"
@@ -65,6 +67,9 @@ void trace_event__cleanup(struct trace_event *t)
65 pevent_free(t->pevent); 67 pevent_free(t->pevent);
66} 68}
67 69
70/*
71 * Returns pointer with encoded error via <linux/err.h> interface.
72 */
68static struct event_format* 73static struct event_format*
69tp_format(const char *sys, const char *name) 74tp_format(const char *sys, const char *name)
70{ 75{
@@ -73,12 +78,14 @@ tp_format(const char *sys, const char *name)
73 char path[PATH_MAX]; 78 char path[PATH_MAX];
74 size_t size; 79 size_t size;
75 char *data; 80 char *data;
81 int err;
76 82
77 scnprintf(path, PATH_MAX, "%s/%s/%s/format", 83 scnprintf(path, PATH_MAX, "%s/%s/%s/format",
78 tracing_events_path, sys, name); 84 tracing_events_path, sys, name);
79 85
80 if (filename__read_str(path, &data, &size)) 86 err = filename__read_str(path, &data, &size);
81 return NULL; 87 if (err)
88 return ERR_PTR(err);
82 89
83 pevent_parse_format(pevent, &event, data, size, sys); 90 pevent_parse_format(pevent, &event, data, size, sys);
84 91
@@ -86,11 +93,14 @@ tp_format(const char *sys, const char *name)
86 return event; 93 return event;
87} 94}
88 95
96/*
97 * Returns pointer with encoded error via <linux/err.h> interface.
98 */
89struct event_format* 99struct event_format*
90trace_event__tp_format(const char *sys, const char *name) 100trace_event__tp_format(const char *sys, const char *name)
91{ 101{
92 if (!tevent_initialized && trace_event__init2()) 102 if (!tevent_initialized && trace_event__init2())
93 return NULL; 103 return ERR_PTR(-ENOMEM);
94 104
95 return tp_format(sys, name); 105 return tp_format(sys, name);
96} 106}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index da6cc4cc2a4f..b85ee55cca0c 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -78,6 +78,8 @@ struct scripting_ops {
78 int (*generate_script) (struct pevent *pevent, const char *outfile); 78 int (*generate_script) (struct pevent *pevent, const char *outfile);
79}; 79};
80 80
81extern unsigned int scripting_max_stack;
82
81int script_spec_register(const char *spec, struct scripting_ops *ops); 83int script_spec_register(const char *spec, struct scripting_ops *ops);
82 84
83void setup_perl_scripting(void); 85void setup_perl_scripting(void);
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 4c00507ee3fd..c83832b555e5 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -330,6 +330,7 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
330 struct map *map; 330 struct map *map;
331 unw_dyn_info_t di; 331 unw_dyn_info_t di;
332 u64 table_data, segbase, fde_count; 332 u64 table_data, segbase, fde_count;
333 int ret = -EINVAL;
333 334
334 map = find_map(ip, ui); 335 map = find_map(ip, ui);
335 if (!map || !map->dso) 336 if (!map || !map->dso)
@@ -348,29 +349,33 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
348 di.u.rti.table_data = map->start + table_data; 349 di.u.rti.table_data = map->start + table_data;
349 di.u.rti.table_len = fde_count * sizeof(struct table_entry) 350 di.u.rti.table_len = fde_count * sizeof(struct table_entry)
350 / sizeof(unw_word_t); 351 / sizeof(unw_word_t);
351 return dwarf_search_unwind_table(as, ip, &di, pi, 352 ret = dwarf_search_unwind_table(as, ip, &di, pi,
352 need_unwind_info, arg); 353 need_unwind_info, arg);
353 } 354 }
354 355
355#ifndef NO_LIBUNWIND_DEBUG_FRAME 356#ifndef NO_LIBUNWIND_DEBUG_FRAME
356 /* Check the .debug_frame section for unwinding info */ 357 /* Check the .debug_frame section for unwinding info */
357 if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { 358 if (ret < 0 &&
359 !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
358 int fd = dso__data_get_fd(map->dso, ui->machine); 360 int fd = dso__data_get_fd(map->dso, ui->machine);
359 int is_exec = elf_is_exec(fd, map->dso->name); 361 int is_exec = elf_is_exec(fd, map->dso->name);
360 unw_word_t base = is_exec ? 0 : map->start; 362 unw_word_t base = is_exec ? 0 : map->start;
363 const char *symfile;
361 364
362 if (fd >= 0) 365 if (fd >= 0)
363 dso__data_put_fd(map->dso); 366 dso__data_put_fd(map->dso);
364 367
368 symfile = map->dso->symsrc_filename ?: map->dso->name;
369
365 memset(&di, 0, sizeof(di)); 370 memset(&di, 0, sizeof(di));
366 if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, 371 if (dwarf_find_debug_frame(0, &di, ip, base, symfile,
367 map->start, map->end)) 372 map->start, map->end))
368 return dwarf_search_unwind_table(as, ip, &di, pi, 373 return dwarf_search_unwind_table(as, ip, &di, pi,
369 need_unwind_info, arg); 374 need_unwind_info, arg);
370 } 375 }
371#endif 376#endif
372 377
373 return -EINVAL; 378 return ret;
374} 379}
375 380
376static int access_fpreg(unw_addr_space_t __maybe_unused as, 381static int access_fpreg(unw_addr_space_t __maybe_unused as,
@@ -461,7 +466,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
461 if (ret) { 466 if (ret) {
462 pr_debug("unwind: access_mem %p not inside range" 467 pr_debug("unwind: access_mem %p not inside range"
463 " 0x%" PRIx64 "-0x%" PRIx64 "\n", 468 " 0x%" PRIx64 "-0x%" PRIx64 "\n",
464 (void *) addr, start, end); 469 (void *) (uintptr_t) addr, start, end);
465 *valp = 0; 470 *valp = 0;
466 return ret; 471 return ret;
467 } 472 }
@@ -471,7 +476,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
471 offset = addr - start; 476 offset = addr - start;
472 *valp = *(unw_word_t *)&stack->data[offset]; 477 *valp = *(unw_word_t *)&stack->data[offset];
473 pr_debug("unwind: access_mem addr %p val %lx, offset %d\n", 478 pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",
474 (void *) addr, (unsigned long)*valp, offset); 479 (void *) (uintptr_t) addr, (unsigned long)*valp, offset);
475 return 0; 480 return 0;
476} 481}
477 482
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index 4007aca8e0ca..6adfa18cdd4e 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -50,6 +50,11 @@ void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN)
50 die_routine = routine; 50 die_routine = routine;
51} 51}
52 52
53void set_warning_routine(void (*routine)(const char *err, va_list params))
54{
55 warn_routine = routine;
56}
57
53void usage(const char *err) 58void usage(const char *err)
54{ 59{
55 usage_routine(err); 60 usage_routine(err);
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index c2cd9bf2348b..47b1e36c7ea0 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -3,6 +3,7 @@
3#include "debug.h" 3#include "debug.h"
4#include <api/fs/fs.h> 4#include <api/fs/fs.h>
5#include <sys/mman.h> 5#include <sys/mman.h>
6#include <sys/utsname.h>
6#ifdef HAVE_BACKTRACE_SUPPORT 7#ifdef HAVE_BACKTRACE_SUPPORT
7#include <execinfo.h> 8#include <execinfo.h>
8#endif 9#endif
@@ -17,7 +18,7 @@
17#include "callchain.h" 18#include "callchain.h"
18 19
19struct callchain_param callchain_param = { 20struct callchain_param callchain_param = {
20 .mode = CHAIN_GRAPH_REL, 21 .mode = CHAIN_GRAPH_ABS,
21 .min_percent = 0.5, 22 .min_percent = 0.5,
22 .order = ORDER_CALLEE, 23 .order = ORDER_CALLEE,
23 .key = CCKEY_FUNCTION 24 .key = CCKEY_FUNCTION
@@ -34,9 +35,6 @@ bool test_attr__enabled;
34bool perf_host = true; 35bool perf_host = true;
35bool perf_guest = false; 36bool perf_guest = false;
36 37
37char tracing_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing";
38char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
39
40void event_attr_init(struct perf_event_attr *attr) 38void event_attr_init(struct perf_event_attr *attr)
41{ 39{
42 if (!perf_host) 40 if (!perf_host)
@@ -390,73 +388,6 @@ void set_term_quiet_input(struct termios *old)
390 tcsetattr(0, TCSANOW, &tc); 388 tcsetattr(0, TCSANOW, &tc);
391} 389}
392 390
393static void set_tracing_events_path(const char *tracing, const char *mountpoint)
394{
395 snprintf(tracing_path, sizeof(tracing_path), "%s/%s",
396 mountpoint, tracing);
397 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
398 mountpoint, tracing, "events");
399}
400
401static const char *__perf_tracefs_mount(const char *mountpoint)
402{
403 const char *mnt;
404
405 mnt = tracefs_mount(mountpoint);
406 if (!mnt)
407 return NULL;
408
409 set_tracing_events_path("", mnt);
410
411 return mnt;
412}
413
414static const char *__perf_debugfs_mount(const char *mountpoint)
415{
416 const char *mnt;
417
418 mnt = debugfs_mount(mountpoint);
419 if (!mnt)
420 return NULL;
421
422 set_tracing_events_path("tracing/", mnt);
423
424 return mnt;
425}
426
427const char *perf_debugfs_mount(const char *mountpoint)
428{
429 const char *mnt;
430
431 mnt = __perf_tracefs_mount(mountpoint);
432 if (mnt)
433 return mnt;
434
435 mnt = __perf_debugfs_mount(mountpoint);
436
437 return mnt;
438}
439
440void perf_debugfs_set_path(const char *mntpt)
441{
442 set_tracing_events_path("tracing/", mntpt);
443}
444
445char *get_tracing_file(const char *name)
446{
447 char *file;
448
449 if (asprintf(&file, "%s/%s", tracing_path, name) < 0)
450 return NULL;
451
452 return file;
453}
454
455void put_tracing_file(char *file)
456{
457 free(file);
458}
459
460int parse_nsec_time(const char *str, u64 *ptime) 391int parse_nsec_time(const char *str, u64 *ptime)
461{ 392{
462 u64 time_sec, time_nsec; 393 u64 time_sec, time_nsec;
@@ -735,3 +666,32 @@ bool find_process(const char *name)
735 closedir(dir); 666 closedir(dir);
736 return ret ? false : true; 667 return ret ? false : true;
737} 668}
669
670int
671fetch_kernel_version(unsigned int *puint, char *str,
672 size_t str_size)
673{
674 struct utsname utsname;
675 int version, patchlevel, sublevel, err;
676
677 if (uname(&utsname))
678 return -1;
679
680 if (str && str_size) {
681 strncpy(str, utsname.release, str_size);
682 str[str_size - 1] = '\0';
683 }
684
685 err = sscanf(utsname.release, "%d.%d.%d",
686 &version, &patchlevel, &sublevel);
687
688 if (err != 3) {
689 pr_debug("Unablt to get kernel version from uname '%s'\n",
690 utsname.release);
691 return -1;
692 }
693
694 if (puint)
695 *puint = (version << 16) + (patchlevel << 8) + sublevel;
696 return 0;
697}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 291be1d84bc3..dcc659017976 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -74,8 +74,7 @@
74#include <linux/magic.h> 74#include <linux/magic.h>
75#include <linux/types.h> 75#include <linux/types.h>
76#include <sys/ttydefaults.h> 76#include <sys/ttydefaults.h>
77#include <api/fs/debugfs.h> 77#include <api/fs/tracing_path.h>
78#include <api/fs/tracefs.h>
79#include <termios.h> 78#include <termios.h>
80#include <linux/bitops.h> 79#include <linux/bitops.h>
81#include <termios.h> 80#include <termios.h>
@@ -83,12 +82,6 @@
83extern const char *graph_line; 82extern const char *graph_line;
84extern const char *graph_dotted_line; 83extern const char *graph_dotted_line;
85extern char buildid_dir[]; 84extern char buildid_dir[];
86extern char tracing_path[];
87extern char tracing_events_path[];
88extern void perf_debugfs_set_path(const char *mountpoint);
89const char *perf_debugfs_mount(const char *mountpoint);
90char *get_tracing_file(const char *name);
91void put_tracing_file(char *file);
92 85
93/* On most systems <limits.h> would have given us this, but 86/* On most systems <limits.h> would have given us this, but
94 * not on some systems (e.g. GNU/Hurd). 87 * not on some systems (e.g. GNU/Hurd).
@@ -152,6 +145,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)))
152 145
153 146
154extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); 147extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
148extern void set_warning_routine(void (*routine)(const char *err, va_list params));
155 149
156extern int prefixcmp(const char *str, const char *prefix); 150extern int prefixcmp(const char *str, const char *prefix);
157extern void set_buildid_dir(const char *dir); 151extern void set_buildid_dir(const char *dir);
@@ -321,6 +315,8 @@ struct symbol;
321extern bool srcline_full_filename; 315extern bool srcline_full_filename;
322char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 316char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
323 bool show_sym); 317 bool show_sym);
318char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
319 bool show_sym, bool unwind_inlines);
324void free_srcline(char *srcline); 320void free_srcline(char *srcline);
325 321
326int filename__read_str(const char *filename, char **buf, size_t *sizep); 322int filename__read_str(const char *filename, char **buf, size_t *sizep);
@@ -354,4 +350,12 @@ static inline char *asprintf_expr_not_in_ints(const char *var, size_t nints, int
354 350
355int get_stack_size(const char *str, unsigned long *_size); 351int get_stack_size(const char *str, unsigned long *_size);
356 352
353int fetch_kernel_version(unsigned int *puint,
354 char *str, size_t str_sz);
355#define KVER_VERSION(x) (((x) >> 16) & 0xff)
356#define KVER_PATCHLEVEL(x) (((x) >> 8) & 0xff)
357#define KVER_SUBLEVEL(x) ((x) & 0xff)
358#define KVER_FMT "%d.%d.%d"
359#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
360
357#endif /* GIT_COMPAT_UTIL_H */ 361#endif /* GIT_COMPAT_UTIL_H */